package com.yhy.module.core.service.quota.impl;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_ADJUSTMENT_DETAIL_CODE_NOT_EXISTS;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_ADJUSTMENT_DETAIL_CODE_NOT_SAME_SPECIALTY;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_ADJUSTMENT_DETAIL_NOT_EXISTS;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_ADJUSTMENT_DETAIL_NOT_SAME_SETTING;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_ADJUSTMENT_DETAIL_SETTING_NOT_EXISTS;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_ADJUSTMENT_SETTING_NOT_EXISTS;
import static com.yhy.module.core.enums.ErrorCodeConstants.QUOTA_ADJUSTMENT_SETTING_QUOTA_ITEM_NOT_EXISTS;

import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.yhy.module.core.controller.admin.quota.vo.QuotaAdjustmentCombinedRespVO;
import com.yhy.module.core.controller.admin.quota.vo.QuotaAdjustmentDetailSaveReqVO;
import com.yhy.module.core.dal.dataobject.quota.QuotaAdjustmentDetailDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaAdjustmentSettingDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaCatalogTreeDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaItemDO;
import com.yhy.module.core.dal.mysql.quota.QuotaAdjustmentDetailMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaAdjustmentSettingMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaCatalogItemMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaCatalogTreeMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaItemMapper;
import com.yhy.module.core.service.quota.QuotaAdjustmentDetailService;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

/**
 * 定额调整明细 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
@Slf4j
public class QuotaAdjustmentDetailServiceImpl implements QuotaAdjustmentDetailService {

    @Resource
    private QuotaAdjustmentDetailMapper quotaAdjustmentDetailMapper;

    @Resource
    private QuotaAdjustmentSettingMapper quotaAdjustmentSettingMapper;

    @Resource
    private QuotaItemMapper quotaItemMapper;

    @Resource
    private QuotaCatalogTreeMapper quotaCatalogTreeMapper;

    @Resource
    private QuotaCatalogItemMapper quotaCatalogItemMapper;

    @Override
    public Long createQuotaAdjustmentDetail(QuotaAdjustmentDetailSaveReqVO createReqVO) {
        // 验证调整设置是否存在
        validateAdjustmentSettingExists(createReqVO.getAdjustmentSettingId());

        // 如果有引用编号，验证引用的调整设置
        if (createReqVO.getAdjustmentCode() != null) {
            validateAdjustmentCodeInSameSpecialty(createReqVO.getAdjustmentSettingId(), createReqVO.getAdjustmentCode());
        }

        // 插入
        QuotaAdjustmentDetailDO detail = BeanUtils.toBean(createReqVO, QuotaAdjustmentDetailDO.class);
        if (detail.getSortOrder() == null) {
            detail.setSortOrder(0);
        }
        quotaAdjustmentDetailMapper.insert(detail);
        return detail.getId();
    }

    @Override
    public void updateQuotaAdjustmentDetail(QuotaAdjustmentDetailSaveReqVO updateReqVO) {
        // 校验存在
        validateQuotaAdjustmentDetailExists(updateReqVO.getId());
        // 验证调整设置是否存在
        validateAdjustmentSettingExists(updateReqVO.getAdjustmentSettingId());

        // 如果有引用编号，验证引用的调整设置
        if (updateReqVO.getAdjustmentCode() != null) {
            validateAdjustmentCodeInSameSpecialty(updateReqVO.getAdjustmentSettingId(), updateReqVO.getAdjustmentCode());
        }

        // 更新
        QuotaAdjustmentDetailDO updateObj = BeanUtils.toBean(updateReqVO, QuotaAdjustmentDetailDO.class);
        quotaAdjustmentDetailMapper.updateById(updateObj);
    }

    @Override
    public void deleteQuotaAdjustmentDetail(Long id) {
        // 校验存在
        validateQuotaAdjustmentDetailExists(id);
        // 删除
        quotaAdjustmentDetailMapper.deleteById(id);
    }

    @Override
    public QuotaAdjustmentDetailDO getQuotaAdjustmentDetail(Long id) {
        return quotaAdjustmentDetailMapper.selectById(id);
    }

    @Override
    public List<QuotaAdjustmentDetailDO> getQuotaAdjustmentDetailListByQuotaItem(Long quotaItemId) {
        // 1. 查询该定额基价下的所有调整设置
        List<QuotaAdjustmentSettingDO> settings = quotaAdjustmentSettingMapper.selectListByQuotaItemId(quotaItemId);
        
        if (settings.isEmpty()) {
            return Collections.emptyList();
        }
        
        // 2. 查询这些调整设置下的所有明细
        List<Long> settingIds = settings.stream()
                .map(QuotaAdjustmentSettingDO::getId)
                .collect(java.util.stream.Collectors.toList());
        
        return quotaAdjustmentDetailMapper.selectListBySettingIds(settingIds);
    }

    @Override
    public List<QuotaAdjustmentDetailDO> getQuotaAdjustmentDetailList(Long adjustmentSettingId) {
        return quotaAdjustmentDetailMapper.selectListBySettingId(adjustmentSettingId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void swapSort(Long id1, Long id2) {
        // 验证两个调整明细是否存在
        QuotaAdjustmentDetailDO detail1 = quotaAdjustmentDetailMapper.selectByIdForUpdate(id1);
        QuotaAdjustmentDetailDO detail2 = quotaAdjustmentDetailMapper.selectByIdForUpdate(id2);

        if (detail1 == null) {
            throw exception(QUOTA_ADJUSTMENT_DETAIL_NOT_EXISTS);
        }
        if (detail2 == null) {
            throw exception(QUOTA_ADJUSTMENT_DETAIL_NOT_EXISTS);
        }

        // 验证是否在同一调整设置下
        if (!detail1.getAdjustmentSettingId().equals(detail2.getAdjustmentSettingId())) {
            throw exception(QUOTA_ADJUSTMENT_DETAIL_NOT_SAME_SETTING);
        }

        // 交换排序值
        Integer tempSort = detail1.getSortOrder();
        detail1.setSortOrder(detail2.getSortOrder());
        detail2.setSortOrder(tempSort);

        quotaAdjustmentDetailMapper.updateById(detail1);
        quotaAdjustmentDetailMapper.updateById(detail2);
    }

    @Override
    public List<QuotaAdjustmentSettingDO> getAvailableSettings(Long adjustmentSettingId) {
        // 获取当前调整设置
        QuotaAdjustmentSettingDO currentSetting = quotaAdjustmentSettingMapper.selectById(adjustmentSettingId);
        if (currentSetting == null) {
            throw exception(QUOTA_ADJUSTMENT_SETTING_NOT_EXISTS);
        }

        // 获取定额专业ID
        Long specialtyId = getSpecialtyIdByQuotaItem(currentSetting.getQuotaItemId());

        // 查询同一定额专业下的所有定额基价
        List<QuotaCatalogTreeDO> catalogTrees = quotaCatalogTreeMapper.selectListByCatalogItemId(specialtyId);

        // 查询这些定额基价下的所有调整设置
        // 这里简化处理，返回所有调整设置，前端可以根据需要过滤
        // 实际应该根据 catalogTrees 中的 ID 查询对应的 quotaItem，再查询调整设置
        return quotaAdjustmentSettingMapper.selectList();
    }

    @Override
    public List<QuotaAdjustmentCombinedRespVO> getCombinedList(Long quotaItemId) {
        // 1. 查询该定额基价下的所有调整设置（第五层）
        List<QuotaAdjustmentSettingDO> settings = quotaAdjustmentSettingMapper.selectListByQuotaItemId(quotaItemId);
        
        if (settings.isEmpty()) {
            return Collections.emptyList();
        }
        
        // 2. 查询所有调整设置的明细（第六层）
        List<Long> settingIds = settings.stream()
                .map(QuotaAdjustmentSettingDO::getId)
                .collect(java.util.stream.Collectors.toList());
        
        List<QuotaAdjustmentDetailDO> allDetails = quotaAdjustmentDetailMapper.selectListBySettingIds(settingIds);
        
        // 3. 按 adjustmentSettingId 分组
        Map<Long, List<QuotaAdjustmentDetailDO>> detailsMap = allDetails.stream()
                .collect(java.util.stream.Collectors.groupingBy(QuotaAdjustmentDetailDO::getAdjustmentSettingId));
        
        // 4. 组装结果
        return settings.stream()
                .map(setting -> {
                    QuotaAdjustmentCombinedRespVO vo = new QuotaAdjustmentCombinedRespVO();
                    vo.setId(setting.getId());
                    vo.setQuotaItemId(setting.getQuotaItemId());
                    vo.setName(setting.getName());
                    vo.setQuotaValue(setting.getQuotaValue());
                    vo.setAdjustmentContent(setting.getAdjustmentContent());
                    vo.setAdjustmentType(setting.getAdjustmentType());
                    vo.setAdjustmentRules(setting.getAdjustmentRules());
                    vo.setSortOrder(setting.getSortOrder());
                    vo.setCreateTime(setting.getCreateTime());
                    
                    // 获取该调整设置的明细列表
                    List<QuotaAdjustmentDetailDO> details = detailsMap.getOrDefault(setting.getId(), Collections.emptyList());
                    List<QuotaAdjustmentCombinedRespVO.DetailItem> detailItems = details.stream()
                            .map(detail -> {
                                QuotaAdjustmentCombinedRespVO.DetailItem item = new QuotaAdjustmentCombinedRespVO.DetailItem();
                                item.setId(detail.getId());
                                item.setAdjustmentSettingId(detail.getAdjustmentSettingId());
                                item.setAdjustmentCode(detail.getAdjustmentCode());
                                item.setAdjustment(detail.getAdjustment());
                                item.setSortOrder(detail.getSortOrder());
                                item.setCreateTime(detail.getCreateTime());
                                return item;
                            })
                            .collect(java.util.stream.Collectors.toList());
                    
                    vo.setDetails(detailItems);
                    return vo;
                })
                .collect(java.util.stream.Collectors.toList());
    }

    private void validateQuotaAdjustmentDetailExists(Long id) {
        if (quotaAdjustmentDetailMapper.selectById(id) == null) {
            throw exception(QUOTA_ADJUSTMENT_DETAIL_NOT_EXISTS);
        }
    }

    private void validateAdjustmentSettingExists(Long adjustmentSettingId) {
        if (quotaAdjustmentSettingMapper.selectById(adjustmentSettingId) == null) {
            throw exception(QUOTA_ADJUSTMENT_DETAIL_SETTING_NOT_EXISTS);
        }
    }

    /**
     * 验证 adjustment_code 是否在同一定额专业
     */
    private void validateAdjustmentCodeInSameSpecialty(Long adjustmentSettingId, Long adjustmentCode) {
        // 1. 查询当前调整设置
        QuotaAdjustmentSettingDO currentSetting = quotaAdjustmentSettingMapper.selectById(adjustmentSettingId);
        if (currentSetting == null) {
            throw exception(QUOTA_ADJUSTMENT_SETTING_NOT_EXISTS);
        }

        // 2. 查询引用的调整设置
        QuotaAdjustmentSettingDO referenceSetting = quotaAdjustmentSettingMapper.selectById(adjustmentCode);
        if (referenceSetting == null) {
            throw exception(QUOTA_ADJUSTMENT_DETAIL_CODE_NOT_EXISTS);
        }

        // 3. 获取两者的定额专业ID
        Long currentSpecialtyId = getSpecialtyIdByQuotaItem(currentSetting.getQuotaItemId());
        Long referenceSpecialtyId = getSpecialtyIdByQuotaItem(referenceSetting.getQuotaItemId());

        // 4. 验证是否在同一定额专业
        if (!currentSpecialtyId.equals(referenceSpecialtyId)) {
            throw exception(QUOTA_ADJUSTMENT_DETAIL_CODE_NOT_SAME_SPECIALTY);
        }
    }

    /**
     * 通过定额基价追溯到定额专业
     */
    private Long getSpecialtyIdByQuotaItem(Long quotaItemId) {
        // 1. 查询定额基价（第三层）
        QuotaItemDO quotaItem = quotaItemMapper.selectById(quotaItemId);
        if (quotaItem == null) {
            throw exception(QUOTA_ADJUSTMENT_SETTING_QUOTA_ITEM_NOT_EXISTS);
        }

        // 2. 查询定额基价树节点（第二层）
        QuotaCatalogTreeDO catalogTree = quotaCatalogTreeMapper.selectById(quotaItem.getCatalogItemId());
        if (catalogTree == null) {
            throw exception(QUOTA_ADJUSTMENT_SETTING_QUOTA_ITEM_NOT_EXISTS);
        }

        // 3. 返回定额专业节点ID（第一层）
        return catalogTree.getCatalogItemId();
    }

}
