package com.gnx.telemedicine.controller;

import com.gnx.telemedicine.dto.user.*;
import com.gnx.telemedicine.dto.admin.UserManagementDto;
import com.gnx.telemedicine.dto.auth.PasswordChangeDto;
import com.gnx.telemedicine.model.UserModel;
import com.gnx.telemedicine.repository.UserRepository;
import com.gnx.telemedicine.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
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.responses.ApiResponses;
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.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/api/v3/users")
@RequiredArgsConstructor
@Tag(name = "User Management", description = "Endpoints for user registration (doctors, patients, and admins)")
public class UserController {

    private final UserService userService;
    private final UserRepository userRepository;

    @Operation(
            summary = "Register a new doctor",
            description = "Register a new doctor account.",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "Doctor registration details",
                    required = true,
                    content = @Content(schema = @Schema(implementation = DoctorRegistrationDto.class))
            )
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "201",
                    description = "Doctor registered successfully",
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = DoctorResponseDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "400",
                    description = "Validation error or duplicate email",
                    content = @Content(mediaType = "application/json")
            )
    })
    @PostMapping("/register/doctor")
    public ResponseEntity<DoctorResponseDto> registerDoctor(@Valid @RequestBody DoctorRegistrationDto doctorRegistrationDto) {
        return new ResponseEntity<>(userService.registerDoctor(doctorRegistrationDto), HttpStatus.CREATED);
    }

    @Operation(
            summary = "Register a new patient",
            description = "Register a new patient account.",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "Patient registration details",
                    required = true,
                    content = @Content(schema = @Schema(implementation = PatientRegistrationDto.class))
            )
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "201",
                    description = "Patient registered successfully.",
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = PatientResponseDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "400",
                    description = "Validation error or duplicate email",
                    content = @Content(mediaType = "application/json")
            )
    })
    @PostMapping("/register/patient")
    public ResponseEntity<PatientResponseDto> registerPatient(@Valid @RequestBody PatientRegistrationDto patientRegistrationDto) {
        return new ResponseEntity<>(userService.registerPatient(patientRegistrationDto), HttpStatus.CREATED);
    }

    @Operation(
            summary = "Register a new admin",
            description = "Register a new admin account. This is restricted and only can be in email in configuration.",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "Admin registration details",
                    required = true,
                    content = @Content(schema = @Schema(implementation = UserRegistrationDto.class))
            )
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "201",
                    description = "Admin registered successfully."
            ),
            @ApiResponse(
                    responseCode = "400",
                    description = "Validation error",
                    content = @Content(mediaType = "application/json")
            )
    })
    @PostMapping("/register/admin")
    public ResponseEntity<Void> registerAdmin(@Valid @RequestBody UserRegistrationDto userRegistrationDto) {
        userService.registerAdmin(userRegistrationDto);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }

    @Operation(
            summary = "Get current user profile",
            description = "Get the profile of the currently authenticated user.",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "User profile retrieved successfully",
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = UserManagementDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT"
            )
    })
    @GetMapping("/me")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<UserManagementDto> getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String email = authentication.getName();
        return ResponseEntity.ok(userService.getCurrentUser(email));
    }

    @Operation(
            summary = "Get current doctor profile",
            description = "Get the doctor-specific profile of the currently authenticated doctor.",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "Doctor profile retrieved successfully",
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = DoctorResponseDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT"
            ),
            @ApiResponse(
                    responseCode = "403",
                    description = "Forbidden - Only doctors can access doctor profile"
            )
    })
    @GetMapping("/doctors/me")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<DoctorResponseDto> getCurrentDoctorProfile() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String email = authentication.getName();
        return ResponseEntity.ok(userService.getCurrentDoctorProfile(email));
    }

    @Operation(
            summary = "Get current patient profile",
            description = "Get the patient-specific profile of the currently authenticated patient.",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "Patient profile retrieved successfully",
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = PatientResponseDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT"
            ),
            @ApiResponse(
                    responseCode = "403",
                    description = "Forbidden - Only patients can access patient profile"
            )
    })
    @GetMapping("/patients/me")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<PatientResponseDto> getCurrentPatientProfile() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String email = authentication.getName();
        return ResponseEntity.ok(userService.getCurrentPatientProfile(email));
    }

    @Operation(
            summary = "Update current user profile",
            description = "Update the profile of the currently authenticated user (firstName, lastName, phoneNumber).",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "User profile updated successfully",
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = UserManagementDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT"
            )
    })
    @PatchMapping("/me")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<UserManagementDto> updateUserProfile(@Valid @RequestBody UserUpdateDto updateDto) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String email = authentication.getName();
        return ResponseEntity.ok(userService.updateUserProfile(email, updateDto));
    }

    @Operation(
            summary = "Update current doctor profile",
            description = "Update the doctor-specific profile of the currently authenticated doctor (specialization, yearsOfExperience, biography, consultationFee).",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "Doctor profile updated successfully",
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = DoctorResponseDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT"
            ),
            @ApiResponse(
                    responseCode = "403",
                    description = "Forbidden - Only doctors can update doctor profile"
            )
    })
    @PatchMapping("/doctors/me")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<DoctorResponseDto> updateDoctorProfile(@Valid @RequestBody DoctorUpdateDto updateDto) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String email = authentication.getName();
        return ResponseEntity.ok(userService.updateDoctorProfile(email, updateDto));
    }

    @Operation(
            summary = "Update current patient profile",
            description = "Update the patient-specific profile of the currently authenticated patient (emergencyContactName, emergencyContactPhone, bloodType, allergies).",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "Patient profile updated successfully",
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = PatientResponseDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT"
            ),
            @ApiResponse(
                    responseCode = "403",
                    description = "Forbidden - Only patients can update patient profile"
            )
    })
    @PatchMapping("/patients/me")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<PatientResponseDto> updatePatientProfile(@Valid @RequestBody PatientUpdateDto updateDto) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String email = authentication.getName();
        return ResponseEntity.ok(userService.updatePatientProfile(email, updateDto));
    }

    @Operation(
            summary = "Get all doctors",
            description = "Get a list of all active doctors in the system. Available to all authenticated users.",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "Doctors retrieved successfully",
                    content = @Content(
                            mediaType = "application/json",
                            array = @ArraySchema(schema = @Schema(implementation = DoctorResponseDto.class))
                    )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT"
            )
    })
    @GetMapping("/doctors")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<List<DoctorResponseDto>> getAllDoctors() {
        return ResponseEntity.ok(userService.getAllDoctors());
    }

    @Operation(
            summary = "Get all patients",
            description = "Get a list of all active patients in the system. Available to all authenticated users.",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "Patients retrieved successfully",
                    content = @Content(
                            mediaType = "application/json",
                            array = @ArraySchema(schema = @Schema(implementation = PatientResponseDto.class))
                    )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT"
            )
    })
    @GetMapping("/patients")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<List<PatientResponseDto>> getAllPatients() {
        return ResponseEntity.ok(userService.getAllPatients());
    }

    @Operation(
            summary = "Get doctor profile by ID",
            description = "Get full doctor profile by ID. Patients can view full doctor profiles to make informed decisions.",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "Doctor profile retrieved successfully",
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = DoctorResponseDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT"
            ),
            @ApiResponse(
                    responseCode = "404",
                    description = "Doctor not found"
            )
    })
    @GetMapping("/doctors/{doctorId}")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<DoctorResponseDto> getDoctorProfileById(
            Authentication authentication,
            @PathVariable java.util.UUID doctorId) {
        return ResponseEntity.ok(userService.getDoctorProfileById(doctorId));
    }

    @Operation(
            summary = "Get patient profile by ID",
            description = "Get full patient profile by ID. Doctors can view full patient profiles for comprehensive care.",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "Patient profile retrieved successfully",
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = PatientResponseDto.class)
                    )
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT"
            ),
            @ApiResponse(
                    responseCode = "403",
                    description = "Forbidden - Only doctors can view patient profiles"
            ),
            @ApiResponse(
                    responseCode = "404",
                    description = "Patient not found"
            )
    })
    @GetMapping("/patients/{patientId}")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<PatientResponseDto> getPatientProfileById(
            Authentication authentication,
            @PathVariable java.util.UUID patientId) {
        String userEmail = authentication.getName();
        UserModel user = userRepository.findByEmail(userEmail)
                .orElseThrow(() -> new RuntimeException("User not found"));

        // Only doctors can view full patient profiles
        if (!user.getRole().name().equals("DOCTOR")) {
            return ResponseEntity.status(403).build();
        }

        return ResponseEntity.ok(userService.getPatientProfileById(patientId));
    }

    @Operation(
            summary = "Change password",
            description = "Change the password for the currently authenticated user. Requires current password and new password.",
            security = @SecurityRequirement(name = "bearerAuth")
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "Password changed successfully"
            ),
            @ApiResponse(
                    responseCode = "400",
                    description = "Validation error or password does not meet requirements",
                    content = @Content(mediaType = "application/json")
            ),
            @ApiResponse(
                    responseCode = "401",
                    description = "Unauthorized - Missing or expired JWT, or current password is incorrect"
            )
    })
    @PostMapping("/me/change-password")
    @SecurityRequirement(name = "bearerAuth")
    public ResponseEntity<Void> changePassword(
            Authentication authentication,
            @Valid @RequestBody PasswordChangeDto passwordChangeDto) {
        String email = authentication.getName();
        userService.changePassword(
                email,
                passwordChangeDto.currentPassword(),
                passwordChangeDto.newPassword(),
                passwordChangeDto.confirmNewPassword()
        );
        return ResponseEntity.ok().build();
    }
}
