package com.hys.app.service.erp.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.hys.app.converter.erp.MemberConverter;
import com.hys.app.framework.util.StringUtil;
import com.hys.app.model.base.Result;
import com.hys.app.model.erp.dos.MemberDO;
import com.hys.app.model.erp.dto.MemberExcelImport;
import com.hys.app.model.erp.enums.SexEnum;
import com.hys.app.service.erp.MemberManager;
import com.hys.app.util.ValidateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 会员导入
 *
 * @author 张崧
 * 2024-01-23
 */
@Service
@Slf4j
public class MemberImportManager {

    @Autowired
    private MemberConverter converter;

    @Autowired
    private MemberManager memberManager;


    @Transactional(rollbackFor = Exception.class)
    public Result doImportExcel(MultipartFile file, Authentication authentication) {
        SecurityContextHolder.getContext().setAuthentication(authentication);

        // 读取excel
        List<MemberExcelImport> importList = readExcel(file);
        if (importList == null) {
            return Result.fail("excel读取失败");
        }

        // 校验数据
        List<String> errorList = checkImportData(importList);
        if (!errorList.isEmpty()) {
            return Result.fail(errorList.toArray(new String[0]));
        }

        // 保存数据
        List<MemberDO> memberList = converter.convertImportList(importList);
        memberManager.saveBatch(memberList);

        return Result.ok();
    }

    private List<MemberExcelImport> readExcel(MultipartFile file) {
        try {
            return EasyExcel.read(file.getInputStream(), MemberExcelImport.class, null).headRowNumber(5).doReadAllSync();
        } catch (Exception e) {
            log.error("会员导入excel读取失败", e);
            return null;
        }
    }

    private List<String> checkImportData(List<MemberExcelImport> importList) {
        // 错误信息集合
        List<String> errorList = new ArrayList<>();

        // 校验excel中的数据是否存在重复
        checkUniqueInExcel(importList, errorList);

        // 校验每行数据正确性
        int line = 1;
        for (MemberExcelImport importData : importList) {
            // 空值检查
            if (StringUtil.isEmpty(importData.getSn())) {
                errorList.add(StrUtil.format("行号为【{}】的【编号】不能为空", line));
            }
            if (StringUtil.isEmpty(importData.getDisableFlagStr())) {
                errorList.add(StrUtil.format("行号为【{}】的【状态】不能为空", line));
            }

            // 出生日期格式检查
            if (StringUtil.notEmpty(importData.getBirthdayStr())) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
                try {
                    Date parse = sdf.parse(importData.getBirthdayStr());
                    importData.setBirthday(parse.getTime() / 1000);
                } catch (ParseException e) {
                    errorList.add(StrUtil.format("行号为【{}】的【出生日期】格式不正确", line));
                }
            }
            // 性别检查
            if (StringUtil.notEmpty(importData.getSexStr())) {
                if (!"男".equals(importData.getSexStr()) && !"女".equals(importData.getSexStr())) {
                    errorList.add(StrUtil.format("行号为【{}】的【性别】值错误", line));
                } else {
                    importData.setSex("男".equals(importData.getSexStr()) ? SexEnum.Men : SexEnum.Woman);
                }
            }
            // 状态检查
            if (StringUtil.notEmpty(importData.getDisableFlagStr())) {
                if (!"0".equals(importData.getDisableFlagStr()) && !"1".equals(importData.getDisableFlagStr())) {
                    errorList.add(StrUtil.format("行号为【{}】的【状态】值错误", line));
                } else {
                    importData.setDisableFlag("1".equals(importData.getDisableFlagStr()));
                }
            }

            // 唯一性校验
            if (ValidateUtil.checkRepeat(memberManager.getBaseMapper(), MemberDO::getSn, importData.getSn(), MemberDO::getId, null)) {
                errorList.add(StrUtil.format("行号为【{}】的【会员编号】已存在", line));
            }
            if (ValidateUtil.checkRepeat(memberManager.getBaseMapper(), MemberDO::getMobile, importData.getMobile(), MemberDO::getId, null)) {
                errorList.add(StrUtil.format("行号为【{}】的【手机号】已存在", line));
            }
            if (ValidateUtil.checkRepeat(memberManager.getBaseMapper(), MemberDO::getEmail, importData.getEmail(), MemberDO::getId, null)) {
                errorList.add(StrUtil.format("行号为【{}】的【邮箱】已存在", line));
            }

            line++;
        }

        return errorList;
    }

    private void checkUniqueInExcel(List<MemberExcelImport> importList, List<String> errorList) {
        // 用于记录每个编号第一次出现的位置
        Map<String, Integer> snMap = new HashMap<>(importList.size());
        // 用于记录每个手机号第一次出现的位置
        Map<String, Integer> mobileMap = new HashMap<>(importList.size());
        // 用于记录每个邮箱第一次出现的位置
        Map<String, Integer> emailMap = new HashMap<>(importList.size());

        for (int i = 0; i < importList.size(); i++) {
            MemberExcelImport importData = importList.get(i);

            // 校验编号重复
            String sn = importData.getSn();
            if (StringUtil.notEmpty(sn)) {
                if (!snMap.containsKey(sn)) {
                    snMap.put(sn, i);
                } else {
                    errorList.add(StrUtil.format("行号为【{},{}】的编号相同", snMap.get(sn) + 1, i + 1));
                }
            }

            // 校验手机号重复
            String mobile = importData.getMobile();
            if (StringUtil.notEmpty(mobile)) {
                if (!mobileMap.containsKey(mobile)) {
                    mobileMap.put(mobile, i);
                } else {
                    errorList.add(StrUtil.format("行号为【{},{}】的手机号相同", mobileMap.get(mobile) + 1, i + 1));
                }
            }

            // 校验邮箱重复
            String email = importData.getEmail();
            if (StringUtil.notEmpty(email)) {
                if (!emailMap.containsKey(email)) {
                    emailMap.put(email, i);
                } else {
                    errorList.add(StrUtil.format("行号为【{},{}】的邮箱相同", emailMap.get(email) + 1, i + 1));
                }
            }

        }
    }
}

