package com.gxwebsoft.auto.service.impl;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.gxwebsoft.auto.dto.*;
import com.gxwebsoft.auto.service.QrLoginService;
import com.gxwebsoft.common.core.security.JwtSubject;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.JSONUtil;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;

import static com.gxwebsoft.common.core.constants.RedisConstants.*;

/**
 * 扫码登录服务实现
 *
 * @author 科技小王子
 * @since 2025-08-31
 */
@Slf4j
@Service
public class QrLoginServiceImpl implements QrLoginService {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private UserService userService;

    @Value("${config.jwt.secret:websoft-jwt-secret-key-2025}")
    private String jwtSecret;

    @Value("${config.jwt.expire:86400}")
    private Long jwtExpire;

    @Override
    public QrLoginGenerateResponse generateQrLoginToken() {
        // 生成唯一的扫码登录token
        String token = UUID.randomUUID().toString(true);

        // 创建扫码登录数据
        QrLoginData qrLoginData = new QrLoginData();
        qrLoginData.setToken(token);
        qrLoginData.setStatus(QR_LOGIN_STATUS_PENDING);
        qrLoginData.setCreateTime(LocalDateTime.now());
        qrLoginData.setExpireTime(LocalDateTime.now().plusSeconds(QR_LOGIN_TOKEN_TTL));

        // 存储到Redis，设置过期时间
        String redisKey = QR_LOGIN_TOKEN_KEY + token;
        redisUtil.set(redisKey, qrLoginData, QR_LOGIN_TOKEN_TTL, TimeUnit.SECONDS);

        log.info("生成扫码登录token: {}", token);

        // 构造二维码内容(这里可以是前端登录页面的URL + token参数)
        String qrCodeContent = "qr-login:" + token;

        return new QrLoginGenerateResponse(token, qrCodeContent, QR_LOGIN_TOKEN_TTL);
    }

    @Override
    public QrLoginStatusResponse checkQrLoginStatus(String token) {
        if (StrUtil.isBlank(token)) {
            return new QrLoginStatusResponse(QR_LOGIN_STATUS_EXPIRED, null, null, 0L);
        }

        String redisKey = QR_LOGIN_TOKEN_KEY + token;
        QrLoginData qrLoginData = redisUtil.get(redisKey, QrLoginData.class);

        if (qrLoginData == null) {
            return new QrLoginStatusResponse(QR_LOGIN_STATUS_EXPIRED, null, null, 0L);
        }

        // 检查是否过期
        if (LocalDateTime.now().isAfter(qrLoginData.getExpireTime())) {
            // 删除过期的token
            redisUtil.delete(redisKey);
            return new QrLoginStatusResponse(QR_LOGIN_STATUS_EXPIRED, null, null, 0L);
        }

        // 计算剩余过期时间
        long expiresIn = ChronoUnit.SECONDS.between(LocalDateTime.now(), qrLoginData.getExpireTime());

        QrLoginStatusResponse response = new QrLoginStatusResponse();
        response.setStatus(qrLoginData.getStatus());
        response.setExpiresIn(expiresIn);

        // 如果已确认，返回token和用户信息
        if (QR_LOGIN_STATUS_CONFIRMED.equals(qrLoginData.getStatus())) {
            response.setAccessToken(qrLoginData.getAccessToken());

            // 获取用户信息
            if (qrLoginData.getUserId() != null) {
                User user = userService.getByIdRel(qrLoginData.getUserId());
                if (user != null) {
                    // 清除敏感信息
                    user.setPassword(null);
                    response.setUserInfo(user);
                }
            }

            // 确认后删除token，防止重复使用
            redisUtil.delete(redisKey);
        }

        return response;
    }

    @Override
    public QrLoginStatusResponse confirmQrLogin(QrLoginConfirmRequest request) {
        String token = request.getToken();
        Integer userId = request.getUserId();
        String platform = request.getPlatform();

        if (StrUtil.isBlank(token) || userId == null) {
            throw new RuntimeException("参数不能为空");
        }

        String redisKey = QR_LOGIN_TOKEN_KEY + token;
        QrLoginData qrLoginData = redisUtil.get(redisKey, QrLoginData.class);

        if (qrLoginData == null) {
            throw new RuntimeException("扫码登录token不存在或已过期");
        }

        // 检查是否过期
        if (LocalDateTime.now().isAfter(qrLoginData.getExpireTime())) {
            redisUtil.delete(redisKey);
            throw new RuntimeException("扫码登录token已过期");
        }

        // 获取用户信息
        User user = userService.getByIdRel(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 检查用户状态
        if (user.getStatus() != null && user.getStatus() != 0) {
            throw new RuntimeException("用户已被冻结");
        }

        // 如果是微信小程序登录，处理微信相关信息
        if ("miniprogram".equals(platform) && request.getWechatInfo() != null) {
            handleWechatMiniProgramLogin(user, request.getWechatInfo());
        }

        // 生成JWT token
        JwtSubject jwtSubject = new JwtSubject(user.getUsername(), user.getTenantId());
        String accessToken = JwtUtil.buildToken(jwtSubject, jwtExpire, jwtSecret);

        // 更新扫码登录数据
        qrLoginData.setStatus(QR_LOGIN_STATUS_CONFIRMED);
        qrLoginData.setUserId(userId);
        qrLoginData.setUsername(user.getUsername());
        qrLoginData.setAccessToken(accessToken);

        // 更新Redis中的数据
        redisUtil.set(redisKey, qrLoginData, 60L, TimeUnit.SECONDS); // 给前端60秒时间获取token

        log.info("用户 {} 通过 {} 平台确认扫码登录，token: {}", user.getUsername(),
                platform != null ? platform : "unknown", token);

        // 清除敏感信息
        user.setPassword(null);

        return new QrLoginStatusResponse(QR_LOGIN_STATUS_CONFIRMED, accessToken, user, 60L);
    }

    /**
     * 处理微信小程序登录相关逻辑
     */
    private void handleWechatMiniProgramLogin(User user, QrLoginConfirmRequest.WechatMiniProgramInfo wechatInfo) {
        // 更新用户的微信信息
        if (StrUtil.isNotBlank(wechatInfo.getOpenid())) {
            user.setOpenid(wechatInfo.getOpenid());
        }
        if (StrUtil.isNotBlank(wechatInfo.getUnionid())) {
            user.setUnionid(wechatInfo.getUnionid());
        }
        if (StrUtil.isNotBlank(wechatInfo.getNickname()) && StrUtil.isBlank(user.getNickname())) {
            user.setNickname(wechatInfo.getNickname());
        }
        if (StrUtil.isNotBlank(wechatInfo.getAvatar()) && StrUtil.isBlank(user.getAvatar())) {
            user.setAvatar(wechatInfo.getAvatar());
        }

        // 更新用户信息到数据库
        try {
            userService.updateById(user);
            log.info("更新用户 {} 的微信小程序信息成功", user.getUsername());
        } catch (Exception e) {
            log.warn("更新用户 {} 的微信小程序信息失败: {}", user.getUsername(), e.getMessage());
        }
    }

    @Override
    public boolean scanQrCode(String token) {
        if (StrUtil.isBlank(token)) {
            return false;
        }

        String redisKey = QR_LOGIN_TOKEN_KEY + token;
        QrLoginData qrLoginData = redisUtil.get(redisKey, QrLoginData.class);

        if (qrLoginData == null) {
            return false;
        }

        // 检查是否过期
        if (LocalDateTime.now().isAfter(qrLoginData.getExpireTime())) {
            redisUtil.delete(redisKey);
            return false;
        }

        // 只有pending状态才能更新为scanned
        if (QR_LOGIN_STATUS_PENDING.equals(qrLoginData.getStatus())) {
            qrLoginData.setStatus(QR_LOGIN_STATUS_SCANNED);

            // 计算剩余过期时间
            long remainingSeconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), qrLoginData.getExpireTime());
            redisUtil.set(redisKey, qrLoginData, remainingSeconds, TimeUnit.SECONDS);

            log.info("扫码登录token {} 状态更新为已扫码", token);
            return true;
        }

        return false;
    }
}
