package com.gnx.telemedicine.controller;

import com.gnx.telemedicine.dto.audit.PhiAccessLogResponseDto;
import com.gnx.telemedicine.model.PhiAccessLog;
import com.gnx.telemedicine.service.PhiAccessLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.Instant;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/v3/audit/phi-access")
@RequiredArgsConstructor
@Tag(name = "PHI Access Logs", description = "Endpoints for viewing PHI access logs (Admin only)")
@SecurityRequirement(name = "bearerAuth")
public class PhiAccessLogController {
    
    private final PhiAccessLogService phiAccessLogService;

    @Operation(
            summary = "Get PHI access logs by patient ID",
            description = "Retrieve all PHI access logs for a specific patient. Admin only.",
            parameters = @Parameter(name = "patientId", description = "Patient ID", required = true)
    )
    @ApiResponse(
            responseCode = "200",
            description = "List of PHI access logs retrieved successfully",
            content = @Content(
                    mediaType = "application/json",
                    array = @ArraySchema(schema = @Schema(implementation = PhiAccessLogResponseDto.class))
            )
    )
    @GetMapping("/patient/{patientId}")
    public ResponseEntity<List<PhiAccessLogResponseDto>> getPhiAccessLogsByPatientId(
            @PathVariable UUID patientId) {
        List<PhiAccessLog> logs = phiAccessLogService.getPhiAccessLogsByPatientId(patientId);
        List<PhiAccessLogResponseDto> response = logs.stream()
                .map(this::toDto)
                .collect(Collectors.toList());
        return ResponseEntity.ok(response);
    }

    @Operation(
            summary = "Get PHI access logs by patient ID and date range",
            description = "Retrieve PHI access logs for a patient within a date range."
    )
    @GetMapping("/patient/{patientId}/date-range")
    public ResponseEntity<List<PhiAccessLogResponseDto>> getPhiAccessLogsByPatientIdAndDateRange(
            @PathVariable UUID patientId,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Instant startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Instant endDate) {
        List<PhiAccessLog> logs = phiAccessLogService.getPhiAccessLogsByPatientIdAndDateRange(patientId, startDate, endDate);
        List<PhiAccessLogResponseDto> response = logs.stream()
                .map(this::toDto)
                .collect(Collectors.toList());
        return ResponseEntity.ok(response);
    }

    @Operation(
            summary = "Get PHI access logs by user ID",
            description = "Retrieve all PHI access logs for a specific user. Admin only.",
            parameters = @Parameter(name = "userId", description = "User ID", required = true)
    )
    @ApiResponse(
            responseCode = "200",
            description = "List of PHI access logs retrieved successfully",
            content = @Content(
                    mediaType = "application/json",
                    array = @ArraySchema(schema = @Schema(implementation = PhiAccessLogResponseDto.class))
            )
    )
    @GetMapping("/user/{userId}")
    public ResponseEntity<List<PhiAccessLogResponseDto>> getPhiAccessLogsByUserId(
            @PathVariable UUID userId) {
        List<PhiAccessLog> logs = phiAccessLogService.getPhiAccessLogsByUserId(userId);
        List<PhiAccessLogResponseDto> response = logs.stream()
                .map(this::toDto)
                .collect(Collectors.toList());
        return ResponseEntity.ok(response);
    }

    private PhiAccessLogResponseDto toDto(PhiAccessLog log) {
        return new PhiAccessLogResponseDto(
                log.getId(),
                log.getUser().getId(),
                log.getUser().getFirstName() + " " + log.getUser().getLastName(),
                log.getUser().getEmail(),
                log.getPatient().getId(),
                log.getPatient().getUser().getFirstName() + " " + log.getPatient().getUser().getLastName(),
                log.getAccessType(),
                log.getAccessedFields(),
                log.getPurpose(),
                log.getIpAddress(),
                log.getUserAgent(),
                log.getTimestamp()
        );
    }
}

