/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yami.shop.bean.app.param.UserRegisterParam;
import com.yami.shop.bean.model.Channel;
import com.yami.shop.bean.model.SysDictData;
import com.yami.shop.bean.model.User;
import com.yami.shop.bean.po.EnterpriseUserErrExcelInfo;
import com.yami.shop.bean.po.EnterpriseUserExcelInfo;
import com.yami.shop.bean.po.EnterpriseUserLogPo;
import com.yami.shop.bean.po.EnterpriseUserPo;
import com.yami.shop.bean.vo.EnterpriseUserVo;
import com.yami.shop.bean.vo.UserPointsVO;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.util.IPHelper;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.dao.ChannelMapper;
import com.yami.shop.dao.SysDictDataMapper;
import com.yami.shop.dao.SysDictTypeMapper;
import com.yami.shop.dao.UserMapper;
import com.yami.shop.service.UserExtensionService;
import com.yami.shop.service.UserService;
import com.yami.shop.utils.CullenUtils;
import com.yami.shop.utils.ExportUtils;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/09/11.
 */
@Service
@Slf4j
@AllArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final UserMapper userMapper;
    private final ChannelMapper channelMapper;
    private final UserExtensionService userExtensionService;

    @Autowired
    private SysDictDataMapper dictDataMapper;


    @Override
    public User getUserByUserId(String userId) {
        return userMapper.selectById(userId);
    }

    @Override
    public void setUserLevelBylevelId(Integer level) {
        userMapper.setUserLevelBylevelId(level);
        userExtensionService.setUserLevelBylevelId(level);
    }

    @Override
    public void setUserLevelByGrowth(Integer level, Integer minNeedGrowth, Integer maxNeedGrowth) {
        userMapper.setMaxUserLevelBylevelId(level, minNeedGrowth, maxNeedGrowth);
        userExtensionService.setMaxUserLevelByLevelId(level, minNeedGrowth, maxNeedGrowth);
    }


    /**
     * 看看有没有校验验证码成功的标识
     *
     * @param userRegisterParam
     * @param checkRegisterSmsFlag
     */
    @Override
    public void validate(UserRegisterParam userRegisterParam, String checkRegisterSmsFlag) {
        if (StrUtil.isBlank(userRegisterParam.getCheckRegisterSmsFlag())) {
            throw new GlobalException("验证码已过期，请重新发送验证码校验");
        } else {
            String checkRegisterSmsFlagMobile = RedisUtil.get(checkRegisterSmsFlag);
            if (!Objects.equals(checkRegisterSmsFlagMobile, userRegisterParam.getMobile())) {
                throw new GlobalException("验证码已过期，请重新发送验证码校验");
            }
        }
    }

    @Override
    public IPage<User> getUserPage(PageParam<User> page, User user) {
        return userMapper.getUserPage(page, user);
    }

    @Override
    public IPage<UserPointsVO> statisticsList(PageParam<User> pageParam, User user) {
        return userMapper.statisticsList(pageParam, user);
    }

    @Override
    public IPage<EnterpriseUserVo> enterpriseUserList(PageParam<EnterpriseUserPo> page, EnterpriseUserPo po) {
        return userMapper.enterpriseUserList(page, po);
    }

    @Override
    public void downloadExcelGoods(HttpServletResponse response) {
        ServletOutputStream outputStream = null;
        try {
            // 重置响应，避免之前的数据影响
            response.reset();

            // 先设置响应头
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            String fileName = URLEncoder.encode("企业员工导入模板", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            // 查询数据
            List<SysDictData> userAttrTypeList = dictDataMapper.selectDictDataByType("user_attr_type");
            String userAttrName = null;
            if (userAttrTypeList != null && !userAttrTypeList.isEmpty()) {
                userAttrName = userAttrTypeList.stream()
                        .filter(data -> data.getDictCode() != 1L)
                        .map(SysDictData::getDictLabel)
                        .collect(Collectors.joining(";"));
            }

            // 准备数据
            List<EnterpriseUserExcelInfo> list = Lists.newArrayList();
            EnterpriseUserExcelInfo enterpriseUserExcelInfo = new EnterpriseUserExcelInfo();
            enterpriseUserExcelInfo.setChannel("必填！");
            enterpriseUserExcelInfo.setRealName("必填！");

            if (StringUtils.isNotEmpty(userAttrName)) {
                enterpriseUserExcelInfo.setUserAttrName("必填！" + userAttrName);
            } else {
                enterpriseUserExcelInfo.setUserAttrName("必填！且值为1");
            }

            enterpriseUserExcelInfo.setPhone("必填！必须输入真实手机号,且该手机号码有微信");
            list.add(enterpriseUserExcelInfo);

            // 获取输出流
            outputStream = response.getOutputStream();

            // 写入Excel
            EasyExcel.write(outputStream, EnterpriseUserExcelInfo.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .sheet("列表")
                    .doWrite(list);
            // 刷新流
            outputStream.flush();

        } catch (Exception e) {
            log.error("下载Excel模板失败", e);
        }
    }

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public void uploadExcelGoods(MultipartFile file,String username) {
        List<SysDictData> userAttrTypeList = dictDataMapper.selectDictDataByType("user_attr_type");//查询人员属性
        List<EnterpriseUserExcelInfo> goodsInfoList = Lists.newArrayList();
        String batchNo = String.valueOf(System.currentTimeMillis());
        EasyExcel.read(file.getInputStream(), EnterpriseUserExcelInfo.class, new PageReadListener<EnterpriseUserExcelInfo>(goodsInfoList::addAll)).sheet().doRead();
        CullenUtils.validateDataThrowException(goodsInfoList.isEmpty(), "请上传企业用户信息...");
        goodsInfoList.forEach(c -> {
            CullenUtils.validateDataThrowException(c.getChannel().contains("必填"), "请删除示例后重试...");
            CullenUtils.validateDataThrowException(c.getPhone()==null,"手机号不能为空...");
            CullenUtils.validateDataThrowException(c.getChannel()==null,"渠道不能为空...");
            CullenUtils.validateDataThrowException(c.getRealName()==null,"姓名不能为空...");
            CullenUtils.validateDataThrowException(c.getUserAttrName()==null,"人员属性不能为空...");
            String userAttrType = getUserAttrType(c.getUserAttrName().replaceAll("\\s+", ""), userAttrTypeList);
            String phone = c.getPhone().replaceAll("\\s+", "");
            if (phone.length()!=11||!CullenUtils.isNumeric(phone)||"0".equals(userAttrType)) {
                userMapper.addUserLog(username,batchNo,"0",c.getChannel(),c.getRealName(),c.getPhone(),userAttrType);
            }else {
                addUser(new EnterpriseUserPo(getChannel(c.getChannel()), c.getRealName(), c.getPhone(),userAttrType));
                userMapper.addUserLog(username,batchNo,"1",c.getChannel(),c.getRealName(),c.getPhone(),userAttrType);
            }
        });
    }

    @Override
    public void addUser(EnterpriseUserPo po) {
        User userInfo = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUserMobile, po.getUserMobile()));
        if (userInfo==null) {
            User user = new User();
            user.setUserName(po.getUserMobile());
            user.setNickName("企业用户");
            user.setRealName(po.getRealName());
            user.setUserMobile(po.getUserMobile());
            user.setModifyTime(new Date());
            user.setUserRegtime(new Date());
            user.setUserRegip(IPHelper.getIpAddr());
            user.setPic("https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132");
            user.setStatus(1);
            user.setLevel(1);
            user.setLevelType(0);
            user.setChannelId(po.getChannelId());
            user.setChannelId(po.getChannelId());
            user.setUserId(IdUtil.simpleUUID());
            save(user);
        }else {
            System.out.println("已存在...");
            User user = new User();
            user.setNickName("企业用户");
            user.setModifyTime(new Date());
            user.setRealName(po.getRealName());
            user.setChannelId(po.getChannelId());
            user.setUserId(userInfo.getUserId());
            userMapper.updateById(user);
        }
    }

    @Override
    public void addUser2(EnterpriseUserPo po) {
        User userInfo = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUserMobile, po.getUserMobile()));
        if (userInfo==null) {
            User user = new User();
            user.setUserName(po.getUserMobile());
            user.setNickName("企业用户");
            user.setRealName(po.getRealName());
            user.setUserMobile(po.getUserMobile());
            user.setModifyTime(new Date());
            user.setUserRegtime(new Date());
            user.setUserRegip(IPHelper.getIpAddr());
            user.setPic("https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132");
            user.setStatus(1);
            user.setLevel(1);
            user.setLevelType(0);
            user.setUserAttrType(po.getUserAttrType());
            user.setChannelId(po.getChannelId());
            user.setChannelId(po.getChannelId());
            user.setUserId(IdUtil.simpleUUID());
            save(user);
        }else {
            System.out.println("已存在...");
            if (userInfo.getChannelId()==null){
                User user = new User();
                user.setNickName("企业用户");
                user.setModifyTime(new Date());
                user.setRealName(po.getRealName());
                user.setChannelId(po.getChannelId());
                user.setUserId(userInfo.getUserId());
                user.setUserAttrType(po.getUserAttrType());
                userMapper.updateById(user);
            }else {
                if (userInfo.getChannelId().equals(po.getChannelId())){
                    throw new GlobalException("系统已存在该员工，请勿重复添加...");
                }else {
                    User user = new User();
                    user.setNickName("企业用户");
                    user.setModifyTime(new Date());
                    user.setRealName(po.getRealName());
                    user.setChannelId(po.getChannelId());
                    user.setUserId(userInfo.getUserId());
                    user.setUserAttrType(po.getUserAttrType());
                    userMapper.updateById(user);
                }
            }
        }
    }


    @Override
    public IPage<EnterpriseUserLogPo> enterpriseUserLogList(PageParam<EnterpriseUserLogPo> page) {
        return userMapper.enterpriseUserLogList(page);
    }

    @Override
    public IPage<User> userList(PageParam<User> page, User user) {
        return userMapper.userList(page, user);
    }

    @Override
    public void downloadErrorExcel(HttpServletResponse response, String batchNo) {
        try {
            System.out.println(batchNo);
            List<EnterpriseUserLogPo> userLogErrList = userMapper.enterpriseUserLogErrList(batchNo);
            CullenUtils.validateDataThrowException(userLogErrList.isEmpty(),"该记录暂无错误日志...");
            List<EnterpriseUserErrExcelInfo> list = Lists.newArrayList();
            userLogErrList.forEach(c-> list.add(new EnterpriseUserErrExcelInfo("手机号格式错误",c.getChannel(),c.getRealName(),c.getPhone())));
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("企业员工", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), EnterpriseUserErrExcelInfo.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .sheet("列表").doWrite(list);
        } catch (IOException e) {
            throw new GlobalException("文件下载异常");
        }
    }

    private Long getChannel(String channel) {
        List<Channel> channelList = channelMapper.selectList(new LambdaQueryWrapper<Channel>().like(Channel::getChannelName, channel));
        CullenUtils.validateDataThrowException(channelList.isEmpty(), "没有该渠道，请检查后重试...");
        CullenUtils.validateDataThrowException(channelList.size() > 1, "查询到多条渠道，请检查后重试...");
        return channelList.get(0).getId();
    }


    /**
     * 导出用户列表
     * @param po
     * @param response
     */
    @Override
    public void export(EnterpriseUserPo po, HttpServletResponse response) {
      List<EnterpriseUserVo> enterpriseUserVos= userMapper.exportList(po);
        if (enterpriseUserVos.isEmpty()){
            throw new GlobalException("该次导出未查询到数据,不允许导出");
        }
        exportNormalOrders(enterpriseUserVos,response,"员工列表");
    }

    @Override
    public Double test(String userId) {
        return userMapper.test(userId);
    }

    /**
     * 导出正常订单数据到Excel（直接输出到HttpServletResponse）
     */
    public void exportNormalOrders(List<EnterpriseUserVo> orderList,
                                   HttpServletResponse response,
                                   String fileName) {
        // 设置响应头
        ExportUtils.setupResponse(response, fileName);

        try (Workbook workbook = new XSSFWorkbook()) {
            // 创建Sheet
            Sheet sheet = workbook.createSheet("员工列表");

            // 设置列宽
            setupColumnWidth(sheet);

            // 创建表头样式
            CellStyle headerStyle = ExportUtils.createHeaderStyle(workbook);

            // 创建数据样式
            CellStyle dataStyle = ExportUtils.createDataStyle(workbook);
            CellStyle numberStyle = ExportUtils.createNumberStyle(workbook);
            CellStyle dateStyle = ExportUtils.createDateStyle(workbook);


            String[] headers = {
                    "序号","所属企业", "员工姓名", "员工手机号", "总充值积分", "当前可用积分",
                    "已过期积分", "已消耗积分"
            };
            // 创建合并单元格的表头
            ExportUtils.createMergedHeader(sheet, headerStyle,"员工列表",7);

            // 创建列标题行
            ExportUtils.createColumnHeaders(sheet, headerStyle,headers);

            // 填充数据
            fillOrderData(sheet, orderList, dataStyle, numberStyle, dateStyle);

            // 写入响应流
            workbook.write(response.getOutputStream());
            response.getOutputStream().flush();

            log.info("订单导出成功，文件：{}，记录数：{}", fileName, orderList.size());

        } catch (Exception e) {
            log.error("订单导出失败", e);
            throw new RuntimeException("导出失败：" + e.getMessage());
        }
    }

    /**
     * 设置列宽
     */
    private void setupColumnWidth(Sheet sheet) {
        // 根据模板设置列宽（单位：1/256字符宽度）
        sheet.setColumnWidth(0, 12 * 256);   // 序号
        sheet.setColumnWidth(1, 12 * 256);   // 所属企业
        sheet.setColumnWidth(2, 18 * 256);   // 员工姓名
        sheet.setColumnWidth(3, 18 * 256);   // 员工手机号
        sheet.setColumnWidth(4, 10 * 256);   // 总充值积分
        sheet.setColumnWidth(5, 8 * 256);    // 当前可用积分
        sheet.setColumnWidth(6, 25 * 256);   // 已过期积分
        sheet.setColumnWidth(7, 20 * 256);   // 已消耗积分
    }

    /**
     * 填充订单数据
     */
    private void fillOrderData(Sheet sheet, List<EnterpriseUserVo> orderList,
                               CellStyle dataStyle, CellStyle numberStyle, CellStyle dateStyle) {
        int rowNum = 2; // 从第3行开始（0-based索引）
        int indexNum= 1; //序号
        for (EnterpriseUserVo enterpriseUserVo : orderList) {
            Row row = sheet.createRow(rowNum++);
            row.setHeightInPoints(18);
            // 序号
            ExportUtils.createCell(sheet,row, 0,0,0, indexNum, dataStyle);
            fillOrderRowData(sheet,row, enterpriseUserVo, dataStyle, numberStyle, dateStyle);
            indexNum++;
        }

    }

    /**
     * 填充单行订单数据
     */
    private void fillOrderRowData(Sheet sheet,Row row, EnterpriseUserVo orderRefundVo,
                                  CellStyle dataStyle, CellStyle numberStyle, CellStyle dateStyle) {

        // 所属企业
        ExportUtils.createCell(sheet,row, 1,0,0, orderRefundVo.getChannelName(), dataStyle);

        // 员工姓名
        ExportUtils.createCell(sheet,row, 2,0,0,  orderRefundVo.getRealName(), dateStyle);

        // 员工手机号
        ExportUtils.createCell(sheet,row, 3,0,0, orderRefundVo.getUserMobile(), dateStyle);

        // 总充值积分
        ExportUtils.createCell(sheet,row, 4,0,0,orderRefundVo.getTotal(), numberStyle);

        // 可用积分
        ExportUtils.createCell(sheet,row, 5,0,0, orderRefundVo.getAvailable(), numberStyle);
        // 已过期积分
        ExportUtils.createCell(sheet,row, 6,0,0, orderRefundVo.getExpired(), numberStyle);
        // 已消耗积分
        ExportUtils.createCell(sheet,row, 7,0,0, orderRefundVo.getUsed(), numberStyle);
    }

    private String getUserAttrType(String userAttrName,List<SysDictData> sysDictDataList){
        if (StringUtils.isNotEmpty(userAttrName)){
            if (!sysDictDataList.isEmpty()){
                for (SysDictData sysDictData : sysDictDataList) {
                    if (sysDictData.getDictLabel().equals(userAttrName)){
                        return sysDictData.getDictValue();
                    }
                }
                return "0";
            }else if (userAttrName.equals("1")){
                return userAttrName;
            }else {
                return "0";
            }
        }
        return "0";
    }
}
