package com.hz.pm.api.projectdeclared.utils;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.function.VUtils;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.common.model.constant.RegionConst;
import com.hz.pm.api.gov.contants.BizProjectContant;
import com.hz.pm.api.gov.model.dto.*;
import com.hz.pm.api.gov.model.entity.GovBizProjectBaseinfo;
import com.hz.pm.api.gov.model.entity.GovOperationProjectBaseinfo;
import com.hz.pm.api.gov.service.IGovBizProjectBaseinfoService;
import com.hz.pm.api.gov.service.IGovOperationProjectBaseinfoService;
import com.hz.pm.api.projectdeclared.contants.ProjectCodeContant;
import com.hz.pm.api.projectlib.model.dto.ProjectDTO;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.entity.ProjectCollection;
import com.hz.pm.api.projectlib.service.IProjectService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

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

/**
 * 生成项目编号工具类
 *
 * @author CMM
 * @since 2023/04/04 14:13
 */
@Component
@RequiredArgsConstructor
public class GenerateProjectCodeUtil {

    private final IProjectService projectService;
    private final IGovBizProjectBaseinfoService baseinfoService;
    private final IGovOperationProjectBaseinfoService operationProjectBaseinfoService;

    public String generateProjectCode(ProjectDTO project) {
        // 获取所属行政区划代码(9位)
        // String areaCode = project.getAreaCode() + ProjectCodeContant.REGION_LAST_3;
        String areaCode = RegionConst.RC_HZ + ProjectCodeContant.REGION_LAST_3;
        // 获取建设年度 (10-13)
        String year = Objects.nonNull(project.getProjectYear()) ? String.valueOf(project.getProjectYear())
                : String.valueOf(LocalDateTime.now().getYear());
        // 14-15 项目类型
        String projectType = project.getProjectType();
        // 16-20 项目序号00001
        String currentCode = areaCode + year + projectType;
        // 16-20 项目序号00001
        //要查询 两边的项目序号
        Long max = getMaxProjectCode(currentCode);
        // 生成20位的项目编号
        return currentCode + String.format(ProjectCodeContant.SHUZI_5, max);
    }

    public String generateProjectCode(ProjectCollection project) {
        // 获取所属行政区划代码(9位)
        // String areaCode = project.getAreaCode() + ProjectCodeContant.REGION_LAST_3;
        String areaCode = RegionConst.RC_HZ + ProjectCodeContant.REGION_LAST_3;
        // 获取建设年度 (10-13)
        String year = Objects.nonNull(project.getProjectYear()) ? String.valueOf(project.getProjectYear())
                : String.valueOf(LocalDateTime.now().getYear());
        // 14-15 项目类型
        String projectType = ProjectCodeContant.PROJECT_TYPE_PREFIX + project.getProjectType();
        // 16-20 项目序号00001
        String currentCode = areaCode + year + projectType;
        // 16-20 项目序号00001
        //要查询 最大的项目编号
        Long max = getMaxProjectCode(currentCode);
        // 生成20位的项目编号
        return currentCode + String.format(ProjectCodeContant.SHUZI_5, max);
    }

    public String generateProjectCode(GovBizProjectSaveDTO dto) {
        // 获取所属行政区划代码(9位)
        GovBizProjectBaseinfoDTO baseinfo = dto.getBaseinfo();
        GovBizProjectApplyDTO apply = dto.getApply();

        VUtils.isTrue(Objects.isNull(baseinfo)).throwMessage("没有项目基本信息 无法生成项目编号!");
        VUtils.isTrue(Objects.isNull(apply)).throwMessage("没有项目申报信息 无法生成项目编号!");

        // String areaCode = (StringUtils.isNotBlank(baseinfo.getBaseAreaCode()) ? baseinfo.getBaseAreaCode() : RegionConst.RC_HZ + BizConst.NINE_AREA_CODE_LAST);
        String areaCode = RegionConst.RC_HZ + BizConst.NINE_AREA_CODE_LAST;
        // 获取建设年度 (10-13)
        String year = Objects.nonNull(apply.getBaseProjSetYear()) ? apply.getBaseProjSetYear()
                : String.valueOf(LocalDateTime.now().getYear());
        // 14-15 项目类型
        String projectType = StringUtils.isNotBlank(baseinfo.getBaseProjType()) ? baseinfo.getBaseProjType() :
                BizProjectContant.ProjectCollection.IS_EFFECTIVE;
        String currentCode = areaCode + year + projectType;
        // 16-20 项目序号00001
        //要查询 最大的项目编号
        Long max = getMaxProjectCode(currentCode);
        // 生成20位的项目编号
        return currentCode + String.format(ProjectCodeContant.SHUZI_5, max);
    }

    public String generateProjectCode(GovOperationProjectSaveDTO dto) {
        // 获取所属行政区划代码(9位)
        GovOperationProjectBaseinfoDTO baseinfo = dto.getBaseinfo();
        GovBizProjectApplyDTO apply = dto.getApply();

        VUtils.isTrue(Objects.isNull(baseinfo)).throwMessage("没有项目基本信息 无法生成项目编号!");
        VUtils.isTrue(Objects.isNull(apply)).throwMessage("没有项目申报信息 无法生成项目编号!");

        // String areaCode = (StringUtils.isNotBlank(baseinfo.getBaseAreaCode()) ? baseinfo.getBaseAreaCode() : RegionConst.RC_HZ + BizConst.NINE_AREA_CODE_LAST);
        String areaCode = RegionConst.RC_HZ + BizConst.NINE_AREA_CODE_LAST;
        // 获取建设年度 (10-13)
        String year = Objects.nonNull(apply.getBaseProjSetYear()) ? apply.getBaseProjSetYear()
                : String.valueOf(LocalDateTime.now().getYear());
        // 14-15 项目类型
        String projectType = StringUtils.isNotBlank(baseinfo.getBaseProjType()) ? baseinfo.getBaseProjType() :
                BizProjectContant.ProjectCollection.IS_EFFECTIVE;
        String currentCode = areaCode + year + projectType;
        // 16-20 项目序号00001
        //要查询 最大的项目编号
        Long max = getMaxProjectCode(currentCode);
        // 生成20位的项目编号
        return currentCode + String.format(ProjectCodeContant.SHUZI_5, max);
    }

    private Long getMaxProjectCode(String currentCode) {
        long max = 0L;
        GovBizProjectBaseinfo baseMax = baseinfoService.getOne(Wrappers.lambdaQuery(GovBizProjectBaseinfo.class)
                .like(GovBizProjectBaseinfo::getBaseProjId, currentCode)
                .orderByDesc(GovBizProjectBaseinfo::getBaseProjId)
                .last(BizConst.LIMIT_1));
        if (Objects.nonNull(baseMax) && StringUtils.isNotBlank(baseMax.getBaseProjId())) {
            max = Long.parseLong(baseMax.getBaseProjId().substring(baseMax.getBaseProjId().length() - 5));
        }
        GovOperationProjectBaseinfo operationBaseMax = operationProjectBaseinfoService.getOne(Wrappers.lambdaQuery(GovOperationProjectBaseinfo.class)
                .like(GovOperationProjectBaseinfo::getBaseProjId, currentCode)
                .orderByDesc(GovOperationProjectBaseinfo::getBaseProjId)
                .last(BizConst.LIMIT_1));
        if (Objects.nonNull(operationBaseMax) && StringUtils.isNotBlank(operationBaseMax.getBaseProjId())) {
            long operationMax = Long.parseLong(operationBaseMax.getBaseProjId().substring(operationBaseMax.getBaseProjId().length() - 5));
            max = Math.max(max, operationMax);
        }
        Project projectMax = projectService.getOne(Wrappers.lambdaQuery(Project.class)
                .like(Project::getProjectCode, currentCode)
                .orderByDesc(Project::getProjectCode)
                .last(BizConst.LIMIT_1));
        if (Objects.nonNull(projectMax) && StringUtils.isNotBlank(projectMax.getProjectCode())) {
            long projectMaxCode = Long.parseLong(projectMax.getProjectCode().substring(projectMax.getProjectCode().length() - 5));
            max = Math.max(max, projectMaxCode);
        }
        max = max + 1;
        return max;
    }
}
