package com.kcim.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kcim.common.exception.CostException;
import com.kcim.common.util.UserContext;
import com.kcim.dao.mapper.ReportFormMapper;
import com.kcim.dao.mapper.ReportRelationMapper;
import com.kcim.dao.model.ReportForm;
import com.kcim.dao.model.ReportRelation;
import com.kcim.dao.model.dto.ReportRelationDTO;
import com.kcim.service.ReportRelationService;
import com.kcim.vo.RelationVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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


@Slf4j
@Service("reportRelationService")
public class ReportRelationServiceImpl extends ServiceImpl<ReportRelationMapper, ReportRelation> implements ReportRelationService {

    private final ReportFormMapper reportFormMapper;

    public ReportRelationServiceImpl(ReportFormMapper reportFormMapper) {
        this.reportFormMapper = reportFormMapper;
    }

    /**
     * 报表项目关联的会计科目对象
     *
     * @param reportId 报表项目id
     * @param hospId   医院id
     * @return {@link RelationVO}
     */
    @Override
    public List<RelationVO> getAccountRelation(Long reportId, Long hospId) {
        List<RelationVO> accountRelation = baseMapper.getAccountRelation(reportId, hospId);

        if(!CollectionUtils.isEmpty(accountRelation)){
            accountRelation.forEach(relationVO -> relationVO.setId(relationVO.getCode()));
        }
        return accountRelation;
    }

    /**
     * 报表项目关联的分摊层级对象
     *
     * @param reportId 报表项目id
     * @param hospId   医院id
     * @return {@link RelationVO}
     */
    @Override
    public List<RelationVO> getShareLevel(Long reportId, Long hospId) {
        List<RelationVO> shareParam = baseMapper.getShareParam(reportId, hospId);
        if(!CollectionUtils.isEmpty(shareParam)){
            shareParam.forEach(relationVO -> relationVO.setId(relationVO.getCode()));

        }
        return shareParam;
    }

    /**
     * 根据关系类型，获取可绑定的关系数据（包含回显）
     *
     * @param reportId 报表项目id
     * @param relation 1.对应会计科目设置，2.对应分摊参数设置，根据列表中showAddRelation字段是否存在判断
     * @param hospId   医院id
     * @return 返回所有列表 并便是已选择的元素
     */
    @Override
    public List<RelationVO> getRelationList(Long reportId, Integer relation, Long hospId) {
        List<RelationVO> list = new ArrayList<>();
        if (relation == 1) {
            list = this.getAccountRelation(reportId, hospId);
        } else if (relation == 2) {
            list = this.getShareLevel(reportId, hospId);
        } else if (relation == 3) {
            list = getResponsibilities(reportId, hospId);
        }
        return list;
    }

    /**
     * 报表项目关联的分摊层级对象
     *
     * @param reportId 报表项目id
     * @param hospId   医院id
     * @return {@link RelationVO}
     */
    @Override
    public List<RelationVO> getResponsibilities(Long reportId, Long hospId) {
        List<RelationVO> responsibilities = baseMapper.getResponsibilities(reportId, hospId);
        if(!CollectionUtils.isEmpty(responsibilities)){
            responsibilities.forEach(relationVO -> relationVO.setId(relationVO.getCode()));
        }
        return responsibilities;
    }

    /**
     * 批量删除分摊层级的数据
     *
     * @param asList 分摊层级的Id集合
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void deleteByIds(List<Long> asList) {
        this.removeByIds(asList);
    }

    /**
     * @param asList
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void removeByReportIds(List<Long> asList) {
        LambdaQueryWrapper<ReportRelation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ReportRelation::getHospId, UserContext.getHospId());
        queryWrapper.in(ReportRelation::getReportId,asList);
        List<ReportRelation> list = this.list(queryWrapper);
        if(!CollectionUtils.isEmpty(list)){
            List<Long> collect = list.stream().map(ReportRelation::getId).collect(Collectors.toList());
            this.removeByIds(collect);
        }

    }

    /**
     * 编辑相关关系
     *
     * @param reportRelationDTO {@link ReportRelationDTO}
     * @param hospId
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    public void saveReportRelation(ReportRelationDTO reportRelationDTO, Long hospId) {

        Integer relation = reportRelationDTO.getRelation();
        List<String> relationCodes = reportRelationDTO.getRelationCodes();
        Long reportId = reportRelationDTO.getReportId();
        Integer reportType = reportRelationDTO.getReportType();

        // 校验这个report是否能绑定
        ReportForm byId = reportFormMapper.selectById(reportId);
        if (Objects.isNull(byId)) {
            throw new CostException("选择的报表项目不存在");
        }



        Integer calcType = byId.getCalcType();
        if (calcType != 1 && calcType != 2 && calcType != 5) {
            throw new CostException("选择的报表项目不能绑定关联关系");
        }

        List<ReportRelation> list = this.list(
                new LambdaQueryWrapper<ReportRelation>().eq(ReportRelation::getReportId, reportId).eq(ReportRelation::getHospId, hospId)
        );
        if (!list.isEmpty()) {
            baseMapper.deleteBatchIds(list.stream().map(ReportRelation::getId).collect(Collectors.toList()));
        }
        if(!CollectionUtils.isEmpty(relationCodes)){
            List<ReportRelation> reportRelations = relationCodes.stream().map(code -> {
                ReportRelation reportRelation = new ReportRelation();
                reportRelation.setRelation(relation);
                reportRelation.setReportId(reportId);
                reportRelation.setHospId(hospId);
                reportRelation.setRelationCode(code);
                reportRelation.setCreateTime(System.currentTimeMillis());
                return reportRelation;
            }).collect(Collectors.toList());
            // 校验 关联关系的id 是否已绑定过其他的报表项目
//            checkIfExist(hospId, relation, relationCodes,reportType);
            this.saveBatch(reportRelations);
        }

    }

    /**
     * 校验 关联关系的id 是否已绑定过其他的报表项目
     *
     * @param hospId        医院id
     * @param relation      关系
     * @param relationCodes 所有需要绑定的code 列表
     * @param reportType
     */
    private void checkIfExist(Long hospId, Integer relation, List<String> relationCodes, Integer reportType) {
        LambdaQueryWrapper<ReportForm> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ReportForm::getHospId,hospId);
        wrapper.eq(ReportForm::getReportType,reportType);
        List<ReportForm> reportForms = reportFormMapper.selectList(wrapper);
        if(!CollectionUtils.isEmpty(reportForms)){
            List<Long> collect = reportForms.stream().map(ReportForm::getId).collect(Collectors.toList());
            List<ReportRelation> relations = this.list(
                    new LambdaQueryWrapper<ReportRelation>().select(ReportRelation::getRelationCode)
                            .in(ReportRelation::getRelationCode, relationCodes)
                            .eq(ReportRelation::getRelation, relation)
                            .eq(ReportRelation::getHospId, hospId)
                            .in(ReportRelation::getReportId,collect)
            );
            if (CollUtil.isNotEmpty(relations)) {
                throw new CostException(500, "编码为:" +
                        StrUtil.join(StrUtil.COMMA, relations.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList())) +
                        "已被其他项目代码绑定");
            }
        }else {
            List<ReportRelation> relations = this.list(
                    new LambdaQueryWrapper<ReportRelation>().select(ReportRelation::getRelationCode)
                            .in(ReportRelation::getRelationCode, relationCodes)
                            .eq(ReportRelation::getRelation, relation)
                            .eq(ReportRelation::getHospId, hospId)
            );
            if (CollUtil.isNotEmpty(relations)) {
                throw new CostException(500, "编码为:" +
                        StrUtil.join(StrUtil.COMMA, relations.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList())) +
                        "已被其他项目代码绑定");
            }
        }



    }
}