package com.bonus.sgzb.app.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.bonus.sgzb.app.domain.TmTask;
import com.bonus.sgzb.app.mapper.BackReceiveMapper;
import com.bonus.sgzb.app.mapper.TmTaskMapper;
import com.bonus.sgzb.app.service.BackReceiveService;
import com.bonus.sgzb.base.api.domain.BackApplyInfo;
import com.bonus.sgzb.base.api.domain.MaMachine;
import com.bonus.sgzb.base.api.domain.MachinePart;
import com.bonus.sgzb.base.api.domain.SltAgreementInfo;
import com.bonus.sgzb.base.mapper.MaMachineMapper;
import com.bonus.sgzb.common.core.constant.TaskTypeConstants;
import com.bonus.sgzb.common.core.enums.TaskStatusEnum;
import com.bonus.sgzb.common.core.enums.TaskTypeEnum;
import com.bonus.sgzb.common.core.utils.DateUtils;
import com.bonus.sgzb.common.core.utils.HttpHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author hay
 * @description 退料申请--app
 * @date 2024/1/22 11:16
 */

@Service
@Slf4j
public class BackReceiveServiceImpl implements BackReceiveService {

    @Resource
    private BackReceiveMapper backReceiveMapper;
    @Resource
    private MaMachineMapper maMachineMapper;


    @Resource
    private TmTaskMapper tmTaskMapper;

    @Value("${sgzb.updateItemStatusUrl}")
    private String updateItemStatus;



    @Override
    public List<BackApplyInfo> getbackReceiveList(BackApplyInfo record) {
        return backReceiveMapper.getbackReceiveList(record);
    }

    @Override
    public List<BackApplyInfo> receiveView(BackApplyInfo record) {
        List<BackApplyInfo> backApplyInfoList = backReceiveMapper.receiveView4FrontEnd(record);
        int count1 = 0;
        int count2 = 0;
        for (BackApplyInfo backApplyInfo : backApplyInfoList) {
            if ("2".equals(backApplyInfo.getManageType())) {
                List<MachinePart> machineParts = new ArrayList<>();
                List<TmTask> typeIds = tmTaskMapper.getMaTypeDetailsByTypeId(backApplyInfo);
                typeIds.removeIf(item -> item == null);
                for (TmTask typeId : typeIds) {
                    MachinePart machinePart = tmTaskMapper.getMachineParts(typeId);
                    machinePart.setParentId(record.getId().intValue());
                    int countMachineByPidAndTid = tmTaskMapper.getCountMachineByPidAndTid(machinePart);
                    Integer machinePartNum = typeId.getPartNum() * backApplyInfo.getAuditNum();
                    count1 += machinePartNum;
                    count2 += countMachineByPidAndTid;
                    machinePart.setPartNum(machinePartNum - countMachineByPidAndTid);
                    machineParts.add(machinePart);
                }
                backApplyInfo.setMaTypeDetails(machineParts);
                if (count1 == count2) {
                    backApplyInfo.setPartNum(0);
                } else {
                    backApplyInfo.setPartNum(backApplyInfo.getAuditNum());
                }
            }
        }
        return backApplyInfoList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int setNumBack(BackApplyInfo record) {
        int res;
        try {
            int taskId = record.getTaskId();
            //修改任务状态
            updateTaskStatus(taskId, 39);
            //插入back_check_details
            res = insertBcd(record);
            if (res == 0) {
                return res;
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return res;
    }

    private int updateTaskStatus(int taskId, int i) {
        int res;
        res = backReceiveMapper.updateTaskStatus(taskId, i);
        return res;
    }

    private int finishBackCheckDetails(BackApplyInfo record) {
        return backReceiveMapper.finishBackCheckDetails(record);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int setCodeBack(BackApplyInfo record) {
        int res = 0;
        try {
            BackApplyInfo[] arr = record.getArr();
            if (arr.length > 0) {
                for (int i = 0; i < arr.length; i++) {
                    //判断是否超出审核数量
                    int re = backReceiveMapper.selectNumByTypeId(arr[i].getParentId(), arr[i].getTypeId());
                    if (re <= 0) {
                        res = -2;
                        break;
                    }
                    //根据maId和taskId查询是否已接收
                    re = backReceiveMapper.selectCodeByMaIdAndTaskId(arr[i].getMaId(), record.getTaskId());
                    if (re > 0) {
                        res = -1;
                        break;
                    }
                }
                if (res < 0) {
                    return res;
                }
            }
            int taskId = record.getTaskId();
            //修改任务状态
            res = updateTaskStatus(taskId, 39);
            if (res == 0) {
                throw new RuntimeException("修改updateTaskStatus异常");
            }
            //插入back_check_details
            res = insertBcd(record);
            if (res == 0) {
                throw new RuntimeException("插入back_check_details异常");
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int endBack(BackApplyInfo record) {
        int res = 0;
        int taskId = record.getTaskId();
        //先判断是否已经完成退料了
        int taskStatus = selectTaskStatus(taskId);
        if (taskStatus == 0) {
            throw new RuntimeException("该退料单已完成退料");
        }
        List<BackApplyInfo> allList1 = backReceiveMapper.getAllList(record);
        res += getEndBackResult(record, allList1, taskId);
        return res;
    }

    private int getEndBackResult(BackApplyInfo record, List<BackApplyInfo> allList1, int taskId) {
        int res = 0;
        List<BackApplyInfo> totalList = backReceiveMapper.receiveView4Backend(record);
        boolean allZeros = totalList.stream().allMatch(n -> Double.valueOf(n.getNum()).intValue() == 0);
        if (allZeros) {
            res = updateTaskStatus(taskId, 40);
            if (res == 0) {
                throw new RuntimeException("tm_task修改状态");
            }
        }

        if (allList1 != null && allList1.size() > 0) {
            for (BackApplyInfo bai : allList1) {
                int maxBackNumBackEnd = 0;
                int passNum = 0;
                int maintenanceNum = 0;
                int scrapNum = 0;
                record.setTypeId(bai.getTypeId());
                int num = backReceiveMapper.getmaChineByCt(record);
                record.setNum(num);

                //修改任务状态
                List<BackApplyInfo> list = totalList.stream().filter(o -> o.getModelId().equals(record.getTypeId())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(totalList)) {
                    for (BackApplyInfo backApplyInfo : list) {
                        maxBackNumBackEnd += backApplyInfo.getMaxBackNumBackend();
                    }
                }
                List<BackApplyInfo> hgList = backReceiveMapper.getHgList(record);
                if (hgList != null && hgList.size() > 0) {
                    for (BackApplyInfo bi : hgList) {
                        passNum += bi.getBackNum();
                    }
                }
                List<BackApplyInfo> wxList = backReceiveMapper.getWxList(record);
                if (wxList != null && wxList.size() > 0) {
                    for (BackApplyInfo bi : wxList) {
                        maintenanceNum += bi.getBackNum();
                    }
                }
                List<BackApplyInfo> bfList = backReceiveMapper.getBfList(record);
                if (bfList != null && bfList.size() > 0) {
                    for (BackApplyInfo bi : bfList) {
                        scrapNum += bi.getBackNum();
                    }
                }
                log.error("退料接收总数与详细数据对比结果:maxBackNumBackEnd={},passNum={},maintenanceNum={},scrapNum={}", maxBackNumBackEnd, passNum, maintenanceNum, scrapNum);
                if (maxBackNumBackEnd < passNum + maintenanceNum + scrapNum) {
                    log.error("TypeId={}所提交的退料数量大于最大退料数,可能您的退料已被别人退掉了!", bai.getTypeId());
                    continue;
                }

                //更加退料接收的数据创建下一步流程
                //合格的插入入库记录input_apply_details，修改库存ma_type,修改机具状态
                if (hgList != null && hgList.size() > 0) {
                    res = insertIad(hgList);
                    if (res == 0) {
                        throw new RuntimeException("input_apply_details");
                    }
                    // 如果是成套的机具，成套机具的库存也要添加
//                    List<BackApplyInfo> ctList = backReceiveMapper.getCtList(record);
//                    if (ctList.size() > 0) {
//                        for (BackApplyInfo backApplyInfo : ctList) {
//                            if ("2".equals(backApplyInfo.getManageType())) {
//                                backReceiveMapper.updateMt(backApplyInfo);
//                            }
//                        }
//                    }
                    res = updateMt(hgList);
                    if (res == 0) {
                        throw new RuntimeException("ma_type");
                    }
                    res = updateMaStatus(hgList);
                    if (res == 0) {
                        throw new RuntimeException("ma_machines");
                    }
                }
                //维修的创建维修任务，插入任务协议表
                if (wxList != null && wxList.size() > 0) {
                    //插入任务表tm_task
                    int newTaskId = insertTt(wxList, TaskTypeEnum.MAINTENANCE_TASK.getCode(), record.getCreateBy());
                    //插入协议任务表tm_task_agreement
                    res = insertTta(newTaskId, wxList);
                    //插入维修记录表repair_apply_details
                    res = insertRad(newTaskId, wxList);
                }
                //待报废的创建报废任务，插入任务协议表
                if (bfList != null && bfList.size() > 0) {
                    //插入任务表tm_task
                    int newTaskId = insertTt(bfList, TaskTypeEnum.SCRAP_TASK.getCode(), record.getCreateBy());
                    //插入协议任务表tm_task_agreement
                    res = insertTta(newTaskId, bfList);
                    //插入维修记录表scrap_apply_details
                    res = insertSad(newTaskId, bfList);
                }

                //更新结算表 slt_agreement_info
                res = updateSlt4Bean(record, bai);
                if (res == 0) {
                    throw new RuntimeException("该机具未被领料使用");
                }

                //完成退料的部分，更新 back_check_details 为 is_finished=1，此部分不支持撤回
                finishBackCheckDetails(record);
                //更新退料接收时间
                updateBackReceiveTime(record);

                //库存日志
                int postStoreNum = backReceiveMapper.getmaChineByCt(record);
                record.setPostStoreNum(postStoreNum);
                record.setBackNum(passNum + maintenanceNum + scrapNum);
                record.setPassNum(passNum);
                record.setMaintenanceNum(maintenanceNum);
                record.setScrapNum(scrapNum);
            }
        }

        return res;
    }

    private void updateBackReceiveTime(BackApplyInfo record) {
        backReceiveMapper.updateBackReceiveTime(record);
    }

    private int selectTaskStatus(int taskId) {
        int taskStatus = backReceiveMapper.selectTaskStatus(taskId);
        if (taskStatus == 40) {
            return 0;
        } else {
            return 1;
        }
    }

    private int updateSlt4Bean(BackApplyInfo record, BackApplyInfo bean) {
        List<SltAgreementInfo> infoList = backReceiveMapper.getStlInfo(bean);
        if (infoList.size() > 0) {
            Integer backNum = bean.getBackNum();
            for (SltAgreementInfo info : infoList) {
                Integer num = info.getNum();
                if (backNum.equals(num)) {
                    backReceiveMapper.updateStlInfo(info, record);
                    break;
                } else if (backNum > num) {
                    backNum = backNum - num;
                    backReceiveMapper.updateStlInfo(info, record);
                } else if (backNum < num) {
                    Integer many = num - backNum;
                    backReceiveMapper.updateStlInfoTwo(info, record, backNum);
                    backReceiveMapper.insStlInfoTwo(info, many);
                    break;
                }
            }
        } else {
            return 0;
        }
        return 1;
    }

//    private int updateSlt(BackApplyInfo record, List<BackApplyInfo> hgList) {
//        for (BackApplyInfo bean : hgList) {
//            List<SltAgreementInfo> infoList = backReceiveMapper.getStlInfo(bean);
//            if (infoList.size() > 0) {
//                Integer backNum = bean.getBackNum();
//                for (SltAgreementInfo info : infoList) {
//                    Integer num = info.getNum();
//                    if (backNum.equals(num)) {
//                        backReceiveMapper.updateStlInfo(info, record);
//                        break;
//                    } else if (backNum > num) {
//                        backNum = backNum - num;
//                        backReceiveMapper.updateStlInfo(info, record);
//                    } else if (backNum < num) {
//                        Integer many = num - backNum;
//                        backReceiveMapper.updateStlInfoTwo(info, record, backNum);
//                        backReceiveMapper.insStlInfoTwo(info, many);
//                        break;
//                    }
//                }
//            } else {
//                return 0;
//            }
//        }
//        return 1;
//    }

    @Override
    public List<BackApplyInfo> codeQuery(BackApplyInfo record) {
        return backReceiveMapper.codeQuery(record);
    }

    @Override
    public List<BackApplyInfo> qrcodeQuery(BackApplyInfo record) {
        return backReceiveMapper.qrcodeQuery(record);
    }

    @Override
    public List<BackApplyInfo> backReceiveRecord(BackApplyInfo record) {
        List<BackApplyInfo> backApplyInfoList = backReceiveMapper.backReceiveRecord(record);
        return backApplyInfoList;
    }

    @Override
    public List<BackApplyInfo> rfidCodeQuery(BackApplyInfo record) {
        return backReceiveMapper.rfidCodeQuery(record);
    }

    @Override
    public int setRfidCodeBack(BackApplyInfo record) {
        int res = 0;
        try {
            BackApplyInfo[] arr = record.getArr();
            if (arr.length > 0) {
                for (int i = 0; i < arr.length; i++) {
                    //根据maId和taskId查询是否已接收
                    int re = backReceiveMapper.selectCodeByMaIdAndTaskId(arr[i].getMaId(), record.getTaskId());
                    if (re > 0) {
                        res = -1;
                        break;
                    }
                }
                if (res == -1) {
                    return res;
                }
            }
            int taskId = record.getTaskId();
            //修改任务状态
            res = updateTaskStatus(taskId, 39);
            if (res == 0) {
                throw new RuntimeException("插入back_check_details异常");
            }
            //插入back_check_details
            res = insertBcd(record);
            if (res == 0) {
                throw new RuntimeException("插入back_check_details异常");
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return res;
    }

    @Override
    public List<TmTask> getBackMachine(TmTask task) {
        return backReceiveMapper.getBackMachine(task);
    }

    @Override
    public List<TmTask> getRecord(TmTask task) {
        return backReceiveMapper.getRecord(task);
    }

    @Override
    public int revoke(BackApplyInfo record) {
        //删除back_check_details
        int res = deleteBcd(record);
        if (res == 0) {
            throw new RuntimeException("该机具未领用，撤回失败");
        }
        return res;
    }

    @Override
    public List<BackApplyInfo> backReceiveRecordWeb(BackApplyInfo record) {
        String typeId = record.getTypeId();
        String[] split = typeId.split(",");
        List<BackApplyInfo> backApplyInfoList = new ArrayList<>();
        for (String s : split) {
            record.setTypeId(s);
            BackApplyInfo backApplyInfo = backReceiveMapper.backReceiveRecordWeb(record);
            if (backApplyInfo != null) {
                backApplyInfoList.add(backApplyInfo);
            }
        }
        return backApplyInfoList;
    }

    @Override
    public List<BackApplyInfo> backReceiveRecordWebPt(BackApplyInfo record) {
        String typeId = record.getTypeId();
        String[] split = typeId.split(",");
        List<BackApplyInfo> backApplyInfoList = new ArrayList<>();
        for (String s : split) {
            record.setTypeId(s);
            List<BackApplyInfo> backApplyInfo = backReceiveMapper.backReceiveRecordWebPt(record);
            if (backApplyInfo != null) {
                for (BackApplyInfo applyInfo : backApplyInfo) {
                    backApplyInfoList.add(applyInfo);
                }
            }
        }
        return backApplyInfoList;
    }

    public int insertRad(int taskId, List<BackApplyInfo> wxList) {
        int result = 0;
        if (wxList != null) {
            for (BackApplyInfo wx : wxList) {
                wx.setTaskId(taskId);
                result = backReceiveMapper.insertRad(wx);
            }
        }
        return result;
    }

    private int insertSad(int taskId, List<BackApplyInfo> list) {
        int result = 0;
        if (list != null) {
            for (BackApplyInfo bf : list) {
                bf.setTaskId(taskId);
                result = backReceiveMapper.insertSad(bf);
            }
        }
        return result;
    }

    public int insertTta(int taskId, List<BackApplyInfo> list) {
        int res;
        String agreementId = String.valueOf(list.get(0).getAgreementId());
        res = backReceiveMapper.insertTta(taskId, agreementId);
        return res;
    }

    public int insertTt(List<BackApplyInfo> hgList, Integer taskType, String createBy) {
        int newTask;
        //生成单号
        String code = genCodeRule(taskType);
        BackApplyInfo applyInfo = new BackApplyInfo();
        applyInfo.setTaskType(Integer.valueOf(taskType));
        String taskStatus = "";
        if (TaskTypeEnum.MAINTENANCE_TASK.getCode().equals(taskType)) {
            //taskStatus = "42";
            taskStatus = TaskStatusEnum.REPAIRPENDING.getCode();
        }
        if (TaskTypeEnum.SCRAP_TASK.getCode().equals(taskType)) {
            //taskStatus = "120";
            taskStatus = TaskStatusEnum.SCRAP_UNDER_REVIEW.getCode();
        }
        applyInfo.setTaskStatus(taskStatus);
        applyInfo.setCode(code);
        //创建人
        applyInfo.setCreateBy(createBy);
        newTask = backReceiveMapper.insertTt(applyInfo);
        if (newTask > 0 && applyInfo.getTaskId() > 0) {
            newTask = applyInfo.getTaskId();
        }
        return newTask;
    }


    private int updateMaStatus(List<BackApplyInfo> hgList) {
        int res = 0;
        if (hgList != null && hgList.size() > 0) {
            for (BackApplyInfo bi : hgList) {
                Integer maId = bi.getMaId();
                if (maId == null) {
                    res = 1;
                } else {
                    res = backReceiveMapper.updateMaStatus(maId, "15");
                    //查询装备是否推送到租赁
                    MaMachine maMachine = maMachineMapper.selectMaMachineByMaId(Long.valueOf(maId));
                    if (maMachine != null && maMachine.getPushStatus().equals(1)) {
                        //同步租赁机具状态
                        try {
                            maMachine.setMaId(maId);
                            // 15---1在库，16---2已出库
                            maMachine.setMaStatus("1");
                            String content = JSONObject.toJSONString(maMachine);
                            Map<String, String> map = new HashMap<>();
                            map.put("body", content);
                            String body = JSONObject.toJSONString(map);
                            String data = HttpHelper.sendHttpPost(updateItemStatus, body);
                            log.info("dataString-=========:" + data);
                        } catch (Exception e) {
                            log.error("同步租赁商城机具状态失败");
                            throw new RuntimeException("同步租赁商城机具状态失败");
                        }
                    }
                }
            }
        }
        return res;
    }

    private int updateMt(List<BackApplyInfo> hgList) {
        int res = 0;
        if (hgList != null && hgList.size() > 0) {
            for (BackApplyInfo bi : hgList) {
                res = backReceiveMapper.updateMt(bi);
            }
        }
        return res;
    }

    private int insertIad(List<BackApplyInfo> hgList) {
        int res = 0;
        if (hgList != null && hgList.size() > 0) {
            for (BackApplyInfo bi : hgList) {
                res = backReceiveMapper.insertIad(bi);
            }
        }
        return res;
    }

    private int insertBcd(BackApplyInfo record) {
        int res = 0;
        BackApplyInfo[] arr = record.getArr();
        if (arr.length > 0) {
            for (int i = 0; i < arr.length; i++) {
                res = backReceiveMapper.insertCheckDetails(arr[i]);
                String manageType = arr[i].getManageType();
                if ("0".equals(manageType)) {
                    String backStatus = arr[i].getBackStatus();
                    int maId = arr[i].getMaId();
                    if ("1".equals(backStatus)) {
                        //退料合格状态变为退料带入库84
                        backReceiveMapper.updateMaStatus(maId, "84");
                    }
                    if ("2".equals(backStatus)) {
                        //退料维修状态变为退料待检修17
                        backReceiveMapper.updateMaStatus(maId, "17");
                    }
                    if ("3".equals(backStatus)) {
                        //退料待报废状态变为退料待报废20
                        backReceiveMapper.updateMaStatus(maId, "20");
                        //在任务表中创建一个报废任务

                    }
                }
            }
        }
        return res;
    }

    private int deleteBcd(BackApplyInfo record) {
        int res = 0;
        if (record != null) {
            String manageType = record.getManageType();
            if ("0".equals(manageType)) {
                List<Integer> maId = backReceiveMapper.getMaId(record);
                for (Integer s : maId) {
                    //机具状态变为在用
                    backReceiveMapper.updateMaStatus(s, "16");
                }
                res = backReceiveMapper.deleteCheckDetails(record);
            } else if ("2".equals(manageType)) {
                String[] split = record.getTypeIds();
                for (String s : split) {
                    record.setTypeId(s);
                    res = backReceiveMapper.deleteCheckDetails(record);
                }
            } else {
                res = backReceiveMapper.deleteCheckDetails(record);
            }

        }

        return res;
    }


    /**
     * 编号生成规则
     */
    private String genCodeRule(Integer taskType) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        Date nowDate = DateUtils.getNowDate();
        String format = dateFormat.format(nowDate);
        Integer taskNum = backReceiveMapper.selectTaskNumByMonthWx(nowDate, taskType);

            String taskNumStr = "";
            if (taskNum != null) {
                // 将字符串转换为整数
//            int num = Integer.parseInt(taskNum);
                // 执行加一操作
                taskNum++;
                // 将结果转换回字符串格式，并确保结果是四位数，不足四位则在前面补0
                taskNumStr = String.format("%04d", taskNum);
            } else {
                taskNumStr = "0001";
            }
            String code = "";
            if (TaskTypeEnum.MAINTENANCE_TASK.getCode().equals(taskType)) {
                code = TaskTypeConstants.WX;
            }

            if (TaskTypeEnum.RETURNED_MATERIALS_TO_BE_SCRAPPED.getCode().equals(taskType)) {
                code = TaskTypeConstants.YBF;
            }
            code = code + format + "-" + taskNumStr;
            return code;
        }
}
