package com.gnx.telemedicine.controller;

import com.gnx.telemedicine.model.DataSubjectConsent;
import com.gnx.telemedicine.model.DataSubjectRequest;
import com.gnx.telemedicine.model.enums.ConsentType;
import com.gnx.telemedicine.model.enums.DataSubjectRequestStatus;
import com.gnx.telemedicine.model.enums.DataSubjectRequestType;
import com.gnx.telemedicine.service.GdprConsentService;
import com.gnx.telemedicine.service.GdprDataSubjectRequestService;
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.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/api/v3/gdpr")
@RequiredArgsConstructor
@Tag(name = "GDPR Compliance", description = "GDPR data subject rights and consent management endpoints")
@SecurityRequirement(name = "bearerAuth")
public class GdprController {

    private final GdprConsentService consentService;
    private final GdprDataSubjectRequestService requestService;

    @Operation(summary = "Grant consent", description = "Grant consent for a specific consent type (GDPR Article 7)")
    @PostMapping("/consent")
    public ResponseEntity<DataSubjectConsent> grantConsent(
            @RequestParam @NotNull ConsentType consentType,
            @RequestParam(required = false) String consentVersion,
            @RequestParam(required = false, defaultValue = "WEB_FORM") String consentMethod,
            Authentication authentication,
            HttpServletRequest request) {
        
        String userEmail = authentication.getName();
        DataSubjectConsent consent = consentService.grantConsent(
                userEmail, consentType, consentVersion, consentMethod, request);
        return ResponseEntity.ok(consent);
    }

    @Operation(summary = "Withdraw consent", description = "Withdraw previously granted consent (GDPR Article 7)")
    @PostMapping("/consent/withdraw")
    public ResponseEntity<DataSubjectConsent> withdrawConsent(
            @RequestParam @NotNull ConsentType consentType,
            Authentication authentication,
            HttpServletRequest request) {
        
        String userEmail = authentication.getName();
        DataSubjectConsent consent = consentService.withdrawConsent(userEmail, consentType, request);
        return ResponseEntity.ok(consent);
    }

    @Operation(summary = "Get user consents", description = "Get all consent records for the authenticated user")
    @GetMapping("/consent")
    public ResponseEntity<List<DataSubjectConsent>> getUserConsents(Authentication authentication) {
        String userEmail = authentication.getName();
        List<DataSubjectConsent> consents = consentService.getUserConsents(userEmail);
        return ResponseEntity.ok(consents);
    }

    @Operation(summary = "Check consent", description = "Check if user has granted consent for a specific type")
    @GetMapping("/consent/check")
    public ResponseEntity<Map<String, Boolean>> checkConsent(
            @RequestParam @NotNull ConsentType consentType,
            Authentication authentication) {
        
        String userEmail = authentication.getName();
        boolean hasConsent = consentService.hasConsent(userEmail, consentType);
        return ResponseEntity.ok(Map.of("hasConsent", hasConsent));
    }

    @Operation(summary = "Request data access", description = "Request access to personal data (GDPR Article 15)")
    @PostMapping("/request/access")
    public ResponseEntity<DataSubjectRequest> requestAccess(
            @RequestParam(required = false) String description,
            Authentication authentication,
            HttpServletRequest request) {
        
        String userEmail = authentication.getName();
        DataSubjectRequest dataRequest = requestService.createRequest(
                userEmail, DataSubjectRequestType.ACCESS, description, request);
        return ResponseEntity.status(HttpStatus.CREATED).body(dataRequest);
    }

    @Operation(summary = "Request data erasure", description = "Request erasure of personal data (GDPR Article 17)")
    @PostMapping("/request/erasure")
    public ResponseEntity<DataSubjectRequest> requestErasure(
            @RequestParam(required = false) String description,
            Authentication authentication,
            HttpServletRequest request) {
        
        String userEmail = authentication.getName();
        DataSubjectRequest dataRequest = requestService.createRequest(
                userEmail, DataSubjectRequestType.ERASURE, description, request);
        return ResponseEntity.status(HttpStatus.CREATED).body(dataRequest);
    }

    @Operation(summary = "Request data rectification", description = "Request rectification of inaccurate data (GDPR Article 16)")
    @PostMapping("/request/rectification")
    public ResponseEntity<DataSubjectRequest> requestRectification(
            @RequestParam(required = false) String description,
            Authentication authentication,
            HttpServletRequest request) {
        
        String userEmail = authentication.getName();
        DataSubjectRequest dataRequest = requestService.createRequest(
                userEmail, DataSubjectRequestType.RECTIFICATION, description, request);
        return ResponseEntity.status(HttpStatus.CREATED).body(dataRequest);
    }

    @Operation(summary = "Request data portability", description = "Request data in a portable format (GDPR Article 20)")
    @PostMapping("/request/portability")
    public ResponseEntity<DataSubjectRequest> requestPortability(
            @RequestParam(required = false) String description,
            Authentication authentication,
            HttpServletRequest request) {
        
        String userEmail = authentication.getName();
        DataSubjectRequest dataRequest = requestService.createRequest(
                userEmail, DataSubjectRequestType.PORTABILITY, description, request);
        return ResponseEntity.status(HttpStatus.CREATED).body(dataRequest);
    }

    @Operation(summary = "Get user requests", description = "Get all data subject requests for the authenticated user")
    @GetMapping("/request")
    public ResponseEntity<List<DataSubjectRequest>> getUserRequests(Authentication authentication) {
        String userEmail = authentication.getName();
        List<DataSubjectRequest> requests = requestService.getUserRequests(userEmail);
        return ResponseEntity.ok(requests);
    }

    @Operation(summary = "Verify request", description = "Verify a data subject request using verification token")
    @PostMapping("/request/verify")
    public ResponseEntity<DataSubjectRequest> verifyRequest(@RequestParam @NotNull String token) {
        DataSubjectRequest request = requestService.verifyRequest(token);
        return ResponseEntity.ok(request);
    }

    @Operation(summary = "Process access request", description = "Process an access request (Admin only)")
    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/request/{id}/process/access")
    public ResponseEntity<DataSubjectRequest> processAccessRequest(
            @PathVariable UUID id,
            Authentication authentication) {
        
        String userEmail = authentication.getName();
        DataSubjectRequest request = requestService.processAccessRequest(id, userEmail);
        return ResponseEntity.ok(request);
    }

    @Operation(summary = "Process erasure request", description = "Process an erasure request (Admin only)")
    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/request/{id}/process/erasure")
    public ResponseEntity<DataSubjectRequest> processErasureRequest(
            @PathVariable UUID id,
            @RequestParam(required = false) String notes,
            Authentication authentication) {
        
        String userEmail = authentication.getName();
        DataSubjectRequest request = requestService.processErasureRequest(id, userEmail, notes);
        return ResponseEntity.ok(request);
    }

    @Operation(summary = "Process portability request", description = "Process a portability request (Admin only)")
    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/request/{id}/process/portability")
    public ResponseEntity<DataSubjectRequest> processPortabilityRequest(
            @PathVariable UUID id,
            Authentication authentication) {
        
        String userEmail = authentication.getName();
        DataSubjectRequest request = requestService.processPortabilityRequest(id, userEmail);
        return ResponseEntity.ok(request);
    }

    @Operation(summary = "Reject request", description = "Reject a data subject request (Admin only)")
    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/request/{id}/reject")
    public ResponseEntity<DataSubjectRequest> rejectRequest(
            @PathVariable UUID id,
            @RequestParam @NotNull String rejectionReason,
            Authentication authentication) {
        
        String userEmail = authentication.getName();
        DataSubjectRequest request = requestService.rejectRequest(id, userEmail, rejectionReason);
        return ResponseEntity.ok(request);
    }

    @Operation(summary = "Get pending requests", description = "Get all pending data subject requests (Admin only)")
    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/request/pending")
    public ResponseEntity<List<DataSubjectRequest>> getPendingRequests() {
        List<DataSubjectRequest> requests = requestService.getPendingRequests();
        return ResponseEntity.ok(requests);
    }
}

