package com.dsk.cscec.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsk.common.core.domain.PageQuery;
import com.dsk.common.core.page.TableDataInfo;
import com.dsk.common.exception.ServiceException;
import com.dsk.common.utils.StringUtils;
import com.dsk.cscec.constant.AdvisoryBodyManageQueryConstants;
import com.dsk.cscec.domain.AdvisoryBody;
import com.dsk.cscec.domain.AdvisoryBodyProject;
import com.dsk.cscec.domain.CbProjectRecord;
import com.dsk.cscec.domain.DProject;
import com.dsk.cscec.domain.bo.CbCheckProjectCodeExistBo;
import com.dsk.cscec.domain.bo.CooperateProjectDetailSearchBo;
import com.dsk.cscec.domain.bo.ProjectDetailBo;
import com.dsk.cscec.domain.bo.ProjectSearchBo;
import com.dsk.cscec.domain.vo.CbProjectInfoVo;
import com.dsk.cscec.domain.vo.CooperateProjectDetailSearchVo;
import com.dsk.cscec.domain.vo.ProjectDetailVo;
import com.dsk.cscec.domain.vo.ProjectSearchVo;
import com.dsk.cscec.mapper.AdvisoryBodyMapper;
import com.dsk.cscec.mapper.AdvisoryBodyProjectMapper;
import com.dsk.cscec.mapper.CbProjectRecordMapper;
import com.dsk.cscec.mapper.DProjectMapper;
import com.dsk.cscec.service.IDProjectService;
import com.dsk.jsk.domain.EnterpriseInfoHeaderBody;
import com.dsk.system.utils.DskOpenApiUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.poi.ss.formula.functions.DProduct;
import org.springframework.stereotype.Service;

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

/**
 * 咨询机构管理
 *
 * @author sxk
 * @since 2023-12-10 15:34:51
 */
@Slf4j
@Service("dProjectService")
public class IDProjectServiceImpl extends ServiceImpl<DProjectMapper, DProject> implements IDProjectService {
    @Resource
    private DProjectMapper baseMapper;
    @Resource
    private AdvisoryBodyMapper advisoryBodyMapper;
    @Resource
    private AdvisoryBodyProjectMapper advisoryBodyProjectMapper;
    @Resource
    private DskOpenApiUtil dskOpenApiUtil;
    @Resource
    private CbProjectRecordMapper projectRecordMapper;

    /**
     * 获取所有项目列表数据
     *
     * @param projectSearchBo 查询实体
     * @param pageQuery       分页对象
     * @return 所有数据
     */
    @Override
    public TableDataInfo<ProjectSearchVo> queryProjectList(ProjectSearchBo projectSearchBo, PageQuery pageQuery) {
        String advisoryBodyName = projectSearchBo.getAdvisoryBodyName();
        List<Long> projectKeys = null;
        if (StringUtils.isNotBlank(advisoryBodyName)) {
            //根据咨询机构名称查询咨询机构Cids
            List<Long> advisoryBodyCids = advisoryBodyMapper.selectAdvisoryBodyCidsByName(advisoryBodyName);
            //根据咨询机构Cids查询项目Keys
            List<Long> projectKeys1 = advisoryBodyProjectMapper.selectProjectKeysByAdvisoryBodyCids(advisoryBodyCids);
            if (projectKeys1.isEmpty()) {
                return TableDataInfo.build();
            }
            projectKeys = projectKeys1;
        }

        QueryWrapper<DProject> wrapper = Wrappers.query();
        //咨询机构的项目数据取中建一局集团第二建筑有限公司和他的下级组织
        wrapper
                //承包单位ID
                .eq("p.contract_org_id", AdvisoryBodyManageQueryConstants.LEVEL1_COMPANY_ID)
                //承包单位主键(字段叫主键,但并不是主键)
                .eq("p.contract_org_name", AdvisoryBodyManageQueryConstants.LEVEL1_COMPANY_NAME)
                //项目名称
                .like(StringUtils.isNotBlank(projectSearchBo.getProjectName()), "p.project_name", projectSearchBo.getProjectName())
                //根据咨询机构名称查出来对应的项目ID
                .in(ObjectUtil.isNotNull(projectKeys) && !projectKeys.isEmpty(), "p.project_key", projectKeys)
                //业主单位
                .like(StringUtils.isNotBlank(projectSearchBo.getOwnerUnit()), "p.owner_name", projectSearchBo.getOwnerUnit())
                //项目创建时间(字段去的合同签约日期)
                .between(ObjectUtil.isNotNull(projectSearchBo.getProjectStartTime()) && ObjectUtil.isNotNull(projectSearchBo.getProjectEndTime()),
                        "p.contract_sign_date",
                        projectSearchBo.getProjectStartTime(),
                        projectSearchBo.getProjectEndTime())
                //项目承接类型下拉选项
                .eq(StringUtils.isNotBlank(projectSearchBo.getProjectUndertakeType()), "p.isinvestproject", projectSearchBo.getProjectUndertakeType())
                //工程基础大类下拉选项
                .eq(StringUtils.isNotBlank(projectSearchBo.getEngineeringFoundationCategory()), "p.project_type1", projectSearchBo.getEngineeringFoundationCategory())
                //工程类别明细
                .eq(StringUtils.isNotBlank(projectSearchBo.getEngineeringCategoryDetail()), "p.project_type", projectSearchBo.getEngineeringCategoryDetail())
                //合同金额
                .between(ObjectUtil.isNotNull(projectSearchBo.getMinContractAmount()) && ObjectUtil.isNotNull(projectSearchBo.getMaxContractAmount()),
                        "p.contract_orig_value",
                        projectSearchBo.getMinContractAmount(),
                        projectSearchBo.getMaxContractAmount())
                .orderByDesc("p.contract_sign_date");
        Page<ProjectSearchVo> page = baseMapper.selectPageProjectList(pageQuery.build(), wrapper);

        for (ProjectSearchVo projectSearchVo : page.getRecords()) {
            //补充咨询机构信息
            projectSearchVo.setAdvisoryBody(this.getAdvisoryBodyByProjectKey(projectSearchVo.getProjectKey()));

            //补充项目与咨询机构关联信息
            projectSearchVo.setAdvisoryBodyProject(advisoryBodyProjectMapper.selectById(projectSearchVo.getProjectKey()));

            //关键字标红
            if (StringUtils.isNotBlank(projectSearchBo.getProjectName())) {
                projectSearchVo.setProjectName(StringUtils.markInRed(projectSearchVo.getProjectName(), projectSearchBo.getProjectName()));
            }

            //查询业主单位Cid
            String ownerName = projectSearchVo.getOwnerName();
            Map<String, Object> params = new HashMap<>();
            params.put("keyword", ownerName);
            Map jskData = MapUtils.getMap(dskOpenApiUtil.requestBody("/nationzj/enterprice/index", params), "data", null);
            //防止没有数据而导致强转错误,所以先判断下total
            if (MapUtils.getInteger(jskData, "total", 0) > 0) {
                List<Map<String, Object>> data = (List<Map<String, Object>>) jskData.get("list");
                for (Map<String, Object> companyData : data) {
                    //企业名称完全匹配上,则直接返回给前端
                    if (ownerName.equals(StringUtils.removeRed(MapUtils.getString(companyData, "name", "NotExist")))) {
                        //jskEid就是cid
                        projectSearchVo.setOwnerUnitCid(MapUtils.getLong(companyData, "jskEid"));
                    }
                }
            }
        }
        return TableDataInfo.build(page);
    }

    /**
     * 获取项目承接类型下拉列表
     *
     * @return 去重后的项目承接类型
     */
    @Override
    public List<String> queryIsInvestProject() {
        return baseMapper.queryIsInvestProject();
    }

    /**
     * 根据项目主键查询咨询机构
     *
     * @param projectKey 项目主键
     * @return 咨询机构
     */
    private AdvisoryBody getAdvisoryBodyByProjectKey(Long projectKey) {
        return advisoryBodyMapper.queryAdvisoryBodyByProjectKey(projectKey);
    }

    /**
     * 获取合作项目明细
     *
     * @param cooperateProjectDetailSearchBo 查询实体
     * @param pageQuery                      分页对象
     * @return 所有数据
     */
    @Override
    public TableDataInfo<CooperateProjectDetailSearchVo> queryCooperateProjectDetailList(CooperateProjectDetailSearchBo cooperateProjectDetailSearchBo, PageQuery pageQuery) {
        //先根据咨询机构CID查出所有该咨询机构下的项目主键keys
        List<Long> projectKeys = advisoryBodyProjectMapper.selectProjectKeysByAdvisoryBodyCids(Collections.singletonList(cooperateProjectDetailSearchBo.getAdvisoryBodyCid()));
        if (projectKeys.isEmpty()) {
            return TableDataInfo.build();
        }
        //再根据记录终改的项目主键查询项目详情
        QueryWrapper<DProject> wrapper = Wrappers.query();
        wrapper
                //项目主键
                .in("project_key", projectKeys)
                //项目名称
                .like(StringUtils.isNotBlank(cooperateProjectDetailSearchBo.getProjectName()), "project_name", cooperateProjectDetailSearchBo.getProjectName())
                //项目承接类型
                .in(ObjectUtil.isNotNull(cooperateProjectDetailSearchBo.getIsinvestproject()), "isinvestproject", cooperateProjectDetailSearchBo.getIsinvestproject())
                //工程基础大类
                .in(ObjectUtil.isNotNull(cooperateProjectDetailSearchBo.getProjectType1()), "project_type1", cooperateProjectDetailSearchBo.getProjectType1())
                //工程类别明细
                .in(ObjectUtil.isNotNull(cooperateProjectDetailSearchBo.getProjectType()), "project_type", cooperateProjectDetailSearchBo.getProjectType())
                //项目地区
                .in(ObjectUtil.isNotNull(cooperateProjectDetailSearchBo.getProvinceName()), "province_name", cooperateProjectDetailSearchBo.getProvinceName())
                .or()
                .in(ObjectUtil.isNotNull(cooperateProjectDetailSearchBo.getCityName()), "city_name", cooperateProjectDetailSearchBo.getCityName());
        Page<CooperateProjectDetailSearchVo> page = baseMapper.selectPageCooperateProjectDetailList(pageQuery.build(), wrapper);

        for (CooperateProjectDetailSearchVo cooperateProjectDetailSearchVo : page.getRecords()) {
            AdvisoryBodyProject advisoryBodyProject = advisoryBodyProjectMapper.selectById(cooperateProjectDetailSearchVo.getProjectKey());
            //填充咨询机构与项目关联信息
            cooperateProjectDetailSearchVo.setAdvisoryBodyProject(advisoryBodyProject);
            //填充结算天数
            if (ObjectUtil.isNotNull(advisoryBodyProject)) {
                Date settleStartTime = advisoryBodyProject.getSettleStartTime();
                Date settleFinishTime = advisoryBodyProject.getSettleFinishTime();
                if (ObjectUtil.isNotNull(settleStartTime) && ObjectUtil.isNotNull(settleFinishTime)) {
                    cooperateProjectDetailSearchVo.setSettlementDays(DateUtil.between(settleStartTime, settleFinishTime, DateUnit.DAY));
                } else {
                    cooperateProjectDetailSearchVo.setSettlementDays(0L);
                }
            }

            //关键字标红
            if (StringUtils.isNotBlank(cooperateProjectDetailSearchBo.getProjectName())) {
                cooperateProjectDetailSearchVo.setProjectName(StringUtils.markInRed(cooperateProjectDetailSearchVo.getProjectName(), cooperateProjectDetailSearchBo.getProjectName()));
            }
        }
        return TableDataInfo.build(page);
    }

    /**
     * 根据项目主键查询项目详情
     *
     * @param projectDetailBo 查询实体
     * @return 项目详情
     */
    @Override
    public ProjectDetailVo queryProjectDetail(ProjectDetailBo projectDetailBo) {
        Long advisoryBodyCid = projectDetailBo.getAdvisoryBodyCid();
        //查询项目明细
        DProject dProject = baseMapper.selectOne(new LambdaQueryWrapper<DProject>()
                .eq(DProject::getProjectKey, projectDetailBo.getProjectKey()));
        ProjectDetailVo projectDetailVo = BeanUtil.toBean(dProject, ProjectDetailVo.class);

        //查询咨询机构信息并填充
        projectDetailVo.setAdvisoryBody(advisoryBodyMapper.queryAdvisoryBodyByProjectKey(projectDetailBo.getProjectKey()));
        //查询项目信息并填充
        projectDetailVo.setAdvisoryBodyProject(advisoryBodyProjectMapper.selectById(projectDetailBo.getProjectKey()));

        if (ObjectUtil.isNotNull(advisoryBodyCid)) {
            EnterpriseInfoHeaderBody infoHeaderBody = new EnterpriseInfoHeaderBody();
            infoHeaderBody.setCompanyId(Math.toIntExact(advisoryBodyCid));
            Map<String, Object> companyMap = dskOpenApiUtil.requestBody("/api/jsk/enterprise/infoHeader", BeanUtil.beanToMap(infoHeaderBody, false, false));
            Map companyData = MapUtils.getMap(companyMap, "data", null);
            //法人
            projectDetailVo.setCorporatePerson(MapUtils.getString(companyData, "corporatePerson", ""));
            //注册地址
            projectDetailVo.setRegAddress(MapUtils.getString(companyData, "addressDetail", ""));
        }
        return projectDetailVo;
    }

    /**
     * 校验项目编码是否存在
     *
     * @param checkBo 待校验信息
     * @return 校验结果
     */
    @Override
    public String checkProjectCodeExist(CbCheckProjectCodeExistBo checkBo) {
        Long projectId = checkBo.getProjectId();
        String projectCode = checkBo.getProjectCode();

        //新增全新项目时,直接校验IPM编码是否重复和是否存在
        if (ObjectUtil.isNull(projectId)) {
            return this.treatProjectCodeExist(projectCode);
        } else {
            CbProjectRecord projectRecord = projectRecordMapper.selectById(projectId);
            ////未做任何改动时
            //Assert.isFalse(projectCode.equals(projectRecord.getIpmProjectNo()), "新编码与旧编码相同");
            //修改项目信息or新增新阶段项目时
            if (projectCode.equals(projectRecord.getIpmProjectNo())
                    && projectRecord.getIsGetProjectDetail()) {
                return projectRecord.getProjectName();
            } else {
                return this.treatProjectCodeExist(projectCode);
            }
        }
    }

    private String treatProjectCodeExist(String projectCode) {
        Assert.isFalse(projectRecordMapper.exists(new LambdaQueryWrapper<CbProjectRecord>()
                .eq(CbProjectRecord::getIpmProjectNo, projectCode)), "项目台账列表中已存在相同IPM编码的项目");
        DProject dProject = baseMapper.selectOne(new LambdaQueryWrapper<DProject>()
                .eq(DProject::getProjectCode, projectCode));
        if (ObjectUtil.isNotNull(dProject)) {
            return dProject.getProjectName();
        }
        throw new ServiceException("IPM项目编码无效");
    }

    /**
     * 获取工程项目信息
     *
     * @param projectId 项目ID
     * @return 工程项目信息
     */
    @Override
    public CbProjectInfoVo getCbProjectInfo(Long projectId) {
        CbProjectRecord projectRecord = projectRecordMapper.selectById(projectId);
        if (!projectRecord.getIsGetProjectDetail()) {
            return null;
        }
        return BeanUtil.toBean(baseMapper.selectOne(new LambdaQueryWrapper<DProject>()
                .eq(DProject::getProjectCode, projectRecord.getIpmProjectNo())), CbProjectInfoVo.class);
    }

    /**
     * 根据项目名称模糊查询项目列表
     *
     * @param projectName 项目名称
     * @return 项目列表
     */
    @Override
    public List<DProject> queryProjectNameList(String projectName) {
        return baseMapper.selectList(new LambdaQueryWrapper<DProject>()
                .select(DProject::getProjectName, DProject::getProjectCode)
                .like(StringUtils.isNotBlank(projectName), DProject::getProjectName, projectName)).stream().peek(item -> {
            item.setProjectName(StringUtils.markInRed(item.getProjectName(), projectName));
        }).collect(Collectors.toList());
    }
}

