package com.microservices.zone.specialProject.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.PageUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.zone.common.service.IZoneSortService;
import com.microservices.zone.project.domain.vo.ZoneProjectDataVo;
import com.microservices.zone.project.domain.vo.ZoneProjectSearchVo;
import com.microservices.zone.project.service.IZoneProjectService;
import com.microservices.zone.resource.domain.ZoneResource;
import com.microservices.zone.resource.domain.vo.ZoneResourceDataVo;
import com.microservices.zone.resource.service.IZoneResourceService;
import com.microservices.zone.specialProject.domain.ZoneSpecialProject;
import com.microservices.zone.specialProject.domain.ZoneSpecialProjectRelevancy;
import com.microservices.zone.specialProject.domain.ZoneSpecialProjectRelevancyTypeEnum;
import com.microservices.zone.specialProject.domain.vo.CommonTypeVo;
import com.microservices.zone.specialProject.domain.vo.ZoneSpecialProjectRelevancyInputVo;
import com.microservices.zone.specialProject.domain.vo.ZoneSpecialProjectRelevancyUpdateVo;
import com.microservices.zone.specialProject.mapper.ZoneSpecialProjectRelevancyMapper;
import com.microservices.zone.specialProject.service.IZoneSpecialProjectRelevancyService;
import com.microservices.zone.specialProject.service.IZoneSpecialProjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 特色专区专项项目关联关系Service业务层处理
 *
 * @author otto
 * @date 2024-10-26
 */
@Service
public class ZoneSpecialProjectRelevancyServiceImpl implements IZoneSpecialProjectRelevancyService {
    @Autowired
    private ZoneSpecialProjectRelevancyMapper zoneSpecialProjectRelevancyMapper;
    @Autowired
    private IZoneSortService zoneSortService;
    @Autowired
    private IZoneProjectService zoneProjectService;
    @Autowired
    private IZoneResourceService zoneResourceService;
    @Autowired
    @Lazy
    private IZoneSpecialProjectService zoneSpecialProjectService;

    /**
     * 查询特色专区专项项目关联关系
     *
     * @param id 特色专区专项项目关联关系主键
     * @return 特色专区专项项目关联关系
     */
    @Override
    public ZoneSpecialProjectRelevancy selectZoneSpecialProjectRelevancyById(Long id) {
        ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancy = zoneSpecialProjectRelevancyMapper.selectZoneSpecialProjectRelevancyById(id);
        if (zoneSpecialProjectRelevancy == null) {
            throw new ServiceException("该专项项目关联关系不存在或无权限访问(专项项目关联关系id[" + id + "])");
        }
        return setZoneSpecialProjectRelevancyDetail(zoneSpecialProjectRelevancy);
    }

    private ZoneSpecialProjectRelevancy setZoneSpecialProjectRelevancyDetail(ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancy) {
        if (ZoneSpecialProjectRelevancyTypeEnum.isProject(zoneSpecialProjectRelevancy.getType())) {
            ZoneProjectDataVo zoneProjectDataVo = zoneProjectService.selectZoneProjectDataById(zoneSpecialProjectRelevancy.getRelevancyId());
            zoneSpecialProjectRelevancy.setRelevancyObject(JSONObject.from(zoneProjectDataVo));
        } else {
            ZoneResourceDataVo zoneResourceDataVo = zoneResourceService.selectZoneResourceDataById(zoneSpecialProjectRelevancy.getRelevancyId());
            zoneSpecialProjectRelevancy.setRelevancyObject(JSONObject.from(zoneResourceDataVo));
        }
        return zoneSpecialProjectRelevancy;
    }

    /**
     * 查询特色专区专项项目关联关系列表
     *
     * @param zoneSpecialProjectRelevancy 特色专区专项项目关联关系
     * @return 特色专区专项项目关联关系
     */
    @Override
    public List<ZoneSpecialProjectRelevancy> selectZoneSpecialProjectRelevancyList(ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancy) {
        List<ZoneSpecialProjectRelevancy> zoneSpecialProjectRelevancyList =
                zoneSpecialProjectRelevancyMapper.selectZoneSpecialProjectRelevancyList(zoneSpecialProjectRelevancy);
        zoneSpecialProjectRelevancyList.forEach(this::setZoneSpecialProjectRelevancyDetail);
        return zoneSpecialProjectRelevancyList;
    }

    /**
     * 新增特色专区专项项目关联关系
     *
     * @param zoneSpecialProjectRelevancyInputVo 特色专区专项项目关联关系
     * @return 结果
     */
    @Override
    public int insertZoneSpecialProjectRelevancy(ZoneSpecialProjectRelevancyInputVo zoneSpecialProjectRelevancyInputVo) {
        ZoneSpecialProject zoneSpecialProject = zoneSpecialProjectService.selectZoneSpecialProjectById(zoneSpecialProjectRelevancyInputVo.getSpecialProjectId());
        checkParameters(zoneSpecialProject.getZoneId()
                , zoneSpecialProjectRelevancyInputVo.getType()
                , zoneSpecialProjectRelevancyInputVo.getRelevancyId()
                , zoneSpecialProjectRelevancyInputVo.getAuthor());
        checkRelevancyAlreadyExists(
                zoneSpecialProject.getZoneId()
                , zoneSpecialProjectRelevancyInputVo.getSpecialProjectId()
                , zoneSpecialProjectRelevancyInputVo.getType()
                , zoneSpecialProjectRelevancyInputVo.getRelevancyId()
        );
        ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancy = zoneSpecialProjectRelevancyInputVo.toZoneSpecialProjectRelevancySearchVo();
        zoneSpecialProjectRelevancy.setCreateTime(DateUtils.getNowDate());
        zoneSpecialProjectRelevancy.setCreateBy(SecurityUtils.getUsername());
        zoneSpecialProjectRelevancy.setDeptId(zoneSpecialProject.getDeptId());
        zoneSpecialProjectRelevancy.setZoneId(zoneSpecialProject.getZoneId());
        Integer maxSort = zoneSortService.getMaxSort(zoneSpecialProject.getZoneId(), ZoneSpecialProjectRelevancy.table_name);
        zoneSpecialProjectRelevancy.setSort(maxSort);
        return zoneSpecialProjectRelevancyMapper.insertZoneSpecialProjectRelevancy(zoneSpecialProjectRelevancy);
    }

    private void checkParameters(Long zoneId, String type, Long relevancyId, String author) {
        try {
            if (ZoneSpecialProjectRelevancyTypeEnum.isProject(type)) {
                ZoneProjectDataVo zoneProjectDataVo = zoneProjectService.selectZoneProjectDataById(relevancyId);
                if (!Objects.equals(zoneId, zoneProjectDataVo.getZoneId())) {
                    throw new ServiceException("该开源项目不存在或无权限访问(开源项目id[%d])", relevancyId);
                }
            } else {
                ZoneResourceDataVo zoneResourceDataVo = zoneResourceService.selectZoneResourceDataById(relevancyId);
                if (!Objects.equals(zoneId, zoneResourceDataVo.getZoneId())) {
                    throw new ServiceException("该资源不存在或无权限访问(资源id[%d])", relevancyId);
                }
                if (StringUtils.isEmpty(author)) {
                    throw new ServiceException("%s作者不能为空", ZoneSpecialProjectRelevancyTypeEnum.getNameByKey(type));
                }
            }

        } catch (ServiceException e) {
            throw new ServiceException("检查专项项目关联对象时出错：%s", e.getMessage());
        }
    }

    private void checkRelevancyAlreadyExists(Long zoneId, Long specialProjectId, String type, Long relevancyId) {
        ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancySearch = new ZoneSpecialProjectRelevancy();
        zoneSpecialProjectRelevancySearch.setZoneId(zoneId);
        zoneSpecialProjectRelevancySearch.setRelevancyId(relevancyId);
        zoneSpecialProjectRelevancySearch.setSpecialProjectId(specialProjectId);
        zoneSpecialProjectRelevancySearch.setType(type);
        List<ZoneSpecialProjectRelevancy> zoneSpecialProjectRelevancyList = zoneSpecialProjectRelevancyMapper.selectZoneSpecialProjectRelevancyList(zoneSpecialProjectRelevancySearch);
        if (zoneSpecialProjectRelevancyList != null && !zoneSpecialProjectRelevancyList.isEmpty()) {
            throw new ServiceException("该专项项目已关联相同的%s类型对象(关联对象id[%d])", ZoneSpecialProjectRelevancyTypeEnum.getNameByKey(type), relevancyId);
        }
    }

    /**
     * 修改特色专区专项项目关联关系
     *
     * @param zoneSpecialProjectRelevancyUpdateVo 特色专区专项项目关联关系
     * @return 结果
     */
    @Override
    public int updateZoneSpecialProjectRelevancy(ZoneSpecialProjectRelevancyUpdateVo zoneSpecialProjectRelevancyUpdateVo) {
        ZoneSpecialProjectRelevancy oldZoneSpecialProjectRelevancy = selectZoneSpecialProjectRelevancyById(zoneSpecialProjectRelevancyUpdateVo.getId());
        checkParameters(oldZoneSpecialProjectRelevancy.getZoneId(), oldZoneSpecialProjectRelevancy.getType(), zoneSpecialProjectRelevancyUpdateVo.getRelevancyId(), zoneSpecialProjectRelevancyUpdateVo.getAuthor());
        if (!oldZoneSpecialProjectRelevancy.getRelevancyId().equals(zoneSpecialProjectRelevancyUpdateVo.getRelevancyId())) {
            checkRelevancyAlreadyExists(
                    oldZoneSpecialProjectRelevancy.getZoneId()
                    , oldZoneSpecialProjectRelevancy.getSpecialProjectId()
                    , oldZoneSpecialProjectRelevancy.getType()
                    , zoneSpecialProjectRelevancyUpdateVo.getRelevancyId()
            );
        }
        ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancy = zoneSpecialProjectRelevancyUpdateVo.toZoneSpecialProjectRelevancySearchVo();
        zoneSpecialProjectRelevancy.setUpdateTime(DateUtils.getNowDate());
        zoneSpecialProjectRelevancy.setUpdateBy(SecurityUtils.getUsername());
        if (zoneSpecialProjectRelevancyUpdateVo.getOrder() != null) {
            Integer setSort =
                    zoneSortService.setSortByOrder(oldZoneSpecialProjectRelevancy, zoneSpecialProjectRelevancyUpdateVo.getOrder(), ZoneSpecialProjectRelevancy.table_name);
            zoneSpecialProjectRelevancy.setSort(setSort);
        }
        return zoneSpecialProjectRelevancyMapper.updateZoneSpecialProjectRelevancy(zoneSpecialProjectRelevancy);
    }

    /**
     * 批量删除特色专区专项项目关联关系
     *
     * @param ids 需要删除的特色专区专项项目关联关系主键
     * @return 结果
     */
    @Override
    public int deleteZoneSpecialProjectRelevancyByIds(Long[] ids) {
        return zoneSpecialProjectRelevancyMapper.deleteZoneSpecialProjectRelevancyByIds(ids);
    }

    /**
     * 删除特色专区专项项目关联关系信息
     *
     * @param id 特色专区专项项目关联关系主键
     * @return 结果
     */
    @Override
    public int deleteZoneSpecialProjectRelevancyById(Long id) {
        return zoneSpecialProjectRelevancyMapper.deleteZoneSpecialProjectRelevancyById(id);
    }

    @Override
    public void deleteZoneSpecialProjectRelevancyBySpecialProjectId(Long specialProjectId) {
        ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancy = new ZoneSpecialProjectRelevancy();
        zoneSpecialProjectRelevancy.setSpecialProjectId(specialProjectId);
        List<ZoneSpecialProjectRelevancy> zoneSpecialProjectRelevancyList =
                zoneSpecialProjectRelevancyMapper.selectZoneSpecialProjectRelevancyList(zoneSpecialProjectRelevancy);
        for (ZoneSpecialProjectRelevancy relevancy : zoneSpecialProjectRelevancyList) {
            deleteZoneSpecialProjectRelevancyById(relevancy.getId());
        }
    }

    @Override
    public List<CommonTypeVo> selectZoneSpecialProjectRelevancyTypeList() {
        return ZoneSpecialProjectRelevancyTypeEnum.getAllToList();
    }

    @Override
    public void deleteZoneSpecialProjectRelevancyByProjectId(Long projectId) {
        ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancySearch = new ZoneSpecialProjectRelevancy();
        zoneSpecialProjectRelevancySearch.setType(ZoneSpecialProjectRelevancyTypeEnum.PROJECT.getKey());
        zoneSpecialProjectRelevancySearch.setRelevancyId(projectId);
        List<ZoneSpecialProjectRelevancy> zoneSpecialProjectRelevancyList = zoneSpecialProjectRelevancyMapper.selectZoneSpecialProjectRelevancyList(zoneSpecialProjectRelevancySearch);
        for (ZoneSpecialProjectRelevancy relevancy : zoneSpecialProjectRelevancyList) {
            deleteZoneSpecialProjectRelevancyById(relevancy.getId());
        }
    }

    @Override
    public void deleteZoneSpecialProjectRelevancyByResourceId(Long resourceId) {
        ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancySearch = new ZoneSpecialProjectRelevancy();
        zoneSpecialProjectRelevancySearch.setType(ZoneSpecialProjectRelevancyTypeEnum.PAPER.getKey());
        zoneSpecialProjectRelevancySearch.setRelevancyId(resourceId);
        List<ZoneSpecialProjectRelevancy> zoneSpecialProjectRelevancyList = zoneSpecialProjectRelevancyMapper.selectZoneSpecialProjectRelevancyList(zoneSpecialProjectRelevancySearch);
        zoneSpecialProjectRelevancySearch.setType(ZoneSpecialProjectRelevancyTypeEnum.PATENT.getKey());
        zoneSpecialProjectRelevancyList.addAll(zoneSpecialProjectRelevancyMapper.selectZoneSpecialProjectRelevancyList(zoneSpecialProjectRelevancySearch));
        for (ZoneSpecialProjectRelevancy relevancy : zoneSpecialProjectRelevancyList) {
            deleteZoneSpecialProjectRelevancyById(relevancy.getId());
        }
    }

    @Override
    public GenericsTableDataInfo<JSONObject> selectZoneResourceList(Long specialProjectId, ZoneResource zoneResource) {
        List<JSONObject> zoneResourceJSONList = new ArrayList<>();
        PageUtils.startPage();
        GenericsTableDataInfo<ZoneResourceDataVo> zoneResourceDataVoGenericsTableDataInfo =
                zoneResourceService.selectZoneResourceList(zoneResource);
        List<ZoneResourceDataVo> zoneResourceDataVoList = zoneResourceDataVoGenericsTableDataInfo.getRows();
        ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancySearch = new ZoneSpecialProjectRelevancy();
        zoneSpecialProjectRelevancySearch.setSpecialProjectId(specialProjectId);
        List<ZoneSpecialProjectRelevancy> zoneSpecialProjectRelevancyList = zoneSpecialProjectRelevancyMapper.selectZoneSpecialProjectRelevancyList(zoneSpecialProjectRelevancySearch);
        for (ZoneResourceDataVo zoneResourceDataVo : zoneResourceDataVoList) {
            ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancy = zoneSpecialProjectRelevancyList.stream().filter(x -> !ZoneSpecialProjectRelevancyTypeEnum.isProject(x.getType())
                    && x.getRelevancyId().equals(zoneResourceDataVo.getId())).findFirst().orElse(null);
            JSONObject zoneResourceJSON = JSONObject.from(zoneResourceDataVo);
            boolean isChoose = false;
            if (zoneSpecialProjectRelevancy != null) {
                isChoose = true;
                zoneResourceJSON.put("relevancyAuthor", zoneSpecialProjectRelevancy.getAuthor());
                zoneResourceJSON.put("relevancyCompany", zoneSpecialProjectRelevancy.getCompany());
            }
            zoneResourceJSON.put("isChoose", isChoose);
            zoneResourceJSONList.add(zoneResourceJSON);
        }
        return new GenericsTableDataInfo<>(zoneResourceJSONList, zoneResourceDataVoGenericsTableDataInfo.getTotal());
    }

    @Override
    public GenericsTableDataInfo<JSONObject> selectZoneProjectList(Long specialProjectId, ZoneProjectSearchVo zoneProjectSearchVo, boolean isOpen) {
        List<JSONObject> zoneProjectJSONList = new ArrayList<>();
        PageUtils.startPage();
        GenericsTableDataInfo<ZoneProjectDataVo> zoneProjectDataVoGenericsTableDataInfo =
                zoneProjectService.selectZoneProjectList(zoneProjectSearchVo, isOpen);
        List<ZoneProjectDataVo> zoneProjectDataVoList = zoneProjectDataVoGenericsTableDataInfo.getRows();
        ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancySearch = new ZoneSpecialProjectRelevancy();
        zoneSpecialProjectRelevancySearch.setSpecialProjectId(specialProjectId);
        zoneSpecialProjectRelevancySearch.setType(ZoneSpecialProjectRelevancyTypeEnum.PROJECT.getKey());
        List<ZoneSpecialProjectRelevancy> zoneSpecialProjectRelevancyList = zoneSpecialProjectRelevancyMapper.selectZoneSpecialProjectRelevancyList(zoneSpecialProjectRelevancySearch);
        for (ZoneProjectDataVo zoneProjectDataVo : zoneProjectDataVoList) {
            ZoneSpecialProjectRelevancy zoneSpecialProjectRelevancy = zoneSpecialProjectRelevancyList.stream().filter(x -> x.getRelevancyId().equals(zoneProjectDataVo.getId())).findFirst().orElse(null);
            JSONObject zoneProjectJSON = JSONObject.from(zoneProjectDataVo);
            boolean isChoose = false;
            if (zoneSpecialProjectRelevancy != null) {
                isChoose = true;
                zoneProjectJSON.put("relevancyAuthor", zoneSpecialProjectRelevancy.getAuthor());
            }
            zoneProjectJSON.put("isChoose", isChoose);
            zoneProjectJSONList.add(zoneProjectJSON);
        }
        return new GenericsTableDataInfo<>(zoneProjectJSONList, zoneProjectDataVoGenericsTableDataInfo.getTotal());
    }
}
