package com.ruoyi.framework.web.service;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.imageio.ImageIO;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.WechatLoginStatus;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.WechatProperties;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.mapper.WechatLoginStatusMapper;

import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;

/**
 * 微信服务
 * 
 * @author ruoyi
 */
@Service
public class WechatService 
{
    private static final Logger log = LoggerFactory.getLogger(WechatService.class);

    @Autowired
    private WxMpService wxMpService;
    
    @Autowired
    private WechatProperties wechatProperties;
    
    @Autowired
    private WechatLoginStatusMapper wechatLoginStatusMapper;

    @Autowired
    private SysUserMapper userMapper;

    /**
     * 生成微信登录二维码
     * 
     * @return 包含二维码信息的Map
     */
    public Map<String, Object> generateLoginQrCode() throws WxErrorException, IOException, com.google.zxing.WriterException 
    {
        // 生成唯一的登录状态ID
        String loginId = UUID.randomUUID().toString().replace("-", "");
        String sceneStr = wechatProperties.getQrScenePrefix() + loginId;
        
        // 创建临时二维码
        WxMpQrCodeTicket ticket = wxMpService.getQrcodeService().qrCodeCreateTmpTicket(sceneStr, wechatProperties.getQrExpireTime());
        String qrCodeUrl = wxMpService.getQrcodeService().qrCodePictureUrl(ticket.getTicket());
        
        // 生成本地二维码图片
        try {
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            BitMatrix bitMatrix = qrCodeWriter.encode(qrCodeUrl, BarcodeFormat.QR_CODE, 200, 200);
            BufferedImage qrCodeImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(qrCodeImage, "png", baos);
            String base64Image = "data:image/png;base64," + java.util.Base64.getEncoder().encodeToString(baos.toByteArray());
        
            // 保存登录状态到数据库
            WechatLoginStatus loginStatus = new WechatLoginStatus();
            loginStatus.setId(loginId);
            loginStatus.setQrCodeUrl(qrCodeUrl);
            loginStatus.setStatus("0"); // 待扫码
            
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.SECOND, wechatProperties.getQrExpireTime());
            loginStatus.setExpireTime(calendar.getTime());
            loginStatus.setCreateTime(new Date());
            loginStatus.setUpdateTime(new Date());
            
            wechatLoginStatusMapper.insertWechatLoginStatus(loginStatus);
            
            // 返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("loginId", loginId);
            result.put("qrCodeUrl", qrCodeUrl);
            result.put("qrCodeImage", base64Image);
            result.put("expireTime", wechatProperties.getQrExpireTime());
            
            return result;
        } catch (com.google.zxing.WriterException e) {
            log.error("生成二维码失败", e);
            throw e;
        }
    }

    /**
     * 获取微信OAuth2授权URL
     * 
     * @param state 状态参数
     * @return 授权URL
     */
    public String getOAuth2AuthorizeUrl(String state) 
    {
        return wxMpService.getOAuth2Service().buildAuthorizationUrl(
            wechatProperties.getRedirectUri(), 
            "snsapi_userinfo", 
            state
        );
    }

    /**
     * 通过授权码获取用户信息
     * 
     * @param code 授权码
     * @return 用户信息
     */
    public WxOAuth2UserInfo getUserInfo(String code) throws WxErrorException 
    {
        WxOAuth2AccessToken accessToken = wxMpService.getOAuth2Service().getAccessToken(code);
        return wxMpService.getOAuth2Service().getUserInfo(accessToken, null);
    }

    /**
     * 检查登录状态
     * 
     * @param loginId 登录ID
     * @return 登录状态信息
     */
    public Map<String, Object> checkLoginStatus(String loginId) 
    {
        WechatLoginStatus loginStatus = wechatLoginStatusMapper.selectWechatLoginStatusById(loginId);
        Map<String, Object> result = new HashMap<>();
        
        if (loginStatus == null) {
            result.put("status", "3"); // 已过期
            result.put("message", "登录状态不存在或已过期");
            return result;
        }
        
        // 检查是否过期
        if (new Date().after(loginStatus.getExpireTime())) {
            result.put("status", "3"); // 已过期
            result.put("message", "二维码已过期");
            return result;
        }
        
        result.put("status", loginStatus.getStatus());
        result.put("userId", loginStatus.getUserId());
        
        switch (loginStatus.getStatus()) {
            case "0":
                result.put("message", "等待扫码");
                break;
            case "1":
                result.put("message", "已扫码，等待确认");
                break;
            case "2":
                result.put("message", "登录成功");
                break;
            default:
                result.put("message", "未知状态");
                break;
        }
        
        return result;
    }

    /**
     * 更新登录状态
     * 
     * @param loginId 登录ID
     * @param status 状态
     * @param userId 用户ID
     * @param openid 微信openid
     */
    public void updateLoginStatus(String loginId, String status, Long userId, String openid) 
    {
        WechatLoginStatus loginStatus = new WechatLoginStatus();
        loginStatus.setId(loginId);
        loginStatus.setStatus(status);
        loginStatus.setUserId(userId);
        loginStatus.setOpenid(openid);
        loginStatus.setUpdateTime(new Date());
        
        wechatLoginStatusMapper.updateWechatLoginStatus(loginStatus);
    }

    /**
     * 根据场景值解析登录ID
     * 
     * @param sceneStr 场景值
     * @return 登录ID
     */
    public String parseLoginIdFromScene(String sceneStr) 
    {
        if (StringUtils.isNotEmpty(sceneStr) && sceneStr.startsWith(wechatProperties.getQrScenePrefix())) {
            return sceneStr.substring(wechatProperties.getQrScenePrefix().length());
        }
        return null;
    }

    /**
     * 微信回调处理
     * 
     * @param code 授权码
     * @param state 状态参数
     * @return 处理结果
     */
    public AjaxResult handleWechatCallback(String code, String state) 
    {
        try {
            if (StringUtils.isEmpty(code)) {
                return AjaxResult.error("授权码不能为空");
            }
            
            // 获取用户信息
            WxOAuth2UserInfo userInfo = getUserInfo(code);
            
            // 解析登录ID
            String loginId = parseLoginIdFromScene(state);
            if (StringUtils.isEmpty(loginId)) {
                return AjaxResult.error("无效的登录状态");
            }
            
            // 查询登录状态
            WechatLoginStatus loginStatus = wechatLoginStatusMapper.selectWechatLoginStatusById(loginId);
            if (loginStatus == null) {
                return AjaxResult.error("登录状态不存在或已过期");
            }
            
            // 检查是否过期
            if (new Date().after(loginStatus.getExpireTime())) {
                return AjaxResult.error("二维码已过期");
            }
            
            // 更新登录状态为已扫码
            updateLoginStatus(loginId, "1", null, userInfo.getOpenid());
            
            // 查询用户是否已绑定
            SysUser user = userMapper.selectUserByWechatOpenid(userInfo.getOpenid());
            Long userId = null;
            
            if (user != null) {
                // 用户已绑定，直接更新用户微信信息
                user.setWechatNickname(userInfo.getNickname());
                user.setWechatAvatar(userInfo.getHeadImgUrl());
                userMapper.updateUser(user);
                userId = user.getUserId();
            } else {
                // 用户未绑定，创建新用户或提示绑定
                // 这里可以根据业务需求决定是自动创建用户还是提示用户绑定
                // 为了演示，我们创建一个新用户
                user = new SysUser();
                user.setUserName("wechat_" + userInfo.getOpenid().substring(0, 10));
                user.setNickName(userInfo.getNickname());
                user.setWechatOpenid(userInfo.getOpenid());
                user.setWechatUnionid(userInfo.getUnionId());
                user.setWechatNickname(userInfo.getNickname());
                user.setWechatAvatar(userInfo.getHeadImgUrl());
                user.setBindWechat("1");
                user.setStatus("0"); // 正常状态
                user.setDelFlag("0"); // 未删除
                user.setPassword("123456"); // 默认密码
                userMapper.insertUser(user);
                userId = user.getUserId();
            }
            
            // 更新登录状态为已确认
            updateLoginStatus(loginId, "2", userId, userInfo.getOpenid());
            
            return AjaxResult.success("登录成功");
        } catch (WxErrorException e) {
            log.error("微信回调处理失败", e);
            return AjaxResult.error("微信回调处理失败: " + e.getMessage());
        }
    }
}