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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.czg.account.dto.user.SysUserAddDTO;
import com.czg.account.dto.user.SysUserEditDTO;
import com.czg.account.dto.user.SysUserEditPwdDTO;
import com.czg.account.entity.SysRole;
import com.czg.account.entity.SysUser;
import com.czg.account.entity.SysUsersRoles;
import com.czg.account.service.SysUserService;
import com.czg.account.vo.SysUserDetailVO;
import com.czg.config.RedisCst;
import com.czg.exception.CzgException;
import com.czg.sa.StpKit;
import com.czg.service.RedisService;
import com.czg.service.account.mapper.SysRoleMapper;
import com.czg.service.account.mapper.SysUserMapper;
import com.czg.service.account.mapper.SysUsersRolesMapper;
import com.czg.utils.CzgStrUtils;
import com.czg.utils.PageUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

/**
 * 系统用户 服务层实现。
 *
 * @author Administrator
 * @since 2025-02-08
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Resource
    private SysRoleMapper sysRoleMapper;
    @Resource
    private SysUsersRolesMapper sysUsersRolesMapper;
    @Resource
    private RedisService redisService;

    @Override
    public SysUser addUser(String nickname, String accountName, String accountPwd, String phone, Long roleId) {
        long count = queryChain().eq(SysUser::getAccount, accountName).count();
        if (count > 0) {
            throw new CzgException("账号已存在");
        }
        // 添加系统账号
        SysUser sysUser = new SysUser();
        sysUser.setAccount(accountName);
        sysUser.setNickName(nickname);
        sysUser.setPhone(phone);
        sysUser.setStatus(1);
        sysUser.setCreateUserId(StpKit.USER.getLoginIdAsLong());
        save(sysUser);
        sysUser.setPassword(SecureUtil.md5(sysUser.getId() + accountPwd));
        updateById(sysUser);

        // 绑定角色
        long roleCount = sysRoleMapper.selectCountByQuery(new QueryWrapper().eq(SysRole::getId, roleId).eq(SysRole::getCreateUserId, StpKit.USER.isAdmin() ? null : StpKit.USER.getLoginIdAsLong()));
        if (roleCount == 0) {
            throw new CzgException("角色不存在");
        }
        SysUsersRoles usersRoles = new SysUsersRoles();
        usersRoles.setUserId(sysUser.getId());
        usersRoles.setRoleId(roleId);
        sysUsersRolesMapper.insert(usersRoles);

        return sysUser;
    }

    @Override
    public Boolean updateSysUserPwd(long sysUserId, String accountPwd) {
        SysUser sysUser = new SysUser();
        sysUser.setId(sysUserId);
        sysUser.setPassword(SecureUtil.md5(sysUser.getId() + accountPwd));
        sysUser.setUpdateUserId(sysUserId);
        sysUser.setUpdateTime(DateUtil.date().toLocalDateTime());
        sysUser.setPwdResetTime(DateUtil.date().toLocalDateTime());
        return updateById(sysUser);
    }

    @Override
    public Boolean removeUserAndRole(Long id) {
        sysUsersRolesMapper.deleteByQuery(new QueryWrapper().eq(SysUsersRoles::getUserId, id));
        return removeById(id);
    }

    @Override
    public Page<SysUserDetailVO> getPage(String key, String startTime, String endTime, Integer status) {
        PageHelper.startPage(PageUtil.buildPageHelp());
        return PageUtil.convert(new PageInfo<>(mapper.page(key, startTime, endTime, status)));
    }

    @Override
    public Boolean edit(SysUserEditDTO sysUserEditDTO) {
        if (StrUtil.isNotBlank(sysUserEditDTO.getAccount())) {
            long count = count(new QueryWrapper().eq(SysUser::getAccount, sysUserEditDTO.getAccount()).ne(SysUser::getId, sysUserEditDTO.getId()));
            if (count > 0) {
                throw new CzgException("账号已存在");
            }
        }

        SysUser sysUser = getById(sysUserEditDTO.getId());
        BeanUtil.copyProperties(sysUserEditDTO, sysUser);
        if (StrUtil.isNotBlank(sysUserEditDTO.getPassword())) {
            sysUser.setPassword(SecureUtil.md5(sysUser.getId() + sysUserEditDTO.getPassword()));
            sysUser.setPwdResetTime(DateUtil.date().toLocalDateTime());
        }

        if (sysUserEditDTO.getRoleId() != null) {
            SysUsersRoles usersRoles = new SysUsersRoles();
            usersRoles.setRoleId(sysUserEditDTO.getRoleId());
            usersRoles.setUserId(sysUser.getId());
            sysUsersRolesMapper.updateByQuery(usersRoles, new QueryWrapper().eq(SysUsersRoles::getUserId, sysUser.getId()));
        }
        return updateById(sysUser);
    }

    @Override
    public Boolean delete(Integer id) {
        SysUser sysUser = getById(id);
        if (sysUser == null) {
            throw new CzgException("用户不存在");
        }
        boolean remove = remove(new QueryWrapper().eq(SysUser::getId, id));
        if (remove) {
            int i = sysUsersRolesMapper.deleteByQuery(new QueryWrapper().eq(SysUsersRoles::getUserId, id));
            return i > 0;
        }
        return false;
    }

    @Override
    public Boolean add(SysUserAddDTO sysUserAddDTO) {
        long count = count(new QueryWrapper().eq(SysUser::getAccount, sysUserAddDTO.getAccount()));
        if (count > 0) {
            throw new CzgException("账号已存在");
        }

        SysUser sysUser = BeanUtil.copyProperties(sysUserAddDTO, SysUser.class);
        boolean save = save(sysUser);
        if (save) {
            sysUser.setPassword(SecureUtil.md5(sysUser.getId() + sysUserAddDTO.getPassword()));
        }

        SysUsersRoles usersRoles = new SysUsersRoles();
        usersRoles.setRoleId(sysUserAddDTO.getRoleId());
        usersRoles.setUserId(sysUser.getId());
        sysUsersRolesMapper.insert(usersRoles);
        return updateById(sysUser);
    }

    @Override
    public void download(String key, String startTime, String endTime, Integer status, HttpServletResponse response) throws IOException {
        Page<SysUserDetailVO> sysUserPage = getPage(key, startTime, endTime, status);
        List<SysUserDetailVO> records = sysUserPage.getRecords();

        // 1. 创建 ExcelWriter
        // true 表示使用 XLSX 格式
        ExcelWriter writer = ExcelUtil.getWriter(true);

        // 2. 写入数据
        writer.write(records, true);

        // 3. 设置响应头，返回 Excel
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("用户列表.xlsx", "UTF-8"));

        // 4. 写入到响应流
        writer.flush(response.getOutputStream(), true);
        writer.close();
    }

    @Override
    public SysUserDetailVO detail(Integer id) {
        SysUser sysUser = getById(id);
        SysUsersRoles usersRoles = sysUsersRolesMapper.selectOneByQuery(new QueryWrapper().eq(SysUsersRoles::getUserId, id));
        SysUserDetailVO sysUserDetailVO = BeanUtil.copyProperties(sysUser, SysUserDetailVO.class);
        sysUserDetailVO.setRoleId(usersRoles.getRoleId());
        return sysUserDetailVO;
    }

    @Override
    public Boolean editPwd(SysUserEditPwdDTO sysUserEditPwdDTO) {
        SysUser sysUser;
        if (sysUserEditPwdDTO.getId() == null) {
            sysUserEditPwdDTO.setId(StpKit.USER.getLoginIdAsLong());
            sysUser = getById(sysUserEditPwdDTO.getId());
        } else {
            sysUser = getById(sysUserEditPwdDTO.getId());
            if (sysUser.getAccount().contains("@")) {
                if (!sysUser.getAccount().split("@")[0].equals(StpKit.USER.getShopId().toString())) {
                    throw new CzgException("修改失败");
                }
            } else {
                throw new CzgException("修改失败");
            }
        }
        if (StrUtil.isNotBlank(sysUserEditPwdDTO.getCode())) {
            Object value = redisService.get(RedisCst.SMS_CODE + sysUser.getPhone() + ":shopPwd");
            if (!sysUserEditPwdDTO.getCode().equals(value)) {
                throw new CzgException("验证码不正确");
            }
        } else if (StrUtil.isNotBlank(sysUserEditPwdDTO.getOriginalPassword()) &&
                !sysUser.getPassword().equals(SecureUtil.md5(sysUser.getId() + sysUserEditPwdDTO.getOriginalPassword()))) {
            throw new CzgException("原密码不正确");
        } else {
            throw new CzgException("修改失败");
        }

        if (!sysUserEditPwdDTO.getPassword().equals(sysUserEditPwdDTO.getCheckPassword())) {
            throw new CzgException("新密码与确认密码不一致");
        }
        CzgStrUtils.checkPwd(sysUserEditPwdDTO.getPassword());
        sysUser.setPassword(SecureUtil.md5(sysUser.getId() + sysUserEditPwdDTO.getPassword()));
        boolean isUp = updateById(sysUser);
        if (isUp) {
            redisService.del(STR."token:admin:session:\{sysUser.getId()}");
        }
        return isUp;
    }
}
