package com.dora.service.impl;


import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.cloudauth20190307.AsyncClient;
import com.aliyun.sdk.service.cloudauth20190307.models.Id2MetaVerifyRequest;
import com.aliyun.sdk.service.cloudauth20190307.models.Id2MetaVerifyResponse;
import darabonba.core.client.ClientOverrideConfiguration;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import com.dora.dto.IdentityVerifyRequestDto;
import com.dora.dto.IdentityVerifyResponseDto;
import com.dora.entity.User;
import com.dora.exception.IdentityVerificationException;
import com.dora.mapper.UserMapper;
import com.dora.service.IdentityVerifyLimitService;
import com.dora.service.IdentityVerifyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 实名认证服务实现类
 * 
 * 集成阿里云CloudAuth身份认证服务，进行真实的身份证二要素验证
 *
 * @author Dora
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class IdentityVerifyServiceImpl implements IdentityVerifyService {

    private final UserMapper userMapper;
    private final IdentityVerifyLimitService identityVerifyLimitService;

    @Value("${aliyun.cloudauth.access-key-id}")
    private String accessKeyId;

    @Value("${aliyun.cloudauth.access-key-secret}")
    private String accessKeySecret;
    
    @Value("${aliyun.cloudauth.region}")
    private String region;
    
    @Value("${aliyun.cloudauth.endpoint}")
    private String endpoint;
    
    @Value("${aliyun.cloudauth.param-type}")
    private String paramType;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public IdentityVerifyResponseDto verifyIdentity(IdentityVerifyRequestDto request, Long userId) {
        log.info("开始为用户 {} 执行实名认证, 姓名: {}, 身份证: {}****", 
                userId, request.getRealName(), request.getIdNumber().substring(0, 6));

        try {
            // 1. 检查用户是否存在
            User user = userMapper.selectById(userId);
            if (user == null) {
                log.error("用户不存在: {}", userId);
                return IdentityVerifyResponseDto.error(null, "用户不存在");
            }

            // 2. 检查用户是否已经实名认证
            if (user.getIsVerified() != null && user.getIsVerified() == 1) {
                log.info("用户 {} 已经完成实名认证", userId);
                return IdentityVerifyResponseDto.success(null, "ALREADY_VERIFIED");
            }

            // 3. 验证身份证号码格式
            log.info("步骤3: 验证身份证号码格式");
            if (!isValidIdNumber(request.getIdNumber())) {
                log.error("身份证号码格式验证失败: {}", request.getIdNumber());
                return IdentityVerifyResponseDto.failure(null, "身份证号码格式不正确");
            }
            log.info("身份证号码格式验证通过");

            // 4. 验证姓名格式
            log.info("步骤4: 验证姓名格式");
            if (!isValidName(request.getRealName())) {
                log.error("姓名格式验证失败: '{}'", request.getRealName());
                return IdentityVerifyResponseDto.failure(null, "姓名格式不正确");
            }
            log.info("姓名格式验证通过");

            // 5. 检查每日认证请求限制
            log.info("步骤5: 检查每日认证请求限制");
            if (!identityVerifyLimitService.canMakeVerifyRequest(userId)) {
                int todayCount = identityVerifyLimitService.getTodayRequestCount(userId);
                int dailyLimit = identityVerifyLimitService.getDailyLimit();
                long resetTime = identityVerifyLimitService.getNextResetTime();
                
                log.warn("用户 {} 今日认证请求已达上限: {}/{}", userId, todayCount, dailyLimit);
                
                String message = String.format("今日实名认证请求已达上限 (%d/%d)，请明天再试", todayCount, dailyLimit);
                IdentityVerifyResponseDto response = IdentityVerifyResponseDto.failure(
                        "DAILY_LIMIT_EXCEEDED_" + System.currentTimeMillis(), 
                        message
                );
                
                // 添加限制相关信息到响应中
                response.setTodayRequestCount(todayCount);
                response.setDailyLimit(dailyLimit);
                response.setRemainingRequests(0);
                response.setResetTime(resetTime);
                
                return response;
            }
            log.info("每日认证请求限制检查通过");

            // 6. 增加认证请求计数（在实际调用API之前）
            log.info("步骤6: 增加认证请求计数");
            identityVerifyLimitService.incrementVerifyRequest(userId);

            // 7. 调用身份认证服务
            log.info("步骤7: 执行身份认证验证");
            boolean verificationResult = performIdentityVerification(request.getRealName(), request.getIdNumber());
            log.info("身份认证验证结果: {}", verificationResult);

            if (verificationResult) {
                // 认证成功，更新用户信息
                User updateUser = new User();
                updateUser.setId(userId);
                updateUser.setRealUsername(request.getRealName());
                updateUser.setIdNumber(request.getIdNumber());
                updateUser.setIsVerified(1); // 标记为已认证
                updateUser.setUpdateTime(LocalDateTime.now());
                
                int updateResult = userMapper.updateById(updateUser);
                if (updateResult > 0) {
                    log.info("用户 {} 实名认证成功，已更新用户信息", userId);
                    log.info("更新信息 - 真实姓名: {}, 身份证: {}****, 认证状态: 已认证", 
                            request.getRealName(), request.getIdNumber().substring(0, 6));
                    
                    IdentityVerifyResponseDto result = IdentityVerifyResponseDto.success(
                            "SUCCESS_" + System.currentTimeMillis(), 
                            "VERIFY_SUCCESS"
                    );
                    result.setVerifyTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    log.info("==================== 实名认证流程完成 ====================");
                    log.info("认证结果: 成功");
                    log.info("完成时间: {}", LocalDateTime.now());
                    log.info("✅ 【真实验证】此次认证通过阿里云CloudAuth进行真实的身份匹配验证");
                    log.info("🔍 【验证详情】正确解析API响应，根据BizCode判断认证结果");
                    return result;
                } else {
                    log.error("用户 {} 实名认证成功但更新用户信息失败", userId);
                    return IdentityVerifyResponseDto.error(
                            "ERROR_" + System.currentTimeMillis(), 
                            "认证成功但更新用户信息失败"
                    );
                }
            } else {
                log.warn("用户 {} 实名认证失败: 身份信息不匹配", userId);
                log.info("==================== 实名认证流程完成 ====================");
                log.info("认证结果: 失败");
                log.info("失败原因: 阿里云身份认证不通过（根据API响应BizCode判断）");
                log.info("完成时间: {}", LocalDateTime.now());
                return IdentityVerifyResponseDto.failure(
                        "FAIL_" + System.currentTimeMillis(),
                        "身份证号码与姓名不匹配"
                );
            }

        } catch (Exception e) {
            log.error("用户 {} 实名认证过程中发生异常", userId, e);
            return IdentityVerifyResponseDto.error(null, "系统异常，请稍后重试: " + e.getMessage());
        }
    }

    @Override
    public boolean isUserVerified(Long userId) {
        if (userId == null) {
            return false;
        }
        
        User user = userMapper.selectById(userId);
        return user != null && user.getIsVerified() != null && user.getIsVerified().equals(1);
    }

    @Override
    public IdentityVerifyResponseDto getUserVerifyInfo(Long userId) {
        if (userId == null) {
            return IdentityVerifyResponseDto.error(null, "用户ID不能为空");
        }

        User user = userMapper.selectById(userId);
        if (user == null) {
            return IdentityVerifyResponseDto.error(null, "用户不存在");
        }

        IdentityVerifyResponseDto response = new IdentityVerifyResponseDto();
        response.setIsVerified(user.getIsVerified() != null && user.getIsVerified() == 1);
        response.setPassed(response.getIsVerified());
        
        // 添加每日请求限制信息
        try {
            response.setTodayRequestCount(identityVerifyLimitService.getTodayRequestCount(userId));
            response.setDailyLimit(identityVerifyLimitService.getDailyLimit());
            response.setRemainingRequests(identityVerifyLimitService.getRemainingRequests(userId));
            response.setResetTime(identityVerifyLimitService.getNextResetTime());
            
            log.debug("用户 {} 认证状态查询 - 今日请求: {}/{}, 剩余: {}", 
                    userId, response.getTodayRequestCount(), response.getDailyLimit(), response.getRemainingRequests());
        } catch (Exception e) {
            log.error("获取用户每日请求限制信息失败 - userId: {}", userId, e);
            // 限制信息获取失败不影响主要功能，设置默认值
            response.setTodayRequestCount(0);
            response.setDailyLimit(identityVerifyLimitService.getDailyLimit());
            response.setRemainingRequests(identityVerifyLimitService.getDailyLimit());
            response.setResetTime(identityVerifyLimitService.getNextResetTime());
        }
        
        if (Boolean.TRUE.equals(response.getIsVerified())) {
            response.setResultStatus("VERIFIED");
            response.setResultMessage("用户已完成实名认证");
            
            // 返回脱敏的实名信息
            if (user.getRealUsername() != null && !user.getRealUsername().isEmpty()) {
                // 姓名脱敏：保留姓氏，其他字符用*替代
                String maskedName = user.getRealUsername().charAt(0) + "*".repeat(Math.max(0, user.getRealUsername().length() - 1));
                response.setResultMessage("已认证用户：" + maskedName);
            }
        } else {
            response.setResultStatus("UNVERIFIED");
            response.setResultMessage("用户未完成实名认证");
        }

        return response;
    }

    /**
     * 执行身份认证验证（阿里云CloudAuth）
     * 
     * 调用阿里云身份认证服务进行真实的身份证二要素验证
     * 
     * @param name 姓名
     * @param idNumber 身份证号码
     * @return 验证结果
     */
    private boolean performIdentityVerification(String name, String idNumber) {
        try {
            log.info("✅ 【真实验证模式】执行阿里云身份认证验证 - 姓名: {}, 身份证: {}****", name, idNumber.substring(0, 6));
            
            // 先进行基本格式验证
            boolean idNumberValid = isValidIdNumber(idNumber);
            boolean nameValid = isValidName(name);
            
            log.info("身份证号码格式验证结果: {}", idNumberValid);
            log.info("姓名格式验证结果: {}", nameValid);
            
            if (!idNumberValid) {
                log.warn("身份证号码格式验证失败: {}", idNumber);
                return false;
            }
            
            if (!nameValid) {
                log.warn("姓名格式验证失败: {} (应为2-4个中文字符)", name);
                return false;
            }
            
            // 检查阿里云凭证配置
            if (accessKeyId == null || accessKeyId.isEmpty() || 
                accessKeySecret == null || accessKeySecret.isEmpty()) {
                log.error("阿里云AccessKey未配置，无法进行身份认证");
                throw new IdentityVerificationException("MISSING_CREDENTIALS", "阿里云AccessKey未配置，请检查环境变量或配置文件");
            }
            
            log.info("开始调用阿里云CloudAuth身份认证API（新版SDK）");
            
            // 配置认证信息
            StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                    .accessKeyId(accessKeyId)
                    .accessKeySecret(accessKeySecret)
                    .build());
            
            // 创建异步客户端
            AsyncClient client = AsyncClient.builder()
                    .region(region)
                    .credentialsProvider(provider)
                    .overrideConfiguration(
                            ClientOverrideConfiguration.create()
                                    .setEndpointOverride(endpoint)
                    )
                    .build();
            
            try {
                // 创建身份证二要素验证请求
                Id2MetaVerifyRequest request = Id2MetaVerifyRequest.builder()
                        .identifyNum(idNumber)  // 身份证号码
                        .userName(name)  // 姓名
                        .paramType(paramType)  // 参数类型：从配置文件读取
                        .build();
                
                log.info("调用阿里云Id2MetaVerify API - 姓名: {}, 身份证: {}****, ParamType: {}", 
                        name, idNumber.substring(0, 6), paramType);
                
                // 同步调用API
                CompletableFuture<Id2MetaVerifyResponse> future = client.id2MetaVerify(request);
                Id2MetaVerifyResponse response = future.get();
                
                log.info("阿里云Id2MetaVerify响应成功");
                
                // 判断验证结果 - 正确解析阿里云API响应
                boolean verifyResult = false;
                if (response.getBody() != null) {
                    log.info("开始解析API响应结果");
                    
                    try {
                        // 检查响应中的Code字段
                        String code = response.getBody().getCode();
                        log.info("API响应Code: {}", code);
                        
                        if ("200".equals(code)) {
                            // Code为200表示接口调用成功，继续检查业务结果
                            log.info("接口调用成功，检查业务验证结果");
                            
                            // 获取ResultObject中的BizCode
                            if (response.getBody().getResultObject() != null) {
                                String bizCode = response.getBody().getResultObject().getBizCode();
                                log.info("业务验证结果BizCode: {}", bizCode);
                                
                                switch (bizCode) {
                                    case "1":
                                        verifyResult = true;
                                        log.info("✅ 阿里云身份认证成功 - 姓名和身份证号码匹配 (BizCode=1)");
                                        break;
                                    case "2":
                                        verifyResult = false;
                                        log.warn("❌ 阿里云身份认证失败 - 姓名和身份证号码不匹配 (BizCode=2)");
                                        break;
                                    case "3":
                                        verifyResult = false;
                                        log.warn("❌ 阿里云身份认证失败 - 查无记录 (BizCode=3)");
                                        break;
                                    default:
                                        verifyResult = false;
                                        log.error("❌ 未知的业务验证结果 BizCode: {}", bizCode);
                                }
                            } else {
                                log.error("API响应中缺少ResultObject");
                                verifyResult = false;
                            }
                        } else {
                            // Code不为200，接口调用失败
                            String message = response.getBody().getMessage();
                            log.error("接口调用失败 - Code: {}, Message: {}", code, message);
                            
                            // 根据不同的错误码提供具体的解决建议
                            if ("440".equals(code)) {
                                log.error("❌ 权限错误：请检查以下配置：");
                                log.error("   1. AccessKey是否具有CloudAuth服务权限");
                                log.error("   2. 账号是否已开通实人认证服务");
                                log.error("   3. 区域配置是否正确（当前：{}）", region);
                                log.error("   4. 建议在阿里云控制台检查RAM权限和服务开通状态");
                            } else if ("400".equals(code)) {
                                log.error("❌ 参数错误：{}", message);
                            }
                            
                            verifyResult = false;
                        }
                        
                    } catch (Exception e) {
                        log.error("解析API响应时发生异常", e);
                        verifyResult = false;
                    }
                    
                } else {
                    log.error("API响应体为空");
                }
                
                return verifyResult;
                
            } finally {
                // 关闭客户端
                client.close();
            }
            
        } catch (ExecutionException e) {
            log.error("调用阿里云身份认证API执行异常", e);
            
            // 处理ExecutionException中的具体异常
            Throwable cause = e.getCause();
            if (cause != null && cause.getMessage() != null) {
                String message = cause.getMessage();
                if (message.contains("InvalidAccessKeyId")) {
                    log.error("错误：AccessKeyId无效，请检查阿里云访问凭证配置");
                } else if (message.contains("SignatureDoesNotMatch")) {
                    log.error("错误：AccessKeySecret无效，请检查阿里云访问凭证配置");
                } else if (message.contains("Forbidden.RAM")) {
                    log.error("错误：RAM权限不足，请确保AccessKey具有CloudAuth服务权限");
                } else {
                    log.error("API调用异常: {}", message);
                }
            }
            
            // API调用失败时返回false，不允许通过认证
            return false;
        } catch (InterruptedException e) {
            log.error("调用阿里云身份认证API被中断", e);
            Thread.currentThread().interrupt();
            return false;
        } catch (Exception e) {
            log.error("调用阿里云身份认证API发生未知异常", e);
            return false;
        }
    }



    /**
     * 验证身份证号码格式
     */
    private boolean isValidIdNumber(String idNumber) {
        if (idNumber == null || idNumber.length() != 18) {
            return false;
        }
        
        // 简单的身份证号码格式验证
        return idNumber.matches("^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$");
    }

    /**
     * 验证姓名格式（支持少数民族长姓名）
     * 
     * 考虑到少数民族姓名可能较长，放开长度限制：
     * - 最少2个字符
     * - 最多支持10个字符（考虑到维吾尔族、藏族等少数民族姓名）
     * - 只允许中文字符
     */
    private boolean isValidName(String name) {
        if (name == null || name.trim().isEmpty()) {
            log.debug("姓名验证失败: 姓名为空");
            return false;
        }
        
        String trimmedName = name.trim();
        log.debug("验证姓名格式: '{}' (长度: {})", trimmedName, trimmedName.length());
        
        // 检查长度：最少2个字符，最多10个字符（支持少数民族长姓名）
        if (trimmedName.length() < 2) {
            log.warn("姓名验证失败: 长度过短 (当前长度: {}, 最少需要: 2个字符)", trimmedName.length());
            return false;
        }
        
        if (trimmedName.length() > 10) {
            log.warn("姓名验证失败: 长度过长 (当前长度: {}, 最多允许: 10个字符)", trimmedName.length());
            return false;
        }
        
        // 检查是否包含非中文字符
        for (char c : trimmedName.toCharArray()) {
            if (c < '\u4e00' || c > '\u9fa5') {
                log.warn("姓名验证失败: 包含非中文字符 '{}' (Unicode: \\u{:04x})", c, (int) c);
                return false;
            }
        }
        
        log.debug("姓名格式验证通过: '{}' (支持少数民族姓名)", trimmedName);
        return true;
    }
}