
package com.yami.shop.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.vo.PointsRechargeVO;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.util.CommonUtils;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.dao.*;
import com.yami.shop.service.PointsFailureRecordService;
import com.yami.shop.service.PointsRechargeService;
import com.yami.shop.service.PointsRecordService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 积分充值 Service实现类
 *
 * @author fbj
 * @since 2025-09-XX
 */
@Service
@AllArgsConstructor
@Slf4j
public class PointsRechargeServiceImpl extends ServiceImpl<PointsRechargeMapper, PointsRecharge> implements PointsRechargeService {

    private final PointsRechargeMapper pointsRechargeMapper;
    private final PointsRecordMapper pointsRecordMapper;
    private final PointsFailureRecordService pointsFailureRecordService;
    private final UserMapper userMapper;
    private final ChannelMapper channelMapper;
    private final PointsRecordService pointsRecordService;

    @Override
    public void exportTemplate(HttpServletResponse response) throws Exception {
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("积分充值导入模板", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        // 创建示例数据
        List<com.yami.shop.service.impl.PointsRechargeTemplateDTO> templateData = new ArrayList<>();
        // 使用EasyExcel导出模板
        EasyExcel.write(response.getOutputStream(), com.yami.shop.service.impl.PointsRechargeTemplateDTO.class)
                .sheet("积分充值导入模板")
                .doWrite(templateData);
    }


    @Override
    public String importPointsRecharge(MultipartFile file, Long userId) throws Exception {
        // 读取Excel数据
        List<com.yami.shop.service.impl.PointsRechargeTemplateDTO> importData = null;
        try {
            importData = EasyExcel.read(file.getInputStream()).head(com.yami.shop.service.impl.PointsRechargeTemplateDTO.class).sheet().doReadSync();
        } catch (IOException e) {
            log.info("导入失败，解析模板有误");
            throw new GlobalException("导入失败，解析模板有误");
        }

        int successCount = 0;
        int failCount = 0;
        String code = CommonUtils.getOrderNo("JF");
        //回去当前登录用户信息


        for (int i = 0; i < importData.size(); i++) {
            com.yami.shop.service.impl.PointsRechargeTemplateDTO templateDTO = importData.get(i);
            try {
                // 数据校验
                CommonUtils.validateCondition(templateDTO.getChannelName() == null,"所属企业不能为空");
                //判断是否存在对应渠道商
                Channel channel = channelMapper.selectOne(new LambdaQueryWrapper<Channel>()
                        .eq(Channel::getChannelName, templateDTO.getChannelName().trim()));
                CommonUtils.validateCondition(channel == null,"渠道商不存在");
                String userName = templateDTO.getUserName();
                CommonUtils.validateCondition(userName == null,"员工名称不能为空");
                CommonUtils.validateCondition(templateDTO.getPoints() == null,"充值积分不能为空");
                CommonUtils.validateCondition(templateDTO.getExpiryDate() == null,"过期时间不能为空");

                // 构造实体对象
                PointsRecharge pointsRecharge = new PointsRecharge();
                String userPhone = templateDTO.getUserPhone();
                CommonUtils.validateCondition(userPhone == null,"员工电话号码不能为空");

                userName = userName.trim();
                userPhone = userPhone.trim();
                //电话号码格式验证
                CommonUtils.validateCondition(!userPhone.matches("^(1(3[0-9]|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\\d{8})$"),"手机号码格式错误");

                //通过用户名称和电话号码校验员工是否存在（存在用户绑定用户，不存在正常添加数据）
                User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                        .eq(User::getUserMobile, userPhone)
                        .eq(User::getStatus, 1)
                        .last("LIMIT 1"));

                CommonUtils.validateCondition(user == null,"员工手机号码不存在");
                pointsRecharge.setUserId(user.getUserId());
                CommonUtils.validateCondition(!userName.equals(user.getRealName()),"员工姓名不正确！");
                CommonUtils.validateCondition(user.getPlatform() == null,"员工未绑定企业，不能导入积分！");
                //小程序注册未绑定企业没有绑定企业可以正常添加，绑定了必须相同
                // 更安全的写法
                CommonUtils.validateCondition(user.getPlatform() == null || !channel.getId().equals(user.getPlatform().longValue()), "该员工属于企业（"+channel.getChannelName()+"），所属企业不匹配！");


                pointsRecharge.setChannelId(channel.getId());
                pointsRecharge.setUserName(userName);
                pointsRecharge.setUserPhone(templateDTO.getUserPhone());
                pointsRecharge.setChannelName(templateDTO.getChannelName());
                pointsRecharge.setPoints(templateDTO.getPoints());
                pointsRecharge.setExpiryDate(templateDTO.getExpiryDate());
                pointsRecharge.setType(0);
                pointsRecharge.setCreateTime(new Date());
                pointsRecharge.setUpdateTime(new Date());
                pointsRecharge.setRechargeStatus(1);
                pointsRecharge.setCode(code);
                pointsRecharge.setCreateBy(userId);

                // 生成充值单号
                pointsRecharge.setRechargeNumber(CommonUtils.getOrderNo("CZ"));

                // 保存数据（因为有过期时间每次导入的都是新增）
                log.info("保存数据：{}", pointsRecharge);
                this.save(pointsRecharge);
                log.info("保存数据成功：{}", pointsRecharge);
                // 添加积分记录明细
                PointsRecord pointsRecord = new PointsRecord();
                pointsRecord.setUserId(pointsRecharge.getUserId());
                pointsRecord.setChannelId(pointsRecharge.getChannelId());
                pointsRecord.setPointsId(pointsRecharge.getId());
                pointsRecord.setCode(pointsRecharge.getCode());
                pointsRecord.setPoints(pointsRecharge.getPoints());
                pointsRecord.setPointsType(1);
                pointsRecord.setPointsAudit(1);
                pointsRecord.setCreationDate(new Date());
                pointsRecord.setExpiryDate(pointsRecharge.getExpiryDate());

                Long aLong = pointsRecordMapper.statisticsPoint(pointsRecord.getUserId(), Math.toIntExact(pointsRecord.getChannelId()));
                pointsRecord.setCurrentlyAvailablePoints(pointsRecord.getPoints().add(BigDecimal.valueOf(aLong == null ? 0 : aLong )));

                pointsRecordService.save(pointsRecord);
                successCount++;
                addImportRecord(1, "成功", templateDTO, code,userId);
            } catch (GlobalException e) {
                log.info("导入失败：{}", e.getMessage());
                failCount++;
                addImportRecord(0, e.getMessage(), templateDTO, code,userId);
            } catch (Exception e) {
                failCount++;
                addImportRecord(0, "系统异常，请联系管理员", templateDTO, code,userId);
            }
        }

        if (successCount > 0 && failCount == 0) {
            return String.format("导入完成，全部成功：%d条", successCount);
        } else if (successCount == 0 && failCount > 0) {
            return String.format("导入完成，全部失败：%d条", failCount);
        } else {
            return String.format("导入完成，成功：%d条，失败：%d条", successCount, failCount);
        }
    }




    /**
     * 封装新增导入记录方法
     *
     * @param status  状态
     * @param message 成功还是失败原因
     */
    private void addImportRecord(int status, String message, com.yami.shop.service.impl.PointsRechargeTemplateDTO templateDTO, String code,Long userId) {
        // 数据保存到积分充值失败记录表
        PointsFailureRecord failureRecord = new PointsFailureRecord();
        failureRecord.setCode(code);
        failureRecord.setRechargeStatus(status);
        failureRecord.setReasonForFailure(message);
        failureRecord.setChannelName(templateDTO.getChannelName());
        failureRecord.setUserName(templateDTO.getUserName());
        failureRecord.setUserPhone(templateDTO.getUserPhone());
        failureRecord.setPoints(templateDTO.getPoints());
        failureRecord.setExpiryDate(templateDTO.getExpiryDate());
        failureRecord.setCreateTime(new Date());
        failureRecord.setCreateBy(userId);

        // 保存记录
        pointsFailureRecordService.save(failureRecord);
    }

    @Override
    public IPage<PointsRechargeVO> statisticsList(PointsRecharge pointsRecharge) {
        List<PointsRechargeVO> pointsRechargeVOS = pointsRechargeMapper.statisticsList(pointsRecharge);
        IPage<PointsRechargeVO> page = new Page<>(0, 1000);
        page.setRecords(pointsRechargeVOS);
        page.setTotal(pointsRechargeVOS.size());

        return  page;
    }
}
