package com.zzsmart.qomo.kn.cost.manage.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.zzsmart.qomo.kn.cost.manage.constants.Constants;
import com.zzsmart.qomo.kn.cost.manage.entity.CostStandard;
import com.zzsmart.qomo.kn.cost.manage.entity.CostStandardVersion;
import com.zzsmart.qomo.kn.cost.manage.enums.StandardStageEnum;
import com.zzsmart.qomo.kn.cost.manage.mapper.CostStandardMapper;
import com.zzsmart.qomo.kn.cost.manage.mapper.CostStandardVersionMapper;
import com.zzsmart.qomo.kn.cost.manage.service.ICostStandardVersionService;

import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
 * @Description: 标准成本-版本号
 * @Author: wangqiong
 * @Date: 2024-06-13
 * @Version: V1.0
 */
@Service
public class CostStandardVersionServiceImpl extends ServiceImpl<CostStandardVersionMapper, CostStandardVersion> implements ICostStandardVersionService {
    @Autowired
    private CostStandardMapper costStandardMapper;
    private static final Logger log = LoggerFactory.getLogger(CostStandardVersionServiceImpl.class);

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(CostStandardVersion costStandardVersion) {
        // todo 查物料表看是否存在改物料，没有抛异常
        LoginUser sysUser = null;
        try {
            sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        } catch (Exception ignored) {

        }
        if (sysUser != null) {
            costStandardVersion.setCreateBy(sysUser.getUsername());
        }
        // 保存版本号表
        boolean save = super.save(costStandardVersion);
        // todo 标准成本计算
        CostStandard standard = standardCalculate(costStandardVersion);
//        standard.setMaterialNumber(costStandardVersion.getMaterialNumber());
//        standard.setVersionNumberId(costStandardVersion.getId());
//        if(sysUser!=null){
//            standard.setCreateBy(sysUser.getUsername());
//        }
//        standard.setCreateTime(new Date());
//        // 保存标准成本表
//        costStandardMapper.insert(standard);
        return save;
    }


    /**
     * 标准成本计算
     *
     * @param costStandardVersion 版本号
     * @return
     */
    private CostStandard standardCalculate(CostStandardVersion costStandardVersion) {
        // 计算逻辑，生成版本号输入的物料号是根节点物料号，
        // 1，根据根节点物料号查找物料表kn_new_sap_mara

        // 2,去bom表找出对应下的所有层级物料cost_material_bom

        // 3，根据物料去工时工序表找出对应工序，工序表中包含所计算的工时，cost_material_process_hours
        // 4，查小时费率表，找到对应工时费率cost_hour_rate
        // 5，查采购单价表，找到对应采购单价cost_purchase_price
        // 5，计算每层级的物料标准成本，存到标准成本明细表cost_standard_detail
        CostStandard standard = new CostStandard();

        // 4，计算bom费用，BOM表清单物料用量*采购单价
        // 5，计算包装费
        // 6，计算辅料费
        // 7，计算人工费，人工工时*费率
        // 8，计算机器折旧费，机器工时*费率
        // 9，计算机物料消耗费，辅料工时*费率
        // 10，计算水电费，燃动力工时*费率
        // 11，计算其他制造费，其他工时*费率
        // 12，计算物流费，物流费用=（机器折旧+机物料消耗+水电费+其他制费）*10.16%
        // 13，计算制造成本，前面所有费用汇总（即人工费+机器折旧费+机物料消耗费+水电费+其他制造费+物流费）
        // 18，计算总成本

        return standard;
    }



    /**
     * excel导入
     *
     * @param request
     * @param response
     * @param clazz
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<CostStandardVersion> clazz) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        Iterator iterator = fileMap.entrySet().iterator();
        if (iterator.hasNext()) {
            Map.Entry<String, MultipartFile> entity = (Map.Entry) iterator.next();
            MultipartFile file = (MultipartFile) entity.getValue();
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<CostStandardVersion> list = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);
                if (CollectionUtil.isEmpty(list)) {
                    log.error("无可导入的数据！");
                    return Result.error("无可导入的数据！");
                }
                int successNum = 0;
                int failureNum = 0;
                //   StringBuilder successMsg = new StringBuilder();
                StringBuilder failureMsg = new StringBuilder();
                long start = System.currentTimeMillis();
                // 校验并组装list
                for (int i = 0; i < list.size(); i++) {
                    CostStandardVersion standardVersion = list.get(i);
                    // 校验物料号是否为空
                    if (StrUtil.isEmpty(standardVersion.getMaterialNumber())) {
                        failureNum++;
                        failureMsg.append("<br/>第 " + (i + 2) + " 行【物料号】字段不能为空：");
                        continue;
                    }
                    if (StrUtil.isNotEmpty(standardVersion.getStage())) {
                        standardVersion.setStage(StandardStageEnum.getCodeByText(standardVersion.getStage()));
                    }
                    // 创建日期
                    Date createDate = new Date();
                    standardVersion.setCreateTime(createDate);
                    String dateStr = new SimpleDateFormat("yyyyMMddHHmmss").format(createDate);
                    // 生成版本号,版本号=图号_阶段_创建日期(格式：yyyyMMddHHmmss)
                    standardVersion.setVersionNumber(standardVersion.getFigureNumber()+ Constants.UNDER_LINE +standardVersion.getStage()+Constants.UNDER_LINE+dateStr);
                    // 设置年份
                    standardVersion.setVersionYear(String.valueOf(createDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate().getYear()));
                    // 调用保存方法
                    try {
                        save(standardVersion);
                    } catch (Exception e) {
                        failureNum++;
                        String msg = "<br/>第 " + (i + 2) + " 行数据导入失败；";
                        failureMsg.append(msg);
                        log.error(msg, e);
                    }
                    successNum++;
                }
                //   costStandardVersionService.saveBatch(list);
                log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
                String returnMsg = "文件导入成功！数据行数：" + successNum;
                if (failureNum > 0) {
                    returnMsg += "<br/>失败数据行数：" + failureNum + "，失败信息如下：<br/>" + failureMsg.toString();
                }
                return Result.ok(returnMsg);
            } catch (Exception exception) {
                String msg = exception.getMessage();
                log.error(msg, exception);
                Result result;
                String duplicateEntry = "Duplicate entry";
                if (msg != null && msg.contains(duplicateEntry)) {
                    result = Result.error("文件导入失败:有重复数据！");
                    return result;
                } else {
                    result = Result.error("文件导入失败:" + exception.getMessage());
                    return result;
                }
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException var23) {
                    var23.printStackTrace();
                }
            }
        } else {
            return Result.error("文件导入失败！");
        }

    }
}
