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.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.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.springframework.stereotype.Service;

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

/**
 * 咨询机构管理
 *
 * @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 projectCode 项目编码
     * @return 校验结果
     */
    @Override
    public Boolean checkProjectCodeExist(String projectCode) {
        Assert.isFalse(projectRecordMapper.exists(new LambdaQueryWrapper<CbProjectRecord>()
                .eq(CbProjectRecord::getIpmProjectNo, projectCode)), "项目台账列表中已存在相同IPM编码的项目");
        return baseMapper.exists(new LambdaQueryWrapper<DProject>()
                .eq(DProject::getProjectCode, projectCode));
    }

    /**
     * 获取工程项目信息
     *
     * @param projectId 项目ID
     * @return 工程项目信息
     */
    @Override
    public CbProjectInfoVo getCbProjectInfo(Long projectId) {
        CbProjectRecord projectRecord = projectRecordMapper.selectById(projectId);
        Assert.isTrue(projectRecord.getIsGetProjectDetail(), "请先通过IPM项目编码获取数据,或IPM项目编码无效");
        return BeanUtil.toBean(baseMapper.selectOne(new LambdaQueryWrapper<DProject>()
                .eq(DProject::getProjectCode, projectRecord.getIpmProjectNo())), CbProjectInfoVo.class);
    }
}

