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


import com.alibaba.nacos.common.utils.CollectionUtils;
import com.bonus.common.biz.domain.BmFileInfo;
import com.bonus.common.biz.enums.ApprovalStatusEnum;
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.approval.domain.ApprovalInstance;
import com.bonus.material.approval.domain.ApprovalRecord;
import com.bonus.material.approval.mapper.ApprovalInstanceMapper;
import com.bonus.material.approval.mapper.ApprovalRecordMapper;
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.repair.domain.ToBeRepair;
import com.bonus.material.repair.mapper.RepairMapper;
import com.bonus.material.repair.service.RepairService;
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.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

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


/**
 * @author hay
 */
@Service
public class RepairServiceImpl implements RepairService {
    @Resource
    private RepairMapper mapper;

    @Resource
    private ApprovalInstanceMapper instanceMapper;

    @Resource
    private ApprovalRecordMapper recordMapper;


    @Override
    public List<ToBeRepair> getToBeRepairList(ToBeRepair bean) {
        try {
            bean.setCompanyId(SecurityUtils.getLoginUser().getSysUser().getDeptId());
            return mapper.selectToBeRepairList(bean);
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ApprovalRequired(
            businessType = "EQUIPMENT_REPAIR",
            businessIdExpr = "#result['data']",
            businessDataExpr = "#bean"
    )
    public AjaxResult addRepairData(ToBeRepair bean) {
        try {
            List<ToBeRepair> list = bean.getToBeRepairList();
            if (list.isEmpty()) {
                return AjaxResult.error("请添加维修数据");
            }
            String username = getCurrentUsername();

            Long changeId;
            if (bean.getChangeId()==null){
                // 1. 创建维修任务
                changeId = createRepairTask(username);
                //将申请的设备状态都改为维修
                for (ToBeRepair detail : list){
                    if ("编码管理".equals(detail.getManageMode()) && !StringHelper.isNullOrEmptyString(detail.getCode())){
                        //1、如果是编码管理，将设备状态改为维修状态
                        if ("装备".equals(detail.getType())){
                            int re1 = mapper.updateDevStatus(detail);
                        } else if ("工具".equals(detail.getType())){
                            int re2 = mapper.updateToolStatus(detail);
                        }
                    } else if ("数量管理".equals(detail.getManageMode())){
                        //目前数量管理的设备都是工具
                        //将在库数量减掉增加维修数量
                        int re3 = mapper.updateToolNum(detail);
                    }
                }
            } else {
                //退料维修任务提交
                changeId = bean.getChangeId();
                //清除旧数据
                int res = mapper.physicalDeletionDetailsByChangeId(bean);
                //修改主表任务为待审核
                int re = mapper.updateStatusById(bean);
            }
            // 2. 保存明细
            for (ToBeRepair detail : list) {
                processRepairDetail(detail, changeId, username);
            }

            // 3. 设置任务ID到bean中（用于审批流）
            bean.setChangeId(changeId);

            return AjaxResult.success("维修申请提交成功，等待审批", changeId);
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("申请失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updateRepairData(ToBeRepair bean) {
        try {
            if (bean.getChangeId()==null){
                throw new Exception("缺少任务ID");
            }
            if (bean.getToBeRepairList().size() <= 0) {
                return AjaxResult.error("请添加维修数据");
            }
            //修改主表任务为待审核
            bean.setStatus("0");
            int num = mapper.updateRepairTask(bean);
            if (num < 1) {
                throw new Exception("修改设备任务失败");
            }
            String username = SecurityUtils.getLoginUser().getSysUser().getNickName();
            //先删除详情中被驳回的数据
            int re1 =  mapper.deleteChangeDetailsByChangeId(bean);
            if (re1 < 1) {
                throw new Exception("删除设备详情失败");
            }
            for (ToBeRepair toBeRepair : bean.getToBeRepairList()) {
                if (!StringHelper.isNullOrEmptyString(toBeRepair.getStatus()) && "通过".equals(toBeRepair.getStatus())){
                    //过滤掉通过的数据
                    continue;
                }
                toBeRepair.setChangeId(bean.getChangeId());
                toBeRepair.setCreateUser(username);
                if (!StringHelper.isNullOrEmptyString(toBeRepair.getIsScrap())) {
                    if (toBeRepair.getBmFileInfos()!=null && toBeRepair.getBmFileInfos().size() > 0) {
                        if ("0".equals(toBeRepair.getIsScrap())) {
                            toBeRepair.setRepairUrl(toBeRepair.getBmFileInfos().get(0).getFileUrl());
                        } else {
                            toBeRepair.setScrapUrl(toBeRepair.getBmFileInfos().get(0).getFileUrl());
                        }
                    }
                } else {
                    throw new Exception("缺少合格状态数据");
                }
                int res = mapper.addRepairData(toBeRepair);
                if (res <= 0) {
                    throw new Exception("添加设备详情失败");
                }
            }
            // 根据id，针对编辑进行审批流重置修改
            // 根据主id查询目前审批流是否存在驳回数据，驳回需重置审批
            ApprovalInstance approvalInstance = new ApprovalInstance();
            approvalInstance.setBusinessId(bean.getChangeId().toString());
            List<ApprovalInstance> approvalInstances = instanceMapper.selectInstanceList(approvalInstance);
            if (CollectionUtils.isNotEmpty(approvalInstances)) {
                ApprovalInstance instance = approvalInstances.get(0);
                if ("3".equals(instance.getStatus())) {
                    // 如果当前节点为第一节点，则状态修改为待审批
                    if (instance.getCurrentNodeOrder() == 1) {
                        num = instanceMapper.updateInstanceStatus(instance.getId(), ApprovalStatusEnum.PENDING.getCode());
                    } else {
                        // 审批中
                        num = instanceMapper.updateInstanceStatus(instance.getId(), ApprovalStatusEnum.IN_PROGRESS.getCode());
                    }
                    if (num < 1) {
                        throw new RuntimeException("修改审批实例状态失败");
                    }
                    // 根据当前节点及id去记录表查询是否存在驳回记录，存在即删除
                    List<ApprovalRecord> approvalRecords = recordMapper.selectRecordListByNode(instance.getId(), instance.getCurrentNodeId());
                    if (CollectionUtils.isNotEmpty(approvalRecords)) {
                        ApprovalRecord approvalRecord = approvalRecords.get(0);
                        // 如果是驳回状态，则删除
                        if ("2".equals(approvalRecord.getApproveResult())) {
                            num = recordMapper.deleteRecordById(approvalRecord.getId());
                            if (num < 1) {
                                throw new RuntimeException("删除审批记录失败");
                            }
                        }
                    }
                }
            }
            return AjaxResult.success("修改成功");

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("修改失败");
        }
    }

    @Override
    public List<ToBeRepair> getRepairList(ToBeRepair bean) {
        try {
            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);
            }
            List<ToBeRepair> list = mapper.getRepairList(bean);
            /*for (ToBeRepair toBeRepair : list) {
                List<ToBeRepair> detailsList = mapper.getDetailsList(toBeRepair);
                if (detailsList != null && !detailsList.isEmpty()) {
                    boolean has0 = false;
                    boolean has1 = false;
                    boolean has2 = false;
                    for (ToBeRepair detail : detailsList) {
                        String audit = detail.getAuditStatus();
                        if ("0".equals(audit)) {
                            has0 = true;
                        }
                        if ("1".equals(audit)) {
                            has1 = true;
                        }
                        if ("2".equals(audit)) {
                            has2 = true;
                        }
                    }
                    // === 状态判断 (已更新为数字编码) ===
                    if (has0 && !has1 && !has2) {
                        // 1. 全部为 0 -> 待审核
                        toBeRepair.setStatus("1");
                    } else if (!has0 && has1 && !has2) {
                        // 2. 全部为 1 -> 全部通过
                        toBeRepair.setStatus("2");
                    } else if (!has0 && !has1 && has2) {
                        // 3. 全部为 2 -> 全部驳回
                        toBeRepair.setStatus("3");
                    } else if (has0 && (has1 || has2)) {
                        // 4. 有 0 且有其他状态 -> 审核中
                        toBeRepair.setStatus("4");
                    } else if (!has0 && has1 && has2) {
                        // 5. 无 0，有 1 且有 2 -> 驳回待处理
                        toBeRepair.setStatus("5");
                    } else {
                        toBeRepair.setStatus("");
                    }
                }
            }

            // 创建一个 Map 来直接指定每个状态码的排序权重
            Map<String, Integer> statusSortOrder = new HashMap<>();
            statusSortOrder.put("4", 0); // 审核中，权重最高
            statusSortOrder.put("5", 2); // 驳回待处理
            statusSortOrder.put("3", 3); // 全部驳回
            statusSortOrder.put("1", 1); // 待审核
            statusSortOrder.put("2", 4); // 全部通过，权重最低

            // 对于未定义的状态（如空字符串），给一个最大的权重，让它排在最后
            final int DEFAULT_ORDER = 99;

            // 使用 Stream API 进行排序
            list = list.stream()
                    .sorted(Comparator
                            .comparingInt((ToBeRepair repair) -> statusSortOrder.getOrDefault(repair.getStatus(), DEFAULT_ORDER))
                            .thenComparing(Comparator.comparing(ToBeRepair::getCreateTime).reversed()))
                    .collect(Collectors.toList());


            // 状态过滤
            String statusFilter = bean.getStatus();
            if (statusFilter != null && !"".equals(statusFilter)) {
                list = list.stream()
                        .filter(item -> statusFilter.equals(item.getStatus()))
                        .collect(Collectors.toList());
            }*/

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteRepairList(ToBeRepair bean) {
        try {
            //删除主任务
            int num = mapper.deleteChangeInfo(bean);
            if (num < 1) {
                throw new Exception("删除主任务失败");
            }
            //删除设备详情
            num = mapper.deleteChangeDetails(bean);
            if (num < 1) {
                throw new Exception("删除设备详情失败");
            }
            return AjaxResult.success("删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("删除失败");
        }
    }

    @Override
    public List<ToBeRepair> getRepairDetailsList(ToBeRepair bean) {
        try {
            List<ToBeRepair> list = mapper.getRepairDetailsList(bean);
            if (!list.isEmpty()){
                for (ToBeRepair toBeRepair : list){
                    if (!StringHelper.isNullOrEmptyString(toBeRepair.getUrl())){
                        List<BmFileInfo> bmFileInfos = new ArrayList<>();
                        BmFileInfo fileInfo = new BmFileInfo();
                        fileInfo.setFileUrl(toBeRepair.getUrl());
                        bmFileInfos.add(fileInfo);
                        toBeRepair.setBmFileInfos(bmFileInfos);
                    }
                }
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    /**
     * 审核维修任务明细
     * 注意：此方法由审批回调内部调用，不应直接暴露给前端
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult auditData(ToBeRepair bean) {
        try {
            if (bean.getToBeRepairList().size() <= 0) {
                return AjaxResult.error("请选择审核数据");
            }
            String username = SecurityUtils.getLoginUser().getSysUser().getNickName();
            Long userId = SecurityUtils.getLoginUser().getUserid();
            for (ToBeRepair toBeRepair : bean.getToBeRepairList()) {
                //查询设备是否已经处理过
                if ("编码管理".equals(toBeRepair.getManageMode())){
                    //1、如果是编码管理，查询状态是否为维修状态
                    if ("装备".equals(toBeRepair.getType())){
                        ToBeRepair bean1 = mapper.selectMaDevInfoByTypeIdAndCode(toBeRepair);
                        if (bean1==null || !"5".equals(bean1.getStatus())){
                            return AjaxResult.error(toBeRepair.getCode()+"编码设备已经处理过");
                        }
                    } else if ("工具".equals(toBeRepair.getType())){
                        ToBeRepair bean1 = mapper.selectByTypeIdAndCode(toBeRepair);
                        if (bean1==null || !"2".equals(bean1.getStatus())){
                            return AjaxResult.error(toBeRepair.getCode()+"编码设备已经处理过");
                        }
                    }
                } else if ("数量管理".equals(toBeRepair.getManageMode())){
                    //2、如果是数量管理，查询剩余的维修数量是否够
                    //todo 目前数量管理的设备都是工具
                    ToBeRepair bean1 = mapper.selectByTypeIdAndCode(toBeRepair);
                    if (bean1==null || bean1.getRepairNum().compareTo(toBeRepair.getRepairNum())<0){
                        return AjaxResult.error(toBeRepair.getTypeModelName()+"剩余维修设备数量不足");
                    }
                }
                if (!StringHelper.isNullOrEmptyString(toBeRepair.getAuditStatus())){
                    toBeRepair.setCreateUser(username);
                    int res = mapper.auditData(toBeRepair);
                    if (res <= 0) {
                        throw new Exception("审核详情表数据失败");
                    }
                    // 根据id查询changeId
                    ToBeRepair info = mapper.selectInfoId(toBeRepair);
                    info.setAuditStatus(toBeRepair.getAuditStatus());
                    info.setCreateBy(userId.toString());
                    // 审核主表
                    res = mapper.auditInfoById(info);
                    if (res <= 0) {
                        throw new Exception("审核主表数据失败");
                    }
                    //如果是审核通过，需要增加周期表数据以及更新台账信息
                    if ("2".equals(toBeRepair.getAuditStatus())){
                        if ("工具".equals(toBeRepair.getType())){
                            //根据typeId和code查询台账信息
                            ToBeRepair bean1 = mapper.selectByTypeIdAndCode(toBeRepair);
                            if (bean1 != null && bean1.getId() > 0){
                                //1、添加周期表数据
                                ToBeRepair bean2 = new ToBeRepair();
                                bean2.setId(bean1.getId());
                                bean2.setCreateBy(userId+"");
                                bean2.setCreateUser(username);
                                bean2.setCode(toBeRepair.getCode());
                                bean2.setRepairNum(toBeRepair.getRepairNum());
                                bean2.setIsScrap(toBeRepair.getIsScrap());
                                bean2.setIsScrapFilter(Integer.valueOf(toBeRepair.getIsScrap()));
                                int re = mapper.addToolLifecycleByRepair(bean2);
                                if (re <= 0) {
                                    throw new Exception("添加周期表数据失败");
                                }
                                //2、更新台账信息
                                int re2 = mapper.updateToolLifecycle(bean2);
                                if (re2 <= 0) {
                                    throw new Exception("更新台账信息失败");
                                }
                            }
                        } else if ("装备".equals(toBeRepair.getType())){
                            //更新台账信息
                            toBeRepair.setCreateBy(userId+"");
                            toBeRepair.setIsScrapFilter(Integer.valueOf(toBeRepair.getIsScrap()));
                            int re3 = mapper.updateMaDevInfo(toBeRepair);
                            if (re3<=0){
                                throw new Exception("更新台账信息失败");
                            }
                        }
                    }
                } else {
                    throw new Exception("缺少审核状态");
                }
            }
            return AjaxResult.success("审核成功");
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("审核失败");
        }
    }

    /**
     * 获取登录用户昵称
     */
    private String getCurrentUsername() {
        return SecurityUtils.getLoginUser().getSysUser().getNickName();
    }

    /**
     * 创建维修任务
     */
    private Long createRepairTask(String username) throws Exception {
        int maxOrder = mapper.getMonthMaxOrderByDate(
                DateUtils.getCurrentYear(),
                DateUtils.getCurrentMonth(),
                TypeEnums.TM_TASK_REPAIR.getTaskTypeId()
        );
        String code = genderTaskCode(maxOrder);
        CsDeviceInfo deviceInfo = new CsDeviceInfo();
        deviceInfo.setType("4");
        deviceInfo.setCode(code);
        deviceInfo.setReviewStatus("0");
        deviceInfo.setCreateUser(username);
        deviceInfo.setCompanyId(SecurityUtils.getLoginUser().getSysUser().getDeptId());
        int result = mapper.addDeviceChange(deviceInfo);
        if (result < 1) {
            throw new Exception("添加任务失败");
        }
        return deviceInfo.getId();
    }

    /**
     * 处理维修明细
     */
    private void processRepairDetail(ToBeRepair detail, Long changeId, String username) throws Exception {
        detail.setChangeId(changeId);
        detail.setCreateUser(username);
        if (StringHelper.isNullOrEmptyString(detail.getIsScrap())) {
            throw new Exception("缺少合格状态数据");
        }
        fillFileUrl(detail);
        if ("1".equals(detail.getIsScrap()) && "数量管理".equals(detail.getManageMode())){
            saveScrapAndQualified(detail);
        } else {
            insertDetail(detail);
        }
    }

    /**
     * 处理维修是否合格，选择了否，并且是数量管理的数据
     */
    private void saveScrapAndQualified(ToBeRepair detail) throws Exception {
        BigDecimal repairNum = detail.getRepairNum();
        BigDecimal retirementNum = detail.getRetirementNum();

        if (retirementNum == null || retirementNum.compareTo(BigDecimal.ZERO) <= 0) {
            throw new Exception("退役数量不能为空或0");
        }
        // 1. 不合格记录
        detail.setRepairNum(retirementNum);
        insertDetail(detail);
        // 2. 合格数量（如果有剩余）
        if (repairNum != null && repairNum.compareTo(retirementNum) > 0) {
            detail.setRepairNum(repairNum.subtract(retirementNum));
            detail.setIsScrap("0");
            detail.setReasonVal("");
            detail.setRepairUrl("");
            insertDetail(detail);
        }
    }

    /**
     * 详情数据新增
     */
    private void insertDetail(ToBeRepair detail) throws Exception {
        if (mapper.addRepairData(detail) <= 0) {
            throw new Exception("添加设备详情失败");
        }
    }



    /**
     * 处理文件
     */
    private void fillFileUrl(ToBeRepair detail) {
        List<BmFileInfo> files = detail.getBmFileInfos();
        if (files != null && !files.isEmpty()) {
            String url = files.get(0).getFileUrl();
            if ("0".equals(detail.getIsScrap())) {
                detail.setRepairUrl(url);
            } else {
                detail.setScrapUrl(url);
            }
        }
    }

    /**
     * 生成任务编号
     * @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.REPAIR_TASK_TYPE_LABEL + result + String.format("-%04d", thisMonthMaxOrder + 1);
    }
}
