package org.dromara.web.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.lang.Dict;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.model.WechatAppletLoginBody;
import org.dromara.common.core.enums.EmployeeStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.ValidatorUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.wechat.config.WechatConfig;
import org.dromara.system.domain.vo.SysClientVo;
import org.dromara.system.domain.vo.SysEmployeeVo;
import org.dromara.system.service.ISysEmployeeService;
import org.dromara.web.domain.vo.LoginVo;
import org.dromara.web.service.IAuthStrategy;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Slf4j
@Service("wechatApplet" + IAuthStrategy.BASE_NAME)
@RequiredArgsConstructor
public class WechatAppletAuthStrategy implements IAuthStrategy {

    private final WechatConfig wechatConfig;
    private final ISysEmployeeService employeeService;

    @Override
    public LoginVo login(String body, SysClientVo client) {
        WechatAppletLoginBody loginBody = JsonUtils.parseObject(body, WechatAppletLoginBody.class);
        ValidatorUtils.validate(loginBody);

        String loginCode = loginBody.getLoginCode();
        if (StringUtils.isEmpty(loginCode)) {
            throw new ServiceException("登录code不能为空");
        }

        String appId = wechatConfig.getAppId();
        String appSecret = wechatConfig.getAppSecret();

        String loginInformation = getLoginInfoByCode(loginCode, appId, appSecret);
        Dict response;
        try {
            response = JsonUtils.parseMap(loginInformation);
        } catch (Exception e) {
            log.error("微信登录返回值解析失败 : {}", e.getMessage());
            throw new ServiceException("微信平台对接失败");
        }

        if (Objects.isNull(response)) {
            throw new ServiceException("微信平台对接失败");
        }

        if (response.containsKey("errcode") && response.getInt("errcode") != 0) {
            log.error("微信登陆失败 : {}", response.getStr("errmsg"));
            throw new ServiceException("微信登陆失败 : 获取 open ID 失败");
        }

        if (!response.containsKey("openid")) {
            throw new ServiceException("open ID 获取失败!");
        }
        String openId = response.getStr("openid");

        String unionId = response.containsKey("unionid") ? response.getStr("unionid") : "";

        SysEmployeeVo employee = employeeService.queryByWechatOpenid(openId);

        if (Objects.isNull(employee)) {
            LoginVo loginVo = new LoginVo();
            loginVo.setOpenid(openId);
            return loginVo;
        }

        if (EmployeeStatus.DISABLED.getCode().equals(employee.getStatus())) {
            throw new ServiceException("您的账号已被封禁，请联系管理员");
        }

        LoginVo loginVo = new LoginVo();
        loginVo.setAccessToken(generateToken(employee.getId(), client));
        loginVo.setExpireIn(StpUtil.getTokenTimeout());
        loginVo.setClientId(client.getClientId());
        loginVo.setOpenid(openId);
        return loginVo;
    }

    private String getLoginInfoByCode(String code, String appId, String appSecret) {
        String url = wechatConfig.getLoginUrl() + "?appid=" + appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
        String result;

        try {
            HttpResponse response = HttpRequest.get(url).execute();
            result = response.body();
            log.info("微信一键授权登录返回信息 : {}", result);
        } catch (Exception e) {
            log.error("获取OpenId 发送GET 请求错误 ====>  {}", e.getMessage());
            throw new ServiceException("微信登录失败!");
        }

        if (StringUtils.isEmpty(result)) {
            throw new ServiceException("微信登录失败!");
        }

        return result;
    }

    private String generateToken(Long employeeId, SysClientVo client) {
        org.dromara.common.core.domain.model.LoginUser loginUser = new org.dromara.common.core.domain.model.LoginUser();
        loginUser.setUserId(employeeId);
        loginUser.setUserType(org.dromara.common.core.enums.UserType.APP_USER.getUserType());

        SysEmployeeVo employee = employeeService.queryById(employeeId);
        if (employee != null) {
            loginUser.setUsername(employee.getName());
            loginUser.setNickname(employee.getName());
        }

        SaLoginParameter model = new SaLoginParameter();
        model.setDeviceType(client.getDeviceType());
        model.setTimeout(client.getTimeout());
        model.setActiveTimeout(client.getActiveTimeout());
        model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());

        // 使用 LoginHelper 进行标准登录，确保 Extra 信息（如 userId）被注入
        LoginHelper.login(loginUser, model);

        return StpUtil.getTokenValue();
    }
}
