package com.dora.controller;

import com.dora.dto.AdminAuthDto;
import com.dora.dto.ApiResponse;
import com.dora.service.AdminAuthService;
import com.dora.service.JwtTokenManager;
import com.dora.util.AdminSecurityUtil;
import com.dora.util.JwtUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;

/**
 * 管理员认证控制器
 */
@RestController
@RequestMapping("/admin/auth")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "管理员认证", description = "管理员注册、登录和认证相关接口")
public class AdminAuthController {

    private final AdminAuthService adminAuthService;
    private final JwtUtil jwtUtil;
    private final JwtTokenManager jwtTokenManager;

    @PostMapping("/first-register")
    @Operation(summary = "管理员首次注册", description = "系统首次部署时的管理员注册接口，仅当系统中没有管理员时可用")
    public ApiResponse<String> firstTimeRegister(
            @Valid @RequestBody AdminAuthDto.AdminRegisterRequest request) {
        
        return adminAuthService.firstTimeRegister(request);
    }

    @GetMapping("/needs-initialization")
    @Operation(summary = "检查系统是否需要初始化", description = "检查系统是否需要进行首次管理员注册")
    public ApiResponse<Boolean> needsInitialization() {
        boolean needsInit = adminAuthService.needsInitialization();
        return ApiResponse.success(needsInit);
    }

    @PostMapping("/register")
    @Operation(summary = "管理员注册", description = "管理员第一次注册接口")
    public ApiResponse<String> register(
            @Valid @RequestBody AdminAuthDto.AdminRegisterRequest request) {
        
        return adminAuthService.register(request);
    }

    @PostMapping("/login")
    @Operation(summary = "管理员登录", description = "管理员登录接口，使用用户名和密码")
    public ApiResponse<AdminAuthDto.AdminLoginResponse> login(
            @Valid @RequestBody AdminAuthDto.AdminLoginRequest request) {
        
        return adminAuthService.login(request);
    }

    @PostMapping("/refresh-token")
    @Operation(summary = "刷新管理员Token", description = "刷新管理员的JWT token以延长登录状态。只有当token即将过期时才会生成新token。")
    public ApiResponse<AdminAuthDto.AdminRefreshTokenResponse> refreshToken(HttpServletRequest request) {
        try {
            // 1. 获取Authorization header
            String authHeader = request.getHeader("Authorization");
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                return ApiResponse.error(401, "未提供认证令牌");
            }

            // 2. 提取token
            String token = authHeader.substring(7);
            
            // 3. 调用JWT工具类进行token刷新
            JwtUtil.RefreshTokenResult result = jwtUtil.refreshAdminToken(token);
            
            // 4. 构建响应
            AdminAuthDto.AdminRefreshTokenResponse response = new AdminAuthDto.AdminRefreshTokenResponse();
            response.setSuccess(result.isSuccess());
            response.setRefreshed(result.isRefreshed());
            response.setMessage(result.getMessage());
            
            if (result.isSuccess()) {
                response.setToken(result.getToken());
                // 格式化过期时间
                if (result.getExpiration() != null) {
                    response.setExpiresAt(formatTokenExpirationTime(result.getExpiration()));
                }
                
                log.info("管理员Token刷新请求处理完成 - 刷新状态: {}, 消息: {}", 
                    result.isRefreshed() ? "已刷新" : "无需刷新", result.getMessage());
                
                return ApiResponse.success(response);
            } else {
                log.warn("管理员Token刷新失败: {}", result.getMessage());
                return ApiResponse.error(401, result.getMessage());
            }
            
        } catch (Exception e) {
            log.error("刷新管理员token失败", e);
            return ApiResponse.error(500, "刷新token失败");
        }
    }

    @GetMapping("/info")
    @Operation(summary = "获取管理员信息", description = "获取当前登录管理员的信息")
    public ApiResponse<AdminAuthDto.AdminInfoResponse> getAdminInfo(
            HttpServletRequest request) {
        
        // 从JWT token中获取管理员ID
        Long adminId = getCurrentAdminId(request);
        if (adminId == null) {
            return ApiResponse.error(401, "请先登录");
        }
        
        return adminAuthService.getAdminInfo(adminId);
    }

    @GetMapping("/dashboard")
    @Operation(summary = "获取仪表盘数据", description = "获取管理员仪表盘的统计数据")
    public ApiResponse<AdminAuthDto.DashboardResponse> getDashboardData() {
        
        log.info("收到仪表盘数据请求");
        
        try {
            // 从SecurityContext中获取管理员ID（由JWT过滤器设置）
            Long adminId = AdminSecurityUtil.getCurrentAdminId();
            log.info("从SecurityContext解析得到的管理员ID: {}", adminId);
            
            log.info("调用服务获取仪表盘数据，管理员ID: {}", adminId);
            return adminAuthService.getDashboardData(adminId);
            
        } catch (RuntimeException e) {
            log.warn("管理员认证失败: {}", e.getMessage());
            return ApiResponse.error(401, "请先登录");
        }
    }

    @GetMapping("/permissions/{permission}")
    @Operation(summary = "检查权限", description = "检查当前管理员是否具有指定权限")
    public ApiResponse<Boolean> checkPermission(
            @Parameter(description = "权限名称") @PathVariable String permission,
            HttpServletRequest request) {
        
        // 从JWT token中获取管理员ID
        Long adminId = getCurrentAdminId(request);
        if (adminId == null) {
            return ApiResponse.error(401, "请先登录");
        }
        
        boolean hasPermission = adminAuthService.hasPermission(adminId, permission);
        return ApiResponse.success(hasPermission);
    }


    /**
     * 从请求中获取当前管理员ID
     */
    private Long getCurrentAdminId(HttpServletRequest request) {
        try {
            // 从Header中获取token
            String authHeader = request.getHeader("Authorization");
            log.debug("Authorization header: {}", authHeader != null ? authHeader.substring(0, Math.min(20, authHeader.length())) + "..." : "null");
            
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                log.warn("无效的Authorization header");
                return null;
            }
            
            String token = authHeader.substring(7);
            log.debug("提取的token长度: {}", token.length());
            
            // 验证token有效性
            boolean isValid = jwtUtil.validateToken(token);
            log.debug("Token验证结果: {}", isValid);
            if (!isValid) {
                log.warn("Token验证失败");
                return null;
            }
            
            // 检查是否为管理员token
            boolean isAdminToken = jwtUtil.isAdminToken(token);
            log.debug("是否为管理员token: {}", isAdminToken);
            if (!isAdminToken) {
                log.warn("不是管理员token");
                return null;
            }
            
            // 获取管理员ID
            Long adminId = jwtUtil.getAdminIdFromToken(token);
            log.debug("从token中获取的管理员ID: {}", adminId);
            return adminId;
            
        } catch (Exception e) {
            log.warn("获取管理员ID失败", e);
            return null;
        }
    }

    /**
     * 检查当前用户是否为管理员
     */
    @GetMapping("/check-admin")
    @Operation(summary = "检查管理员身份", description = "检查当前用户是否为管理员")
    public ApiResponse<Boolean> checkAdmin(HttpServletRequest request) {
        Long adminId = getCurrentAdminId(request);
        if (adminId == null) {
            return ApiResponse.success(false);
        }
        
        boolean isAdmin = adminAuthService.isAdmin(adminId);
        return ApiResponse.success(isAdmin);
    }

    /**
     * 检查当前用户是否为工作人员
     */
    @GetMapping("/check-staff")
    @Operation(summary = "检查工作人员身份", description = "检查当前用户是否为工作人员")
    public ApiResponse<Boolean> checkStaff(HttpServletRequest request) {
        Long adminId = getCurrentAdminId(request);
        if (adminId == null) {
            return ApiResponse.success(false);
        }
        
        boolean isStaff = adminAuthService.isStaff(adminId);
        return ApiResponse.success(isStaff);
    }
    
    /**
     * 调试接口 - 获取当前token信息
     */
    @GetMapping("/debug-token")
    @Operation(summary = "调试token信息", description = "用于调试JWT token解析问题")
    public ApiResponse<Object> debugToken(HttpServletRequest request) {
        try {
            String authHeader = request.getHeader("Authorization");
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                return ApiResponse.error(400, "无效的Authorization header");
            }
            
            String token = authHeader.substring(7);
            
            // 基本信息
            java.util.Map<String, Object> result = new java.util.HashMap<>();
            result.put("tokenLength", token.length());
            result.put("tokenPrefix", token.substring(0, Math.min(20, token.length())));
            
            try {
                result.put("isValid", jwtUtil.validateToken(token));
                result.put("isAdminToken", jwtUtil.isAdminToken(token));
                result.put("type", jwtUtil.getTypeFromToken(token));
                result.put("adminId", jwtUtil.getAdminIdFromToken(token));
                result.put("expiration", jwtUtil.getExpirationDateFromToken(token));
            } catch (Exception e) {
                result.put("parseError", e.getMessage());
            }
            
            return ApiResponse.success(result);
            
        } catch (Exception e) {
            return ApiResponse.error(500, "调试失败: " + e.getMessage());
        }
    }

    /**
     * 管理员登出
     */
    @PostMapping("/logout")
    @Operation(summary = "管理员登出", description = "管理员主动登出，清理当前token")
    public ApiResponse<String> logout(HttpServletRequest request) {
        try {
            String authHeader = request.getHeader("Authorization");
            if (!StringUtils.hasText(authHeader) || !authHeader.startsWith("Bearer ")) {
                return ApiResponse.error(400, "未提供认证令牌");
            }

            String token = authHeader.substring(7);
            if (!jwtUtil.validateToken(token)) {
                return ApiResponse.error(400, "认证令牌无效或已过期");
            }

            // 获取管理员信息
            Long adminId = jwtUtil.getAdminIdFromToken(token);
            String jwtId = jwtUtil.getJwtIdFromToken(token);

            if (adminId != null && jwtId != null) {
                // 从token管理器中移除当前token
                jwtTokenManager.removeAdminToken(adminId, jwtId);
                log.info("管理员登出成功 - adminId: {}, jwtId: {}", adminId, jwtId);
                return ApiResponse.success("登出成功");
            } else {
                return ApiResponse.error(400, "token信息不完整");
            }

        } catch (Exception e) {
            log.error("管理员登出失败", e);
            return ApiResponse.error("登出失败: " + e.getMessage());
        }
    }

    /**
     * 格式化token过期时间
     * @param expirationTime 过期时间
     * @return 格式化后的时间
     */
    private java.time.LocalDateTime formatTokenExpirationTime(java.util.Date expirationTime) {
        java.time.Instant instant = expirationTime.toInstant();
        return instant.atZone(java.time.ZoneId.systemDefault()).toLocalDateTime();
    }
} 