package com.gnx.telemedicine.controller;

import com.gnx.telemedicine.dto.auth.TwoFactorSetupResponseDto;
import com.gnx.telemedicine.dto.auth.TwoFactorVerifyRequestDto;
import com.gnx.telemedicine.model.TwoFactorAuth;
import com.gnx.telemedicine.service.TwoFactorAuthService;
import io.swagger.v3.oas.annotations.Operation;
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 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.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/v3/2fa")
@RequiredArgsConstructor
@Tag(name = "Two-Factor Authentication", description = "Endpoints for managing 2FA")
@SecurityRequirement(name = "bearerAuth")
public class TwoFactorAuthController {
    
    private final TwoFactorAuthService twoFactorAuthService;

    @Operation(
            summary = "Setup 2FA",
            description = "Initialize 2FA setup for the current user. Returns secret key and backup codes.",
            responses = @ApiResponse(
                    responseCode = "200",
                    description = "2FA setup initialized",
                    content = @Content(schema = @Schema(implementation = TwoFactorSetupResponseDto.class))
            )
    )
    @PostMapping("/setup")
    public ResponseEntity<Map<String, Object>> setup2FA(Authentication authentication) {
        String userEmail = authentication.getName();
        TwoFactorAuth twoFactorAuth = twoFactorAuthService.setup2FA(userEmail);
        
        String qrCodeUrl = twoFactorAuthService.generateQrCodeUrl(userEmail);
        
        Map<String, Object> response = new HashMap<>();
        response.put("userId", twoFactorAuth.getUser().getId());
        response.put("secretKey", twoFactorAuth.getSecretKey());
        response.put("qrCodeUrl", qrCodeUrl);
        response.put("backupCodes", twoFactorAuth.getBackupCodes());
        response.put("enabled", twoFactorAuth.getEnabled());
        
        return ResponseEntity.ok(response);
    }

    @Operation(
            summary = "Enable 2FA",
            description = "Enable 2FA after verifying the setup code."
    )
    @PostMapping("/enable")
    public ResponseEntity<Map<String, String>> enable2FA(
            Authentication authentication,
            @RequestBody @Valid TwoFactorVerifyRequestDto requestDto) {
        String userEmail = authentication.getName();
        twoFactorAuthService.enable2FA(userEmail, requestDto.code());
        
        Map<String, String> response = new HashMap<>();
        response.put("message", "2FA enabled successfully");
        return ResponseEntity.ok(response);
    }

    @Operation(
            summary = "Disable 2FA",
            description = "Disable 2FA for the current user. Requires verification code."
    )
    @PostMapping("/disable")
    public ResponseEntity<Map<String, String>> disable2FA(
            Authentication authentication,
            @RequestBody @Valid TwoFactorVerifyRequestDto requestDto) {
        String userEmail = authentication.getName();
        twoFactorAuthService.disable2FA(userEmail, requestDto.code());
        
        Map<String, String> response = new HashMap<>();
        response.put("message", "2FA disabled successfully");
        return ResponseEntity.ok(response);
    }

    @Operation(
            summary = "Check if 2FA is enabled",
            description = "Check if 2FA is enabled for the current user."
    )
    @GetMapping("/status")
    public ResponseEntity<Map<String, Object>> get2FAStatus(Authentication authentication) {
        String userEmail = authentication.getName();
        boolean enabled = twoFactorAuthService.is2FAEnabled(userEmail);
        
        Map<String, Object> response = new HashMap<>();
        response.put("enabled", enabled);
        
        if (enabled) {
            twoFactorAuthService.get2FASetup(userEmail).ifPresent(setup -> {
                response.put("hasBackupCodes", setup.getBackupCodes() != null && !setup.getBackupCodes().isEmpty());
                response.put("backupCodesCount", setup.getBackupCodes() != null ? setup.getBackupCodes().size() : 0);
            });
        }
        
        return ResponseEntity.ok(response);
    }

    @Operation(
            summary = "Regenerate backup codes",
            description = "Generate new backup codes. Old codes will be invalidated."
    )
    @PostMapping("/backup-codes/regenerate")
    public ResponseEntity<Map<String, Object>> regenerateBackupCodes(
            Authentication authentication,
            @RequestBody @Valid TwoFactorVerifyRequestDto requestDto) {
        String userEmail = authentication.getName();
        List<String> backupCodes = twoFactorAuthService.regenerateBackupCodes(userEmail, requestDto.code());
        
        Map<String, Object> response = new HashMap<>();
        response.put("backupCodes", backupCodes);
        response.put("message", "Backup codes regenerated successfully");
        return ResponseEntity.ok(response);
    }

    @Operation(
            summary = "Get QR code URL",
            description = "Get the QR code URL for 2FA setup."
    )
    @GetMapping("/qr-code")
    public ResponseEntity<Map<String, String>> getQrCode(Authentication authentication) {
        String userEmail = authentication.getName();
        String qrCodeUrl = twoFactorAuthService.generateQrCodeUrl(userEmail);
        
        Map<String, String> response = new HashMap<>();
        response.put("qrCodeUrl", qrCodeUrl);
        return ResponseEntity.ok(response);
    }
}

