package com.hz.pm.sync.open.manage;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hz.pm.sync.scheduler.model.dto.ProjectBaseInfoDTO;
import com.hz.pm.sync.scheduler.model.dto.ProjectSaveDTO;
import com.hz.pm.sync.scheduler.model.entity.*;
import com.hz.pm.sync.scheduler.service.*;
import com.ningdatech.basic.function.VUtils;
import com.ningdatech.basic.util.StrPool;
import com.hz.pm.sync.common.constant.BizConst;
import com.hz.pm.sync.open.enumeration.GovProjectStatusEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * @Classname ProjectReceiveManage
 * @Description
 * @Date 2023/8/25 9:11
 * @Author PoffyZhang
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class ProjectReceiveManage {

    private final IProjectBaseInfoService baseInfoService;

    private final IProjectApplyService applyService;

    private final IProjectApproveService approveService;

    private final IProjectCimplementService cimplementService;

    private final IProjectMimplementService mimplementService;

    private final IProjectProcureService procureService;

    /**
     * 接收保存 项目
     *
     * @param dto
     * @return
     */
    public String save(ProjectSaveDTO dto) {

        //1.保存项目基本信息
        ProjectBaseInfo baseInfo = dto.getBaseinfo();
        String baseProjId = baseInfo.getBaseProjId();
        VUtils.isTrue(StringUtils.isBlank(baseProjId))
                .throwMessage("项目编号不能为空!");

        ProjectBaseInfo oldBaseInfo = baseInfoService.getOne(Wrappers.lambdaQuery(ProjectBaseInfo.class)
                .eq(ProjectBaseInfo::getBaseProjId, baseProjId)
                .last(BizConst.LIMIT_1));
        ProjectBaseInfo saveBase = BeanUtil.copyProperties(baseInfo, ProjectBaseInfo.class);

        //项目状态
        String baseProjSetProg = saveBase.getBaseProjSetProg();
        if (StringUtils.isBlank(baseProjSetProg)) {
            return "无状态不保存";
        }
        //评审中 基本信息和申报信息
        GovProjectStatusEnum match = GovProjectStatusEnum.match(baseProjSetProg);
        if (Objects.isNull(match)) {
            return "状态不对 不保存";
        }
        switch (match) {
            case APPROVAL:
                log.info("评审中状态 保存基本信息和申报信息 :{}", baseProjId);
                saveBase(oldBaseInfo, saveBase, baseInfo);
                saveApply(dto, baseProjId);
                break;
            case PENDING:
            case APPROVED:
                log.info("待立项和已立项状态 保存基本信息,申报信息,评审信息 :{}", baseProjId);
                saveBase(oldBaseInfo, saveBase, baseInfo);
                saveApply(dto, baseProjId);
                saveApprove(dto, baseProjId);
                break;
            case PURCHASED:
                log.info("已采购状态 保存基本信息,申报信息,评审信息,采购信息 :{}", baseProjId);
                saveBase(oldBaseInfo, saveBase, baseInfo);
                saveApply(dto, baseProjId);
                saveApprove(dto, baseProjId);
                saveProcure(dto, baseProjId);
                break;
            case HAS_PRE_INS:
            case HAS_FINAL_INS:
            case TERMINATED:
                log.info("初验 终验状态 终止 保存所有信息 :{}", baseProjId);
                saveBase(oldBaseInfo, saveBase, baseInfo);
                saveApply(dto, baseProjId);
                saveApprove(dto, baseProjId);
                saveProcure(dto, baseProjId);
                saveCimplementOrMimplement(dto, baseProjId);
                break;
            case REJECTED:
                log.info("驳回终止状态 啥都不保存 :{}", baseProjId);
                break;
            default:
                log.info("没有匹配任何状态 保存失败 :{}", baseProjId);
        }

        return BizConst.SAVE_SUCCESS;
    }

    private void saveCimplementOrMimplement(ProjectSaveDTO dto, String baseProjId) {
        // 4.保存 建设项目 实施信息
        ProjectCimplement cimplement = dto.getCimplement();
        if (Objects.nonNull(cimplement)) {
            ProjectCimplement oldCimplement = cimplementService.getOne(Wrappers.lambdaQuery(ProjectCimplement.class)
                    .eq(ProjectCimplement::getBaseProjId, baseProjId)
                    .last(BizConst.LIMIT_1));

            ProjectCimplement saveCimplement = BeanUtil.copyProperties(cimplement, ProjectCimplement.class);
            saveCimplement.setBaseProjId(baseProjId);
            if (Objects.isNull(oldCimplement)) {
                //如果当前 数据不存在 但是我们平台操作是修改 说明之前数据被推送过了那么 可以置为修改update
                if (StringUtils.isNotBlank(cimplement.getOp()) && BizConst.OP_UPDATE.equals(cimplement.getOp())) {
                    saveCimplement.setOp(BizConst.OP_UPDATE);
                } else {
                    saveCimplement.setOp(BizConst.OP_INSERT);
                }
                saveCimplement.setTongTime(LocalDateTime.now());
            } else {
                saveCimplement.setOp(BizConst.OP_INSERT);
                saveCimplement.setTongID(oldCimplement.getTongID());
                saveCimplement.setTongTime(LocalDateTime.now());
            }
            saveCimplement.setBizTime(LocalDateTime.now());
            cimplementService.saveOrUpdate(saveCimplement);
        }

        // 5.保存 运维项目 实施信息
        ProjectMimplement mimplement = dto.getMimplement();
        if (Objects.nonNull(mimplement)) {
            ProjectMimplement oldMimplement = mimplementService.getOne(Wrappers.lambdaQuery(ProjectMimplement.class)
                    .eq(ProjectMimplement::getBaseProjId, baseProjId)
                    .last(BizConst.LIMIT_1));

            ProjectMimplement saveMimplement = BeanUtil.copyProperties(mimplement, ProjectMimplement.class);
            saveMimplement.setBaseProjId(baseProjId);
            if (Objects.isNull(oldMimplement)) {
                //如果当前 数据不存在 但是我们平台操作是修改 说明之前数据被推送过了那么 可以置为修改update
                if (StringUtils.isNotBlank(mimplement.getOp()) && BizConst.OP_UPDATE.equals(mimplement.getOp())) {
                    saveMimplement.setOp(BizConst.OP_UPDATE);
                } else {
                    saveMimplement.setOp(BizConst.OP_INSERT);
                }
                saveMimplement.setTongTime(LocalDateTime.now());
            } else {
                saveMimplement.setOp(BizConst.OP_INSERT);
                saveMimplement.setTongID(oldMimplement.getTongID());
                saveMimplement.setTongTime(LocalDateTime.now());
            }
            saveMimplement.setBizTime(LocalDateTime.now());
            mimplementService.saveOrUpdate(saveMimplement);
        }
    }

    private void saveProcure(ProjectSaveDTO dto, String baseProjId) {
        // 6.保存 采购信息
        List<ProjectProcure> procures = dto.getProcures();
        if (Objects.nonNull(procures)) {
            List<ProjectProcure> olds = procureService.list(Wrappers.lambdaQuery(ProjectProcure.class)
                    .eq(ProjectProcure::getBaseProjId, baseProjId)
                    .orderByAsc(ProjectProcure::getBaseBidCode));
            int index = 0;
            for (ProjectProcure old : olds) {
                if (StringUtils.isNotBlank(old.getBaseBidCode())) {
                    try {
                        String bidCode = old.getBaseBidCode().split(StrPool.DASH)[1];
                        index = Integer.parseInt(bidCode);
                    } catch (Exception e) {
                        log.error(e.getMessage(),e);
                    }
                }
                //删除标记
                old.setOp(BizConst.OP_DELETE);
                procureService.updateById(old);
            }
            index++;
            for (ProjectProcure procure : procures) {
                //添加标记
                ProjectProcure saveProcure = BeanUtil.copyProperties(procure, ProjectProcure.class);
                saveProcure.setBaseProjId(baseProjId);
                saveProcure.setBaseBidCode(baseProjId + StrPool.DASH + String.format(StrPool.FORMAT_DATE_SINGLE_DIGITS, index));
                saveProcure.setTongID(null);
                saveProcure.setTongTime(LocalDateTime.now());
                saveProcure.setBizTime(LocalDateTime.now());
                saveProcure.setOp(BizConst.OP_INSERT);
                procureService.save(saveProcure);
                index++;
            }
        }
    }

    private void saveApprove(ProjectSaveDTO dto, String baseProjId) {
        // 3.保存 审批信息
        ProjectApprove approve = dto.getApprove();

        ProjectApprove oldApprove = approveService.getOne(Wrappers.lambdaQuery(ProjectApprove.class)
                .eq(ProjectApprove::getBaseProjId, baseProjId)
                .last(BizConst.LIMIT_1));

        ProjectApprove saveApprove = BeanUtil.copyProperties(approve, ProjectApprove.class);
        saveApprove.setBaseProjId(baseProjId);
        if (Objects.isNull(oldApprove)) {
            //如果当前 数据不存在 但是我们平台操作是修改 说明之前数据被推送过了那么 可以置为修改update
            if (StringUtils.isNotBlank(approve.getOp()) && BizConst.OP_UPDATE.equals(approve.getOp())) {
                saveApprove.setOp(BizConst.OP_UPDATE);
            } else {
                saveApprove.setOp(BizConst.OP_INSERT);
            }
            saveApprove.setTongTime(LocalDateTime.now());
        } else {
            saveApprove.setOp(BizConst.OP_INSERT);
            saveApprove.setTongID(oldApprove.getTongID());
            saveApprove.setTongTime(LocalDateTime.now());
        }
        saveApprove.setBizTime(LocalDateTime.now());
        approveService.saveOrUpdate(saveApprove);
    }

    private void saveApply(ProjectSaveDTO dto, String baseProjId) {
        // 2.保存 申报信息
        ProjectApply apply = dto.getApply();

        ProjectApply oldApply = applyService.getOne(Wrappers.lambdaQuery(ProjectApply.class)
                .eq(ProjectApply::getBaseProjId, baseProjId)
                .last(BizConst.LIMIT_1));

        ProjectApply saveApply = BeanUtil.copyProperties(apply, ProjectApply.class);
        saveApply.setBaseProjId(baseProjId);
        if (Objects.isNull(oldApply)) {
            //如果当前 数据不存在 但是我们平台操作是修改 说明之前数据被推送过了那么 可以置为修改update
            if (StringUtils.isNotBlank(apply.getOp()) && BizConst.OP_UPDATE.equals(apply.getOp())) {
                saveApply.setOp(BizConst.OP_UPDATE);
            } else {
                saveApply.setOp(BizConst.OP_INSERT);
            }
            saveApply.setTongTime(LocalDateTime.now());
        } else {
            saveApply.setOp(BizConst.OP_INSERT);
            saveApply.setTongID(oldApply.getTongID());
            saveApply.setTongTime(LocalDateTime.now());
        }

        saveApply.setBizTime(LocalDateTime.now());
        applyService.saveOrUpdate(saveApply);
    }

    //保存基本信息
    private void saveBase(ProjectBaseInfo oldBaseInfo, ProjectBaseInfo saveBase, ProjectBaseInfo baseInfo) {
        if (Objects.isNull(oldBaseInfo)) {
            //如果当前 数据不存在 但是我们平台操作是修改 说明之前数据被推送过了那么 可以置为修改update
            if (StringUtils.isNotBlank(baseInfo.getOp()) && BizConst.OP_UPDATE.equals(baseInfo.getOp())) {
                saveBase.setOp(BizConst.OP_UPDATE);
            } else {
                saveBase.setOp(BizConst.OP_INSERT);
            }
            saveBase.setTongTime(LocalDateTime.now());
        } else {
            saveBase.setOp(BizConst.OP_INSERT);
            saveBase.setTongID(oldBaseInfo.getTongID());
            saveBase.setTongTime(LocalDateTime.now());
        }
        saveBase.setBizTime(LocalDateTime.now());
        baseInfoService.saveOrUpdate(saveBase);
    }

    /**
     * 置为无效
     *
     * @param dto
     * @return
     */
    public String notEffective(ProjectBaseInfoDTO dto) {
        ProjectBaseInfo oldBaseInfo = baseInfoService.getOne(Wrappers.lambdaQuery(ProjectBaseInfo.class)
                .eq(ProjectBaseInfo::getBaseProjId, dto.getBaseProjId())
                .last(BizConst.LIMIT_1));

        ProjectBaseInfo saveBaseinfo = BeanUtil.copyProperties(dto, ProjectBaseInfo.class);
        saveBaseinfo.setIsEffective(BizConst.NOT_EFFECTIVE);
        if (Objects.isNull(oldBaseInfo)) {
            saveBaseinfo.setTongTime(LocalDateTime.now());
        }
        saveBaseinfo.setBizTime(LocalDateTime.now());
        saveBaseinfo.setOp(BizConst.OP_UPDATE);
        baseInfoService.saveOrUpdate(saveBaseinfo);

        return BizConst.OP_SUCCESS;
    }

    /**
     * 删除表里的所有数据
     *
     * @return
     */
    public String deleteAll() {
        baseInfoService.remove(Wrappers.lambdaQuery(ProjectBaseInfo.class));
        applyService.remove(Wrappers.lambdaQuery(ProjectApply.class));
        approveService.remove(Wrappers.lambdaQuery(ProjectApprove.class));
        cimplementService.remove(Wrappers.lambdaQuery(ProjectCimplement.class));
        mimplementService.remove(Wrappers.lambdaQuery(ProjectMimplement.class));
        procureService.remove(Wrappers.lambdaQuery(ProjectProcure.class));
        log.info("删除所有前置表数据成功");
        return BizConst.OP_SUCCESS;
    }
}
