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

import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.yhy.module.core.controller.admin.quota.vo.QuotaRateFieldRespVO;
import com.yhy.module.core.controller.admin.quota.vo.QuotaRateFieldSaveReqVO;
import com.yhy.module.core.dal.dataobject.quota.QuotaCatalogItemDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaRateFieldDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaRateItemDO;
import com.yhy.module.core.dal.mysql.quota.QuotaCatalogItemMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaRateFieldMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaRateItemMapper;
import com.yhy.module.core.service.quota.QuotaRateFieldService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yhy.module.core.enums.ErrorCodeConstants.*;

/**
 * 定额费率字段绑定 Service 实现
 */
@Service
@RequiredArgsConstructor
public class QuotaRateFieldServiceImpl implements QuotaRateFieldService {

    private final QuotaRateFieldMapper rateFieldMapper;
    private final QuotaRateItemMapper rateItemMapper;
    private final QuotaCatalogItemMapper catalogItemMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveRateField(QuotaRateFieldSaveReqVO saveReqVO) {
        // 1. 验证费率项存在
        QuotaRateItemDO rateItem = rateItemMapper.selectById(saveReqVO.getRateItemId());
        if (rateItem == null) {
            throw exception(QUOTA_RATE_ITEM_NOT_EXISTS);
        }
        
        // 2. 验证绑定范围
        if (saveReqVO.getBindingIds() != null && saveReqVO.getBindingIds().length > 0) {
            validateBindingRange(rateItem.getCatalogItemId(), saveReqVO.getBindingIds());
        }
        
        // 3. 查询是否已存在
        QuotaRateFieldDO existField = rateFieldMapper.selectByRateItemIdAndFieldIndex(
                saveReqVO.getRateItemId(), saveReqVO.getFieldIndex());
        
        if (existField != null) {
            // 更新
            QuotaRateFieldDO updateObj = BeanUtils.toBean(saveReqVO, QuotaRateFieldDO.class);
            updateObj.setId(existField.getId());
            rateFieldMapper.updateById(updateObj);
            return existField.getId();
        } else {
            // 新增
            QuotaRateFieldDO insertObj = BeanUtils.toBean(saveReqVO, QuotaRateFieldDO.class);
            rateFieldMapper.insert(insertObj);
            return insertObj.getId();
        }
    }

    @Override
    public void deleteRateField(Long id) {
        QuotaRateFieldDO field = rateFieldMapper.selectById(id);
        if (field == null) {
            throw exception(QUOTA_RATE_FIELD_NOT_EXISTS);
        }
        rateFieldMapper.deleteById(id);
    }

    @Override
    public void deleteByRateItemId(Long rateItemId) {
        rateFieldMapper.deleteByRateItemId(rateItemId);
    }

    @Override
    public QuotaRateFieldDO getRateField(Long id) {
        return rateFieldMapper.selectById(id);
    }

    @Override
    public List<QuotaRateFieldRespVO> getRateFieldList(Long rateItemId) {
        List<QuotaRateFieldDO> fields = rateFieldMapper.selectListByRateItemId(rateItemId);
        return fields.stream()
                .map(field -> BeanUtils.toBean(field, QuotaRateFieldRespVO.class))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBinding(Long rateItemId, Integer fieldIndex, Long[] bindingIds) {
        // 1. 验证费率项存在
        QuotaRateItemDO rateItem = rateItemMapper.selectById(rateItemId);
        if (rateItem == null) {
            throw exception(QUOTA_RATE_ITEM_NOT_EXISTS);
        }
        
        // 2. 验证绑定范围
        if (bindingIds != null && bindingIds.length > 0) {
            validateBindingRange(rateItem.getCatalogItemId(), bindingIds);
        }
        
        // 3. 查询或创建字段
        QuotaRateFieldDO field = rateFieldMapper.selectByRateItemIdAndFieldIndex(rateItemId, fieldIndex);
        if (field == null) {
            field = new QuotaRateFieldDO();
            field.setRateItemId(rateItemId);
            field.setFieldIndex(fieldIndex);
            field.setBindingIds(bindingIds);
            rateFieldMapper.insert(field);
        } else {
            field.setBindingIds(bindingIds);
            rateFieldMapper.updateById(field);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchSaveRateFields(Long rateItemId, List<QuotaRateFieldSaveReqVO> fields) {
        // 1. 验证费率项存在
        QuotaRateItemDO rateItem = rateItemMapper.selectById(rateItemId);
        if (rateItem == null) {
            throw exception(QUOTA_RATE_ITEM_NOT_EXISTS);
        }
        
        // 2. 删除原有字段
        rateFieldMapper.deleteByRateItemId(rateItemId);
        
        // 3. 批量插入新字段
        for (QuotaRateFieldSaveReqVO fieldVO : fields) {
            fieldVO.setRateItemId(rateItemId);
            
            // 验证绑定范围
            if (fieldVO.getBindingIds() != null && fieldVO.getBindingIds().length > 0) {
                validateBindingRange(rateItem.getCatalogItemId(), fieldVO.getBindingIds());
            }
            
            QuotaRateFieldDO field = BeanUtils.toBean(fieldVO, QuotaRateFieldDO.class);
            rateFieldMapper.insert(field);
        }
    }

    @Override
    public void validateBindingRange(Long catalogItemId, Long[] bindingIds) {
        if (bindingIds == null || bindingIds.length == 0) {
            return;
        }
        
        // 1. 获取模式节点所属的定额专业
        QuotaCatalogItemDO modeNode = catalogItemMapper.selectById(catalogItemId);
        if (modeNode == null) {
            throw exception(QUOTA_CATALOG_ITEM_NOT_EXISTS);
        }
        
        // 向上追溯到定额专业节点
        Long specialtyId = findSpecialtyId(modeNode);
        if (specialtyId == null) {
            throw exception(QUOTA_CATALOG_ITEM_SPECIALTY_NOT_FOUND);
        }
        
        // 2. 验证每个绑定节点是否属于同一定额专业
        for (Long bindingId : bindingIds) {
            QuotaCatalogItemDO bindingNode = catalogItemMapper.selectById(bindingId);
            if (bindingNode == null) {
                throw exception(QUOTA_CATALOG_ITEM_NOT_EXISTS);
            }
            
            Long bindingSpecialtyId = findSpecialtyId(bindingNode);
            if (!specialtyId.equals(bindingSpecialtyId)) {
                throw exception(QUOTA_RATE_FIELD_BINDING_OUT_OF_RANGE);
            }
        }
    }

    /**
     * 向上追溯找到定额专业节点ID
     */
    private Long findSpecialtyId(QuotaCatalogItemDO node) {
        QuotaCatalogItemDO current = node;
        while (current != null) {
            if ("specialty".equals(current.getNodeType())) {
                return current.getId();
            }
            if (current.getParentId() == null) {
                break;
            }
            current = catalogItemMapper.selectById(current.getParentId());
        }
        return null;
    }
}
