package com.social.media.controller;

import com.social.media.dto.LoginRequest;
import com.social.media.dto.LoginResponse;
import com.social.media.service.AuthService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

/**
 * REST Controller for authentication operations
 */
@RestController
@RequestMapping("/api/v1/auth")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "Authentication", description = "User authentication and authorization operations")
public class AuthController {

    private final AuthService authService;

    @Operation(
        summary = "User login", 
        description = "Authenticates a user with email and password. Returns user information and authentication token on success."
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "Login successful"),
        @ApiResponse(responseCode = "401", description = "Invalid credentials"),
        @ApiResponse(responseCode = "423", description = "Account locked"),
        @ApiResponse(responseCode = "400", description = "Invalid request format"),
        @ApiResponse(responseCode = "500", description = "Internal server error")
    })
    @PostMapping("/login")
    public ResponseEntity<LoginResponse> login(@Valid @RequestBody LoginRequest loginRequest) {
        log.info("Login attempt for email: {}", loginRequest.getEmail());
        
        try {
            LoginResponse response = authService.authenticate(loginRequest);
            
            if (response.isSuccess()) {
                log.info("Login successful for user: {}", response.getEmail());
                return ResponseEntity.ok(response);
            } else {
                // Determinar o status HTTP baseado no tipo de erro
                HttpStatus status = determineErrorStatus(response);
                log.warn("Login failed for email: {} - {}", loginRequest.getEmail(), response.getMessage());
                return ResponseEntity.status(status).body(response);
            }
            
        } catch (Exception e) {
            log.error("Unexpected error during login for email: {}", loginRequest.getEmail(), e);
            LoginResponse errorResponse = LoginResponse.error("Erro interno durante autenticação");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
        }
    }

    @Operation(
        summary = "User logout", 
        description = "Logs out a user and invalidates their session/token"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "Logout successful"),
        @ApiResponse(responseCode = "400", description = "Invalid user ID"),
        @ApiResponse(responseCode = "500", description = "Internal server error")
    })
    @PostMapping("/logout")
    public ResponseEntity<Map<String, Object>> logout(
            @Parameter(description = "User ID to logout") @RequestParam Long userId) {
        
        log.info("Logout attempt for user ID: {}", userId);
        
        try {
            boolean success = authService.logout(userId);
            
            if (success) {
                log.info("Logout successful for user ID: {}", userId);
                return ResponseEntity.ok(Map.of(
                    "success", true,
                    "message", "Logout realizado com sucesso",
                    "userId", userId
                ));
            } else {
                log.warn("Logout failed for user ID: {}", userId);
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "message", "Erro durante logout",
                    "userId", userId
                ));
            }
            
        } catch (Exception e) {
            log.error("Unexpected error during logout for user ID: {}", userId, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of(
                "success", false,
                "message", "Erro interno durante logout",
                "userId", userId
            ));
        }
    }

    @Operation(
        summary = "Validate session", 
        description = "Validates if a user session/token is still active and valid"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "Session validation result"),
        @ApiResponse(responseCode = "400", description = "Invalid parameters"),
        @ApiResponse(responseCode = "500", description = "Internal server error")
    })
    @GetMapping("/validate")
    public ResponseEntity<Map<String, Object>> validateSession(
            @Parameter(description = "User ID") @RequestParam Long userId,
            @Parameter(description = "Authentication token") @RequestParam(required = false) String token) {
        
        log.debug("Session validation for user ID: {}", userId);
        
        try {
            boolean isValid = authService.validateSession(userId, token);
            
            return ResponseEntity.ok(Map.of(
                "valid", isValid,
                "userId", userId,
                "message", isValid ? "Sessão válida" : "Sessão inválida"
            ));
            
        } catch (Exception e) {
            log.error("Error during session validation for user ID: {}", userId, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of(
                "valid", false,
                "message", "Erro interno durante validação",
                "userId", userId
            ));
        }
    }

    @Operation(
        summary = "Refresh token", 
        description = "Refreshes an authentication token using a refresh token"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "Token refreshed successfully"),
        @ApiResponse(responseCode = "401", description = "Invalid refresh token"),
        @ApiResponse(responseCode = "400", description = "Invalid request"),
        @ApiResponse(responseCode = "500", description = "Internal server error")
    })
    @PostMapping("/refresh")
    public ResponseEntity<Map<String, Object>> refreshToken(
            @Parameter(description = "Refresh token") @RequestParam String refreshToken) {
        
        log.debug("Token refresh attempt");
        
        try {
            String newToken = authService.refreshToken(refreshToken);
            
            if (newToken != null) {
                return ResponseEntity.ok(Map.of(
                    "success", true,
                    "token", newToken,
                    "message", "Token renovado com sucesso"
                ));
            } else {
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of(
                    "success", false,
                    "message", "Refresh token inválido ou expirado"
                ));
            }
            
        } catch (Exception e) {
            log.error("Error during token refresh", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of(
                "success", false,
                "message", "Erro interno durante renovação do token"
            ));
        }
    }

    @Operation(
        summary = "Check authentication status", 
        description = "Simple endpoint to check if authentication service is working"
    )
    @ApiResponse(responseCode = "200", description = "Authentication service is working")
    @GetMapping("/status")
    public ResponseEntity<Map<String, Object>> status() {
        return ResponseEntity.ok(Map.of(
            "service", "Authentication Service",
            "status", "active",
            "timestamp", java.time.LocalDateTime.now()
        ));
    }

    /**
     * Determina o status HTTP apropriado baseado no tipo de erro de login
     */
    private HttpStatus determineErrorStatus(LoginResponse response) {
        if (response.isAccountLocked()) {
            return HttpStatus.LOCKED; // 423
        }
        
        if (response.isPasswordExpired()) {
            return HttpStatus.FORBIDDEN; // 403
        }
        return HttpStatus.UNAUTHORIZED; // 401
    }
}
