package com.gnx.telemedicine.controller;

import com.gnx.telemedicine.dto.patient_safety.ClinicalAlertRequestDto;
import com.gnx.telemedicine.dto.patient_safety.ClinicalAlertResponseDto;
import com.gnx.telemedicine.model.Doctor;
import com.gnx.telemedicine.model.Patient;
import com.gnx.telemedicine.model.UserModel;
import com.gnx.telemedicine.repository.DoctorRepository;
import com.gnx.telemedicine.repository.PatientRepository;
import com.gnx.telemedicine.repository.UserRepository;
import com.gnx.telemedicine.service.ClinicalAlertService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

@RestController
@RequestMapping("/api/v3/clinical-alerts")
@RequiredArgsConstructor
@Tag(name = "Clinical Alerts", description = "Endpoints for managing clinical safety alerts")
@SecurityRequirement(name = "bearerAuth")
public class ClinicalAlertController {
    
    private final ClinicalAlertService clinicalAlertService;
    private final UserRepository userRepository;
    private final DoctorRepository doctorRepository;
    private final PatientRepository patientRepository;
    
    @Operation(summary = "Get all alerts for a patient")
    @GetMapping("/patient/{patientId}")
    public ResponseEntity<List<ClinicalAlertResponseDto>> getAlertsByPatientId(
            Authentication authentication,
            @PathVariable UUID patientId) {
        String userEmail = authentication.getName();
        UserModel user = userRepository.findByEmail(userEmail)
                .orElseThrow(() -> new RuntimeException("User not found"));
        
        // Check if user is the patient or the patient's treating doctor
        if (user.getRole().name().equals("PATIENT")) {
            Optional<Patient> patientOpt = patientRepository.findByUser(user);
            if (patientOpt.isEmpty()) {
                return ResponseEntity.status(403).build();
            }
            Patient patient = patientOpt.get();
            if (!patient.getId().equals(patientId)) {
                return ResponseEntity.status(403).build(); // Patients can only see their own alerts
            }
            return ResponseEntity.ok(clinicalAlertService.getAlertsByPatientId(patientId));
        } else if (user.getRole().name().equals("DOCTOR")) {
            Optional<Doctor> doctorOpt = doctorRepository.findByUser(user);
            if (doctorOpt.isEmpty()) {
                return ResponseEntity.status(403).build();
            }
            Doctor doctor = doctorOpt.get();
            // Doctors can only see alerts for their patients
            return ResponseEntity.ok(clinicalAlertService.getAlertsByDoctorIdAndPatientId(doctor.getId(), patientId));
        }
        
        return ResponseEntity.status(403).build();
    }
    
    @Operation(summary = "Get unacknowledged alerts for a patient")
    @GetMapping("/patient/{patientId}/unacknowledged")
    public ResponseEntity<List<ClinicalAlertResponseDto>> getUnacknowledgedAlertsByPatientId(
            Authentication authentication,
            @PathVariable UUID patientId) {
        String userEmail = authentication.getName();
        UserModel user = userRepository.findByEmail(userEmail)
                .orElseThrow(() -> new RuntimeException("User not found"));
        
        // Check if user is the patient or the patient's treating doctor
        if (user.getRole().name().equals("PATIENT")) {
            Optional<Patient> patientOpt = patientRepository.findByUser(user);
            if (patientOpt.isEmpty()) {
                return ResponseEntity.status(403).build();
            }
            Patient patient = patientOpt.get();
            if (!patient.getId().equals(patientId)) {
                return ResponseEntity.status(403).build(); // Patients can only see their own alerts
            }
            return ResponseEntity.ok(clinicalAlertService.getUnacknowledgedAlertsByPatientId(patientId));
        } else if (user.getRole().name().equals("DOCTOR")) {
            Optional<Doctor> doctorOpt = doctorRepository.findByUser(user);
            if (doctorOpt.isEmpty()) {
                return ResponseEntity.status(403).build();
            }
            Doctor doctor = doctorOpt.get();
            // Doctors can only see alerts for their patients
            return ResponseEntity.ok(clinicalAlertService.getUnacknowledgedAlertsByDoctorIdAndPatientId(doctor.getId(), patientId));
        }
        
        return ResponseEntity.status(403).build();
    }
    
    @Operation(summary = "Get all unacknowledged alerts for the current user")
    @GetMapping("/unacknowledged")
    public ResponseEntity<List<ClinicalAlertResponseDto>> getAllUnacknowledgedAlerts(
            Authentication authentication) {
        String userEmail = authentication.getName();
        UserModel user = userRepository.findByEmail(userEmail)
                .orElseThrow(() -> new RuntimeException("User not found"));
        
        // Doctors see alerts for their patients only
        if (user.getRole().name().equals("DOCTOR")) {
            Optional<Doctor> doctorOpt = doctorRepository.findByUser(user);
            if (doctorOpt.isEmpty()) {
                return ResponseEntity.status(403).build();
            }
            Doctor doctor = doctorOpt.get();
            return ResponseEntity.ok(clinicalAlertService.getUnacknowledgedAlertsByDoctorId(doctor.getId()));
        } else if (user.getRole().name().equals("PATIENT")) {
            // Patients see their own alerts
            Optional<Patient> patientOpt = patientRepository.findByUser(user);
            if (patientOpt.isEmpty()) {
                return ResponseEntity.status(403).build();
            }
            Patient patient = patientOpt.get();
            return ResponseEntity.ok(clinicalAlertService.getUnacknowledgedAlertsByPatientId(patient.getId()));
        }
        
        // Admins can see all alerts (for now, return all)
        return ResponseEntity.ok(clinicalAlertService.getAllUnacknowledgedAlerts());
    }
    
    @Operation(summary = "Create a clinical alert")
    @PostMapping
    public ResponseEntity<ClinicalAlertResponseDto> createAlert(
            Authentication authentication,
            @RequestBody @Valid ClinicalAlertRequestDto requestDto) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(clinicalAlertService.createAlert(userEmail, requestDto));
    }
    
    @Operation(summary = "Acknowledge an alert")
    @PostMapping("/{alertId}/acknowledge")
    public ResponseEntity<ClinicalAlertResponseDto> acknowledgeAlert(
            Authentication authentication,
            @PathVariable UUID alertId) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(clinicalAlertService.acknowledgeAlert(userEmail, alertId));
    }
    
    @Operation(summary = "Resolve an alert")
    @PostMapping("/{alertId}/resolve")
    public ResponseEntity<ClinicalAlertResponseDto> resolveAlert(
            Authentication authentication,
            @PathVariable UUID alertId) {
        String userEmail = authentication.getName();
        return ResponseEntity.ok(clinicalAlertService.resolveAlert(userEmail, alertId));
    }
    
    @Operation(summary = "Check for drug interactions")
    @PostMapping("/check-interactions/{patientId}")
    public ResponseEntity<Void> checkForDrugInteractions(@PathVariable UUID patientId) {
        clinicalAlertService.checkForDrugInteractions(patientId);
        return ResponseEntity.ok().build();
    }
}

