package com.gxwebsoft.auto.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.gxwebsoft.auto.dto.*;
import com.gxwebsoft.auto.service.QrLoginService;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.security.JwtSubject;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.common.system.service.WxService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.HashMap;
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;

  @Autowired
  private ConfigProperties configProperties;

  @Autowired
  private WxService wxService;

  private static final String QR_LOGIN_TOKEN = "QR_LOGIN_TOKEN";

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

    // 创建扫码登录数据
    QrLoginData qrLoginData = new QrLoginData();
    qrLoginData.setToken(token);
    qrLoginData.setStatus(QR_LOGIN_STATUS_PENDING);
    qrLoginData.setTenantId(tenantId);
    qrLoginData.setCreateTime(DateUtil.formatDateTime(DateUtil.date()));
    qrLoginData.setExpireTime(DateUtil.formatDateTime(DateUtil.offsetSecond(DateUtil.date(), QR_LOGIN_TOKEN_TTL.intValue())));

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

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

    // 构造响应对象
    QrLoginGenerateResponse response = new QrLoginGenerateResponse();
    response.setToken(token);
    response.setExpiresIn(QR_LOGIN_TOKEN_TTL);

    // APP扫码内容
    response.setQrCodeContent("qr-login:" + token);

    // 微信小程序路径
    response.setMiniprogramPath("/pages/qr-login?token=" + token);

    // 生成微信小程序码
    try {
      String miniprogramQrCodeUrl = generateMiniprogramQrCode(token,tenantId);
      response.setMiniprogramQrCodeUrl(miniprogramQrCodeUrl);
    } catch (Exception e) {
      log.warn("生成微信小程序码失败: {}", e.getMessage());
      // 小程序码生成失败不影响整体功能，继续返回其他信息
    }

    return response;
  }

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

    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, null);
    }

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

    // 计算剩余过期时间
    long expiresIn = (DateUtil.parseDateTime(qrLoginData.getExpireTime()).getTime() - DateUtil.date().getTime()) / 1000;

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

    // 如果已确认，返回token和用户信息
    if (QR_LOGIN_STATUS_CONFIRMED.equals(qrLoginData.getStatus())) {
      response.setAccessToken(qrLoginData.getAccessToken());
      // 获取用户信息
      if (qrLoginData.getUserId() != null) {
        User user = userService.getAllByUserId("" + 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();

    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 (DateUtil.date().after(DateUtil.parseDateTime(qrLoginData.getExpireTime()))) {
      redisUtil.delete(redisKey);
      throw new RuntimeException("扫码登录token已过期");
    }

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

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

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

    // 更新扫码登录数据
    qrLoginData.setStatus(QR_LOGIN_STATUS_CONFIRMED);
    qrLoginData.setUserId(userId);
    qrLoginData.setUsername(user.getUsername());
    qrLoginData.setAccessToken(accessToken);
    qrLoginData.setTenantId(user.getTenantId());
    // 更新Redis中的数据
    redisUtil.set(redisKey, qrLoginData, 60L, TimeUnit.SECONDS); // 给前端60秒时间获取token

    log.info("用户 {} 确认扫码登录，token: {}", user.getUsername(), token);

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

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

  @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 (DateUtil.date().after(DateUtil.parseDateTime(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 = (DateUtil.parseDateTime(qrLoginData.getExpireTime()).getTime() - DateUtil.date().getTime()) / 1000;
      redisUtil.set(redisKey, qrLoginData, remainingSeconds, TimeUnit.SECONDS);

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

    return false;
  }

  /**
   * 生成微信小程序码
   */
  private String generateMiniprogramQrCode(String token, Integer tenantId) {
    try {
      // 使用公共的 WxService 获取 AccessToken
      String accessToken = wxService.getAccessToken(tenantId);
      if (StrUtil.isBlank(accessToken)) {
        throw new RuntimeException("获取微信AccessToken失败");
      }

      String apiUrl = "https://api.weixin.qq.com/wxa/getwxacode?access_token=" + accessToken;
      HashMap<String, Object> params = new HashMap<>();
      params.put("path", "/pages/qr-login?token=" + token);
      params.put("width", 430); // 二维码宽度，默认430px

      // 调用微信API生成小程序码
      byte[] qrCodeBytes = HttpRequest.post(apiUrl)
          .body(JSON.toJSONString(params))
          .execute().bodyBytes();

      // 保存文件
      String fileName = "qr-login-" + token + ".png";
      String uploadPath = getUploadPath();
      String filePath = uploadPath + "qrcode/" + fileName;

      // 确保目录存在
      File dir = new File(uploadPath + "qrcode/");
      if (!dir.exists()) {
        dir.mkdirs();
      }

      File file = FileUtil.writeBytes(qrCodeBytes, filePath);
      if (file != null && file.exists()) {
        // 返回可访问的URL
        return configProperties.getFileServer() + "/qrcode/" + fileName;
      } else {
        throw new RuntimeException("保存小程序码文件失败");
      }
    } catch (Exception e) {
      log.error("生成微信小程序码失败: {}", e.getMessage(), e);
      throw new RuntimeException("生成微信小程序码失败: " + e.getMessage());
    }
  }



  /**
   * 获取文件上传路径
   */
  private String getUploadPath() {
    String uploadPath = configProperties.getUploadPath();
    if (StrUtil.isBlank(uploadPath)) {
      uploadPath = configProperties.getLocalUploadPath();
    }
    if (StrUtil.isBlank(uploadPath)) {
      uploadPath = "/tmp/uploads/";
    }
    if (!uploadPath.endsWith("/")) {
      uploadPath += "/";
    }
    return uploadPath;
  }
}
