package com.zg.project.wisdom.service.impl;

import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

import com.zg.common.exception.ServiceException;
import com.zg.common.utils.DateUtils;
import com.zg.common.utils.SecurityUtils;
import com.zg.common.utils.StringUtils;
import com.zg.framework.web.domain.AjaxResult;
import com.zg.project.wisdom.domain.dto.ExcelFieldMapping;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zg.project.wisdom.mapper.GysJhMapper;
import com.zg.project.wisdom.domain.GysJh;
import com.zg.project.wisdom.service.IGysJhService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

/**
 * 供应计划Service业务层处理
 * 
 * @author zg
 * @date 2025-05-28
 */
@Service
public class GysJhServiceImpl implements IGysJhService 
{
    @Autowired
    private GysJhMapper gysJhMapper;

    /**
     * 查询供应计划
     * 
     * @param id 供应计划主键
     * @return 供应计划
     */
    @Override
    public GysJh selectGysJhById(Long id)
    {
        return gysJhMapper.selectGysJhById(id);
    }

    /**
     * 查询供应计划列表
     * 
     * @param gysJh 供应计划
     * @return 供应计划
     */
    @Override
    public List<GysJh> selectGysJhList(GysJh gysJh)
    {
        return gysJhMapper.selectGysJhList(gysJh);
    }

    /**
     * 新增供应计划
     * 
     * @param gysJh 供应计划
     * @return 结果
     */
    @Override
    public int insertGysJh(GysJh gysJh)
    {
        gysJh.setCreateTime(DateUtils.getNowDate());
        return gysJhMapper.insertGysJh(gysJh);
    }

    /**
     * 修改供应计划
     * 
     * @param gysJh 供应计划
     * @return 结果
     */
    @Override
    public int updateGysJh(GysJh gysJh)
    {
        gysJh.setUpdateTime(DateUtils.getNowDate());
        return gysJhMapper.updateGysJh(gysJh);
    }

    /**
     * 批量删除供应计划
     * 
     * @param ids 需要删除的供应计划主键
     * @return 结果
     */
    @Override
    public int deleteGysJhByIds(Long[] ids)
    {
        return gysJhMapper.deleteGysJhByIds(ids);
    }

    /**
     * 删除供应计划信息
     * 
     * @param id 供应计划主键
     * @return 结果
     */
    @Override
    public int deleteGysJhById(Long id)
    {
        return gysJhMapper.deleteGysJhById(id);
    }

    /**
     * 供应计划导入
     * @param jhList
     * @param operName
     * @return
     */
    @Override
    public String importGysJhList(List<GysJh> jhList, String operName) {
        if (jhList == null || jhList.isEmpty()) {
            throw new ServiceException("导入数据不能为空！");
        }

        int successNum = 0;
        int failureNum = 0;
        StringBuilder failureMsg = new StringBuilder();

        for (GysJh jh : jhList) {
            try {
                // 唯一性校验：订单号 + 项目号 + 物料号
//                boolean exists = gysJhMapper.existsByUniqueKeys(jh.getSapNo(), jh.getXmNo(), jh.getWlNo());
//                if (exists) {
//                    failureNum++;
//                    failureMsg.append("<br/>订单号：").append(jh.getSapNo())
//                            .append("，项目号：").append(jh.getXmNo())
//                            .append("，物料号：").append(jh.getWlNo())
//                            .append(" 已存在，跳过导入。");
//                    continue;
//                }

                jh.setCreateBy(operName);
                jh.setStatus("0");
                jh.setIsDelete("0");
                insertGysJh(jh);
                successNum++;
            } catch (Exception e) {
                failureNum++;
                failureMsg.append("<br/>订单号：").append(jh.getSapNo())
                        .append("，项目号：").append(jh.getXmNo())
                        .append("，物料号：").append(jh.getWlNo())
                        .append(" 导入失败：").append(e.getMessage());
            }
        }

        if (failureNum > 0) {
            failureMsg.insert(0, "导入完成，但有 " + failureNum + " 条记录失败：");
            throw new ServiceException(failureMsg.toString());
        }

        return "导入成功，共 " + successNum + " 条数据";
    }


    /**
     * 根据SAP编号查询
     * @param sapNo
     * @return
     */
    @Override
    public AjaxResult getBySapNo(String sapNo) {

        List<GysJh> list = gysJhMapper.getBySapNo(sapNo);

        if (list == null || list.isEmpty()) {
            return AjaxResult.success(list);
        }

        AjaxResult result = AjaxResult.success(list);

        List<String> inStockWlNos = list.stream()
                .filter(x -> x != null && "1".equals(String.valueOf(x.getStatus()).trim()))
                .map(GysJh::getWlNo)
                .filter(wlNo -> wlNo != null && !wlNo.trim().isEmpty())
                .map(String::trim)
                .distinct()
                .collect(java.util.stream.Collectors.toList());

        if (!inStockWlNos.isEmpty()) {
            result.put("warn", true);
            result.put("inStockWlNos", inStockWlNos);
            result.put("msg", "该 SAP 订单号下，以下物料号已全部入库，请注意："
                    + String.join("、", inStockWlNos));
        }

        return result;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int importByMapping(MultipartFile file, List<ExcelFieldMapping> mapping) throws Exception {
        List<GysJh> list = parseExcel(file, mapping);
        if (list == null || list.isEmpty()) {
            return 0;
        }
        for (GysJh item : list) {
            gysJhMapper.insertGysJh(item);
        }
        return list.size();
    }

    /**
     * 解析 Excel -> GysJh 列表
     */
    private List<GysJh> parseExcel(MultipartFile file, List<ExcelFieldMapping> mappingList) throws Exception {
        List<GysJh> result = new ArrayList<>();

        try (InputStream is = file.getInputStream();
             Workbook workbook = WorkbookFactory.create(is)) {

            Sheet sheet = workbook.getSheetAt(0);
            if (sheet == null) {
                return result;
            }

            // 1. 把映射转换成：字段名 -> 列索引
            Map<String, Integer> fieldColumnIndex = new HashMap<>();
            for (ExcelFieldMapping m : mappingList) {
                if (m == null) {
                    continue;
                }
                String label = m.getLabel();   // wlNo / jhAmt ...
                String prop = m.getProp();     // A / B / C ...
                if (StringUtils.isEmpty(label) || StringUtils.isEmpty(prop)) {
                    continue;
                }
                fieldColumnIndex.put(label, excelColToIndex(prop));
            }

            DataFormatter formatter = new DataFormatter();

            int firstRowNum = sheet.getFirstRowNum();
            int lastRowNum = sheet.getLastRowNum();

            // 默认第一行是表头，从第二行开始读
            for (int rowNum = firstRowNum + 1; rowNum <= lastRowNum; rowNum++) {
                Row row = sheet.getRow(rowNum);
                if (row == null) {
                    continue;
                }

                // 关键字段都为空则认为是空行，跳过
                String wlNoVal  = getCellString(row, fieldColumnIndex.get("wlNo"), formatter);
                String sapNoVal = getCellString(row, fieldColumnIndex.get("sapNo"), formatter);
                if (StringUtils.isEmpty(wlNoVal) && StringUtils.isEmpty(sapNoVal)) {
                    continue;
                }

                GysJh item = new GysJh();
                // 序号可以用行号，也可以单独映射，看你需求
                item.setIndexNo((long) (rowNum));

                // 按字段名逐个赋值
                for (Map.Entry<String, Integer> entry : fieldColumnIndex.entrySet()) {
                    String field = entry.getKey();
                    Integer colIndex = entry.getValue();
                    String cellValue = getCellString(row, colIndex, formatter);
                    if (StringUtils.isEmpty(cellValue)) {
                        continue;
                    }

                    switch (field) {
                        case "wlNo":
                            item.setWlNo(cellValue.trim());
                            break;
                        case "wlMs":
                            item.setWlMs(cellValue.trim());
                            break;
                        case "xmNo":
                            item.setXmNo(cellValue.trim());
                            break;
                        case "xmMs":
                            item.setXmMs(cellValue.trim());
                            break;
                        case "dw":
                            item.setDw(cellValue.trim());
                            break;
                        case "gysNo":
                            item.setGysNo(cellValue.trim());
                            break;
                        case "gysMc":
                            item.setGysMc(cellValue.trim());
                            break;
                        case "jhAmt":
                            // BigDecimal
                            item.setJhAmt(parseBigDecimal(cellValue));
                            break;
                        case "htDj":
                            // BigDecimal
                            item.setHtDj(parseBigDecimal(cellValue));
                            break;
                        case "jhQty":
                            item.setJhQty(parseBigDecimal(cellValue));
                            break;
                        case "htQty":
                            item.setHtQty(parseBigDecimal(cellValue));
                            break;
                        case "entityId":
                            item.setEntityId(cellValue.trim());
                            break;
                        case "sapNo":
                            item.setSapNo(cellValue.trim());
                            break;
                        default:
                            // 以后扩展字段，就在上面加 case
                            break;
                    }
                }

                // 默认字段
                item.setStatus("0");
                item.setIsDelete("0");
                String username = SecurityUtils.getUsername();
//                item.setCreateBy("大爷的！！！");
                item.setCreateTime(DateUtils.getNowDate());

                result.add(item);
            }
        }

        return result;
    }

    /**
     * Excel 列字母转索引（A -> 0, B -> 1, ..., AA -> 26）
     */
    private int excelColToIndex(String col) {
        col = col.trim().toUpperCase();
        int index = 0;
        for (int i = 0; i < col.length(); i++) {
            char c = col.charAt(i);
            index = index * 26 + (c - 'A' + 1);
        }
        return index - 1;
    }

    /**
     * 统一获取单元格字符串
     */
    private String getCellString(Row row, Integer colIndex, DataFormatter formatter) {
        if (row == null || colIndex == null || colIndex < 0) {
            return null;
        }
        Cell cell = row.getCell(colIndex);
        if (cell == null) {
            return null;
        }
        String val = formatter.formatCellValue(cell);
        return StringUtils.isEmpty(val) ? null : val.trim();
    }

    /**
     * 字符串转 BigDecimal（空串返回 null）
     */
    /**
     * 字符串转 BigDecimal（空串或"null"返回 null）
     */
    private BigDecimal parseBigDecimal(String value) {
        if (StringUtils.isEmpty(value)) {
            return null;
        }

        try {
            String trimmedValue = value.trim();
            if ("null".equalsIgnoreCase(trimmedValue)) {
                return null;
            }

            // 去掉千分位逗号
            String v = trimmedValue.replace(",", "").trim();
            // 再次检查处理后的值
            if (StringUtils.isEmpty(v) || "null".equalsIgnoreCase(v)) {
                return null;
            }

            return new BigDecimal(v);
        } catch (NumberFormatException e) {
            // 记录详细错误信息以便调试
//            log.warn("解析BigDecimal失败，输入值: '{}'", value, e);
            return null;
        }
    }

    /**
     * 字符串转 Long（空串返回 null）
     */
    private Long parseLong(String value) {
        if (StringUtils.isEmpty(value)) {
            return null;
        }

        String trimmedValue = value.trim();
        if ("null".equalsIgnoreCase(trimmedValue)) {
            return null;
        }

        try {
            String v = trimmedValue.replace(",", "").trim();
            if (StringUtils.isEmpty(v) || "null".equalsIgnoreCase(v)) {
                return null;
            }
            return Long.valueOf(v);
        } catch (NumberFormatException e) {
//            log.warn("无法解析为Long的值: '{}'", value);
            return null;
        }
    }


}
