package com.zt.plat.module.base.service.quantityUnitRelation;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import com.zt.plat.module.base.controller.admin.quantityUnitRelation.vo.*;
import com.zt.plat.module.base.dal.dataobject.quantityUnitRelation.QuantityUnitRelationDO;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;

import com.zt.plat.module.base.dal.dao.quantityUnitRelation.QuantityUnitRelationMapper;
import com.zt.plat.module.base.dal.dao.unitQuantity.UnitQuantityMapper;
import com.zt.plat.module.base.dal.dao.untInfo.UntInfoMapper;
import com.zt.plat.module.base.service.untInfo.UntInfoService;
import com.zt.plat.module.base.controller.admin.untInfo.vo.UntInfoSaveReqVO;
import com.zt.plat.module.base.controller.admin.untInfo.vo.UntInfoRespVO;
import com.zt.plat.module.base.dal.dataobject.unitQuantity.UnitQuantityDO;
import com.zt.plat.module.base.dal.dataobject.untInfo.UntInfoDO;

import java.util.function.Function;
import java.util.stream.Collectors;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
import static com.zt.plat.module.unitmanagement.enums.UnitErrorCodeConstants.*;

/**
 * 计量单位量与单位关联 Service 实现类
 *
 * @author 后台管理-1
 */
@Service
@Validated
public class QuantityUnitRelationServiceImpl implements QuantityUnitRelationService {

    @Resource
    private QuantityUnitRelationMapper quantityUnitRelationMapper;

    @Resource
    private UntInfoService untInfoService;

    @Resource
    private UnitQuantityMapper unitQuantityMapper;

    @Resource
    private UntInfoMapper untInfoMapper;

    @Override
    public QuantityUnitRelationRespVO createQuantityUnitRelation(QuantityUnitRelationSaveReqVO createReqVO) {
        // 插入
        QuantityUnitRelationDO quantityUnitRelation = BeanUtils.toBean(createReqVO, QuantityUnitRelationDO.class);
        quantityUnitRelationMapper.insert(quantityUnitRelation);
        // 返回
        return BeanUtils.toBean(quantityUnitRelation, QuantityUnitRelationRespVO.class);
    }

    @Override
    public void updateQuantityUnitRelation(QuantityUnitRelationSaveReqVO updateReqVO) {
        // 校验存在
        validateQuantityUnitRelationExists(updateReqVO.getId());
        // 更新
        QuantityUnitRelationDO updateObj = BeanUtils.toBean(updateReqVO, QuantityUnitRelationDO.class);
        quantityUnitRelationMapper.updateById(updateObj);
    }

    @Override
    public void deleteQuantityUnitRelation(Long id) {
        // 校验存在
        validateQuantityUnitRelationExists(id);
        // 删除
        quantityUnitRelationMapper.deleteById(id);
    }

    @Override
        public void deleteQuantityUnitRelationListByIds(List<Long> ids) {
        // 校验存在
        validateQuantityUnitRelationExists(ids);
        // 删除
        quantityUnitRelationMapper.deleteByIds(ids);
        }

    private void validateQuantityUnitRelationExists(List<Long> ids) {
        List<QuantityUnitRelationDO> list = quantityUnitRelationMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(QUANTITY_UNIT_RELATION_NOT_EXISTS);
        }
    }

    private void validateQuantityUnitRelationExists(Long id) {
        if (quantityUnitRelationMapper.selectById(id) == null) {
            throw exception(QUANTITY_UNIT_RELATION_NOT_EXISTS);
        }
    }

    @Override
    public QuantityUnitRelationDO getQuantityUnitRelation(Long id) {
        return quantityUnitRelationMapper.selectById(id);
    }

    @Override
    public PageResult<QuantityUnitRelationDO> getQuantityUnitRelationPage(QuantityUnitRelationPageReqVO pageReqVO) {
        return quantityUnitRelationMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchSaveQuantityUnitRelations(QuantityUnitRelationBatchSaveReqVO batchSaveReqVO) {
        Long untQtyId = batchSaveReqVO.getUntQtyId();
        List<QuantityUnitRelationBatchSaveReqVO.UnitRelationItemVO> requestItems = batchSaveReqVO.getUnitRelations();

        // 1. 查询数据库中该量纲下的所有现有关联关系
        List<QuantityUnitRelationDO> existingRelations = quantityUnitRelationMapper.selectListByUntQtyId(untQtyId);

        // 2. 提取请求中的ID列表(排除null)
        List<Long> requestIds = requestItems.stream()
                .map(QuantityUnitRelationBatchSaveReqVO.UnitRelationItemVO::getId)
                .filter(Objects::nonNull)
                .toList();

        // 3. 提取现有数据的ID列表
        List<Long> existingIds = convertList(existingRelations, QuantityUnitRelationDO::getId);

        // 4. 找出需要删除的ID(数据库有但请求中没有的)
        List<Long> toDeleteIds = new ArrayList<>();
        for (Long existingId : existingIds) {
            if (!requestIds.contains(existingId)) {
                toDeleteIds.add(existingId);
            }
        }

        // 5. 执行逻辑删除
        if (CollUtil.isNotEmpty(toDeleteIds)) {
            quantityUnitRelationMapper.deleteByIds(toDeleteIds);
        }

        // 6. 处理新增和更新
        for (QuantityUnitRelationBatchSaveReqVO.UnitRelationItemVO item : requestItems) {
            QuantityUnitRelationDO relation = new QuantityUnitRelationDO();
            relation.setUntQtyId(untQtyId);
            relation.setUntId(item.getUntId());
            relation.setIsBse(item.getIsBse());

            if (item.getId() != null) {
                // 更新操作
                relation.setId(item.getId());
                quantityUnitRelationMapper.updateById(relation);
            } else {
                // 新增操作
                quantityUnitRelationMapper.insert(relation);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public QuantityUnitRelationRespVO createUnitWithRelation(CreateUnitWithRelationReqVO createReqVO) {
        // 1. 创建计量单位
        UntInfoSaveReqVO untInfoReqVO = new UntInfoSaveReqVO();
        untInfoReqVO.setName(createReqVO.getName());
        untInfoReqVO.setSmb(createReqVO.getSmb());
        UntInfoRespVO untInfoResp = untInfoService.createUntInfo(untInfoReqVO);

        // 2. 创建量纲-单位关联关系
        QuantityUnitRelationSaveReqVO relationReqVO = new QuantityUnitRelationSaveReqVO();
        relationReqVO.setUntQtyId(createReqVO.getUntQtyId());
        relationReqVO.setUntId(untInfoResp.getId());
        relationReqVO.setIsBse(createReqVO.getIsBse());

        return createQuantityUnitRelation(relationReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUnitWithRelation(DeleteUnitWithRelationReqVO deleteReqVO) {
        // 1. 先删除关联关系（外键约束，必须先删除）
        deleteQuantityUnitRelation(deleteReqVO.getRelationId());

        // 2. 再删除计量单位
        untInfoService.deleteUntInfo(deleteReqVO.getUntId());
    }

    @Override
    public PageResult<QuantityUnitRelationSimpleRespVO> getQuantityUnitRelationSimplePage(QuantityUnitRelationSimplePageReqVO pageReqVO) {
        LambdaQueryWrapperX<QuantityUnitRelationDO> wrapper = new LambdaQueryWrapperX<>();
        wrapper.eqIfPresent(QuantityUnitRelationDO::getUntQtyId, pageReqVO.getUntQtyId());

        if (StrUtil.isNotBlank(pageReqVO.getKeyword())) {
            String keyword = pageReqVO.getKeyword();
        List<Long> matchedQtyIds = unitQuantityMapper.selectList(new LambdaQueryWrapperX<UnitQuantityDO>()
            .like(UnitQuantityDO::getName, keyword))
                    .stream()
                    .map(UnitQuantityDO::getId)
                    .filter(Objects::nonNull)
                    .toList();
        List<Long> matchedUntIds = untInfoMapper.selectList(new LambdaQueryWrapperX<UntInfoDO>()
            .like(UntInfoDO::getName, keyword)
            .or()
            .like(UntInfoDO::getSmb, keyword))
                    .stream()
                    .map(UntInfoDO::getId)
                    .filter(Objects::nonNull)
                    .toList();

            if (CollUtil.isEmpty(matchedQtyIds) && CollUtil.isEmpty(matchedUntIds)) {
                return new PageResult<>(Collections.emptyList(), 0L);
            }

            wrapper.and(w -> {
                boolean hasCondition = false;
                if (CollUtil.isNotEmpty(matchedQtyIds)) {
                    w.in(QuantityUnitRelationDO::getUntQtyId, matchedQtyIds);
                    hasCondition = true;
                }
                if (CollUtil.isNotEmpty(matchedUntIds)) {
                    if (hasCondition) {
                        w.or();
                    }
                    w.in(QuantityUnitRelationDO::getUntId, matchedUntIds);
                }
            });
        }

        wrapper.orderByAsc(QuantityUnitRelationDO::getUntQtyId).orderByAsc(QuantityUnitRelationDO::getId);

        PageResult<QuantityUnitRelationDO> pageResult = quantityUnitRelationMapper.selectSimplePage(pageReqVO, wrapper);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return new PageResult<>(Collections.emptyList(), pageResult.getTotal());
        }

        Set<Long> qtyIds = pageResult.getList().stream()
                .map(QuantityUnitRelationDO::getUntQtyId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Set<Long> unitIds = pageResult.getList().stream()
                .map(QuantityUnitRelationDO::getUntId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        Map<Long, UnitQuantityDO> qtyMap = qtyIds.isEmpty() ? Collections.emptyMap()
                : unitQuantityMapper.selectBatchIds(qtyIds).stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(UnitQuantityDO::getId, Function.identity()));
        Map<Long, UntInfoDO> unitMap = unitIds.isEmpty() ? Collections.emptyMap()
                : untInfoMapper.selectBatchIds(unitIds).stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(UntInfoDO::getId, Function.identity()));

        List<QuantityUnitRelationSimpleRespVO> respList = pageResult.getList().stream().map(item -> {
            QuantityUnitRelationSimpleRespVO vo = new QuantityUnitRelationSimpleRespVO();
            vo.setId(item.getId());
            vo.setUntQtyId(item.getUntQtyId());
            UnitQuantityDO quantityDO = qtyMap.get(item.getUntQtyId());
            if (quantityDO != null) {
                vo.setUntQtyName(quantityDO.getName());
            }
            vo.setUntId(item.getUntId());
            UntInfoDO untInfoDO = unitMap.get(item.getUntId());
            if (untInfoDO != null) {
                vo.setUntName(untInfoDO.getName());
                vo.setUntSymbol(untInfoDO.getSmb());
            }
            vo.setIsBse(item.getIsBse());
            return vo;
        }).collect(Collectors.toList());
        return new PageResult<>(respList, pageResult.getTotal());
    }

}