package com.bonus.material.scrap.service.impl;

import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.util.StrUtil;
import com.bonus.common.biz.domain.BmFileInfo;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.approval.annotation.ApprovalRequired;
import com.bonus.material.common.constants.TypeConstants;
import com.bonus.material.common.enums.TypeEnums;
import com.bonus.material.devchange.domain.CsDeviceInfo;
import com.bonus.material.devchange.domain.MaDevFile;
import com.bonus.material.repair.domain.ToBeRepair;
import com.bonus.material.scrap.domain.ToBeScrap;
import com.bonus.material.scrap.mapper.ScrapMapper;
import com.bonus.material.scrap.service.ToBeScrapService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.hibernate.validator.internal.util.StringHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.bonus.common.biz.constant.MaterialConstants.ADMIN_ID;
import static com.bonus.common.biz.constant.MaterialConstants.PROVINCE_COMPANY_DEPT_ID;

@Service
public class ToBeScrapServiceImpl implements ToBeScrapService {

    @Resource
    private ScrapMapper scrapMapper;

    /**
     * 删除任务
     */
    @Override
    public AjaxResult deleteChangeInfo(Long id) {
        if (Objects.isNull(id)) {
            return AjaxResult.error("请求参数异常！");
        }
        int deleted = scrapMapper.deleteChangeInfo(id);
        return deleted > 0 ? AjaxResult.success("删除成功") : AjaxResult.error("删除失败");
    }

    /**
     * 审批退役任务明细
     * 注意：此方法由审批回调内部调用，不应直接暴露给前端
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult auditData(ToBeScrap bean) {
        try {
            if (Objects.isNull(bean)) {
                throw new ServiceException("请求参数异常！");
            }
            if (Objects.isNull(bean.getId())) {
                throw new ServiceException("任务ID不能为空");
            }

            // 根据任务ID查出所有的报废明细
            List<ToBeScrap> toBeScrapList = scrapMapper.getScrapDetailsList(bean);
            if (CollectionUtils.isEmpty(toBeScrapList)) {
                throw new ServiceException("该退役任务未查询到明细数据");
            }

            String username = SecurityUtils.getLoginUser().getSysUser().getNickName();
            Long userId = SecurityUtils.getLoginUser().getUserid();
            for (ToBeScrap toBeScrap : toBeScrapList) {
                toBeScrap.setCreateUser(username);
                if (StrUtil.isNotBlank(toBeScrap.getReviewStatus())) {
                    int res = scrapMapper.auditData(toBeScrap);
                    if (res < 1) {
                        throw new ServiceException("数据审批失败，修改0条明细");
                    }
                    // 如果是审批通过，需要增加周期表数据以及更新台账信息
                    if (Objects.equals("2", bean.getReviewStatus())) {
                        if (Objects.equals("工具", toBeScrap.getType())) {
                            // 根据typeId和code查询台账信息
                            ToBeScrap bean1 = scrapMapper.selectByTypeIdAndCode(toBeScrap);
                            if (bean1 != null && bean1.getId() > 0) {
                                //1、添加周期表数据
                                ToBeScrap bean2 = new ToBeScrap();
                                bean2.setId(bean1.getId());
                                bean2.setCreateBy(userId);
                                bean2.setCreateUser(username);
                                bean2.setCode(toBeScrap.getDevCode());
                                bean2.setDevCode(toBeScrap.getDevCode());
                                bean2.setScrapNum(toBeScrap.getScrapNum());
                                bean2.setIsScrap("1");
                                bean2.setIsScrapFilter(1);
                                int addedToolLifecycle = scrapMapper.addToolLifecycleByRepair(bean2);
                                if (addedToolLifecycle < 1) {
                                    throw new ServiceException("添加工具周期表数据失败");
                                }
                                // 2、更新工具台账表
                                int updatedToolLifecycle = scrapMapper.updateToolLifecycle(bean2);
                                if (updatedToolLifecycle <= 0) {
                                    throw new ServiceException("更新工具台账信息失败");
                                }
                            }
                        } else if (Objects.equals("装备", toBeScrap.getType())) {
                            //更新台账信息
                            toBeScrap.setCreateBy(userId);
                            toBeScrap.setIsScrapFilter(1);
                            int updateDevInfos = scrapMapper.updateMaDevInfo(toBeScrap);
                            if (updateDevInfos <= 0) {
                                throw new ServiceException("更新台账信息失败");
                            }
                        } else {
                            throw new ServiceException("设备类型异常");
                        }
                    }
                } else {
                    throw new ServiceException("审批状态为空，请检查！");
                }
            }
            // 修改主任务状态
            int res = scrapMapper.updateChangeStatus(bean.getId(), bean.getReviewStatus());
            if (res < 1) {
                throw new ServiceException("更新任务状态失败");
            }
            /*// 明细审核完成后，根据审批数量去修改外层任务状态
            int pendingReviewCount = scrapMapper.selectCountByChangeId(bean.getId());
            if (pendingReviewCount > 0) {
                int res = scrapMapper.updateChangeStatus(bean.getId(), "1");
                if (res < 1) {
                    throw new ServiceException("更新任务状态失败");
                }
            } else if (pendingReviewCount == 0) {
                int res = scrapMapper.updateChangeStatus(bean.getId(), "2");
                if (res < 1) {
                    throw new ServiceException("更新任务状态失败");
                }
            }*/

            return AjaxResult.success("审批成功");
        } catch (Exception e) {
            System.err.println(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("审核失败");
        }
    }

    /**
     * 新增报废退役任务
     * 提交后会自动创建审批流实例
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @ApprovalRequired(
            businessType = "EQUIPMENT_SCRAP",
            businessIdExpr = "#result['data']",
            businessDataExpr = "#bean"
    )
    public AjaxResult addScrapData(ToBeScrap bean) {
        try {
            if (bean.getToBeScrapList().isEmpty()) {
                return AjaxResult.error("请添加退役明细数据");
            }
            if (Objects.isNull(bean.getOperationType()) || !StrUtil.equalsAny(bean.getOperationType(), "add", "edit")) {
                return AjaxResult.error("操作类型异常！");
            }


            // 如果是编辑操作，那么就直接把之前的任务删掉重新建立
            if (Objects.equals("edit", bean.getOperationType())) {
                scrapMapper.deleteChangeInfo(bean.getId());
            }
            String username = SecurityUtils.getLoginUser().getSysUser().getNickName();
            //1、创建退役任务单号
            int thisMonthMaxOrder = scrapMapper.getMonthMaxOrderByDate(DateUtils.getCurrentYear(), DateUtils.getCurrentMonth(), TypeEnums.TM_TASK_RETIRE.getTaskTypeId());
            String code = genderTaskCode(thisMonthMaxOrder);
            CsDeviceInfo deviceInfo = new CsDeviceInfo();
            deviceInfo.setType(String.valueOf(TypeEnums.TM_TASK_RETIRE.getTaskTypeId()));
            deviceInfo.setCode(code);
            deviceInfo.setReviewStatus("0");  // 待审批状态
            deviceInfo.setCreateUser(username);
            deviceInfo.setCompanyId(SecurityUtils.getLoginUser().getSysUser().getDeptId());
            // 添加任务
            int num = scrapMapper.addDeviceChangeApply(deviceInfo);
            if (num < 1) {
                throw new ServiceException("添加任务失败");
            }
            Long changeId = deviceInfo.getId();
            // 保存任务明细
            for (ToBeScrap toBeScrap : bean.getToBeScrapList()) {

                BigDecimal onWayNum = Optional.ofNullable(scrapMapper.getDetailsNum(toBeScrap)).orElse(BigDecimal.ZERO);
                // 获取已使用数量（可能为null，转0）
                BigDecimal usedNum = Optional.ofNullable(toBeScrap.getInStockNum()).orElse(BigDecimal.ZERO);
                // 获取本次申请数量（可能为null，转0）
                BigDecimal applyNum = Optional.ofNullable(toBeScrap.getScrapNum()).orElse(BigDecimal.ZERO);

                // ========== 步骤2：计算总占用数量（在途 + 本次申请） ==========
                BigDecimal totalOccupyNum = onWayNum.add(applyNum);

                toBeScrap.getBmFileInfos().forEach(item -> {
                    toBeScrap.setScrapUrl(item.getFileUrl());
                });

                // ========== 步骤3：业务校验（usedNum < totalOccupyNum 时触发错误） ==========
                if (usedNum.compareTo(totalOccupyNum) < 0) {
                    // 格式化数值：根据业务场景选择舍入模式（此处以保留2位小数、四舍五入为例，可调整）
                    // 注意：展示的是总占用数量，与校验逻辑一致，避免用户误解
                    String totalOccupyNumStr = formatBigDecimal(onWayNum, 0, RoundingMode.HALF_UP);
                    String applyNumStr = formatBigDecimal(applyNum, 0, RoundingMode.HALF_UP);
                    String typeName = toBeScrap.getTypeName();

                    // 构建错误信息
                    String errorMsg = String.format("%s，已有在途单据，在途数量%s，本次申请数量%s", typeName, totalOccupyNumStr, applyNumStr);

                    // 记录日志：包含关键参数，便于问题排查
                    // 返回错误结果
                    return AjaxResult.error(errorMsg, AjaxResult.class);
                }


                toBeScrap.setChangeId(changeId);
                toBeScrap.setCreateUser(username);


                if (CollectionUtils.isNotEmpty(toBeScrap.getBmFileInfos())) {
                    toBeScrap.setScrapUrl(toBeScrap.getBmFileInfos().get(0).getFileUrl());
                }
                int res = scrapMapper.addScrapChangeApplyDetails(toBeScrap);
                if (res <= 0) {
                    throw new ServiceException("添加退役明细数据失败");
                }
            }
            // 返回任务ID，供审批流使用
            return AjaxResult.success("任务提交成功，等待审批", changeId);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("申请失败");
        }
    }

    /**
     * 生成退役任务编号
     *
     * @param thisMonthMaxOrder 本月最大单号
     * @return 任务单号
     */
    private String genderTaskCode(int thisMonthMaxOrder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date nowDate = DateUtils.getNowDate();
        String format = dateFormat.format(nowDate);
        String result = format.replace("-", "");
        return TypeConstants.SCRAP_TASK_TYPE_LABEL + result + String.format("-%04d", thisMonthMaxOrder + 1);
    }

    /**
     * 获取在库的装备、工具列表
     */
    @Override
    public List<ToBeScrap> getInStockList(ToBeScrap bean) {
        bean.setCompanyId(SecurityUtils.getLoginUser().getSysUser().getDeptId());
        return scrapMapper.getInStockList(bean);
    }

    /**
     * 获取报废申请列表
     */
    @Override
    public List<ToBeScrap> getScrapApplyList(ToBeScrap bean) {
        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
        Long userId = SecurityUtils.getLoginUser().getUserid();
        // 管理员和省公司可查看所有数据
//        if (userId != null && deptId != null
//                && !userId.equals(ADMIN_ID)
//                && !deptId.equals(PROVINCE_COMPANY_DEPT_ID)) {
//            bean.setCompanyId(deptId);
//        }
        if(ADMIN_ID.equals(userId)){
            bean.setCompanyId(1L);
        }else{
            bean.setCompanyId(deptId);
        }
        return scrapMapper.getScrapApplyList(bean);
    }

    /**
     * 获取报废详情明细
     */
    @Override
    public List<ToBeScrap> getScrapDetailsList(ToBeScrap bean) {

        try {
            List<ToBeScrap> list = scrapMapper.getScrapDetailsList(bean);
            list.forEach(item -> {
                if(ObjectUtils.isNotEmpty(item.getScrapUrl())){
                    MaDevFile maDevFile = new MaDevFile();
                    maDevFile.setFileUrl(item.getScrapUrl());
                    maDevFile.setFileName(getFileNameFromUrl(item.getReasonUrl()));
                    item.setBmFileInfos(new ArrayList<>());
                    item.getBmFileInfos().add(maDevFile);
                }

            });
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }

    }


    /**
     * 从标准文件URL中提取文件名（适配你的场景）
     *
     * @param urlStr item.getReasonUrl() 返回的URL字符串
     * @return 提取的文件名（如 36448a87-a53a-4d49-aa78-1639ca72440d.png）
     */
    public static String getFileNameFromUrl(String urlStr) {
        // 1. 空值校验
        if (urlStr == null || urlStr.trim().isEmpty()) {
            return "";
        }

        // 2. 移除URL中的参数和锚点（你的场景无参数/锚点，仅做兼容）
        String cleanUrl = urlStr.split("\\?")[0].split("#")[0];

        // 3. 提取最后一个"/"后的内容（核心步骤）
        int lastSlashIndex = cleanUrl.lastIndexOf('/');
        if (lastSlashIndex == -1 || lastSlashIndex == cleanUrl.length() - 1) {
            return ""; // 无"/"或以"/"结尾，返回空
        }
        String fileName = cleanUrl.substring(lastSlashIndex + 1);

        // 4. 解码URL编码（你的场景无编码，但保留以兼容扩展）
        return URLDecoder.decode(fileName, StandardCharsets.UTF_8);
    }


    /**
     * @param id
     * @return
     */
    @Override
    public List<ToBeScrap> getDetail(String id) {

        return scrapMapper.getDetail(id);
    }


    private String formatBigDecimal(BigDecimal value, int scale, RoundingMode roundingMode) {
        // 空值转0后再格式化，消除空指针
        return Optional.ofNullable(value)
                .orElse(BigDecimal.ZERO)
                .setScale(scale, roundingMode)
                .toPlainString(); // 避免科学计数法
    }
}
