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

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.yhy.module.core.controller.admin.infoprice.vo.InfoPriceBookPageReqVO;
import com.yhy.module.core.controller.admin.infoprice.vo.InfoPriceBookRespVO;
import com.yhy.module.core.controller.admin.infoprice.vo.InfoPriceBookSaveReqVO;
import com.yhy.module.core.dal.dataobject.infoprice.InfoPriceBookDO;
import com.yhy.module.core.dal.dataobject.infoprice.InfoPriceTreeDO;
import com.yhy.module.core.dal.mysql.infoprice.InfoPriceBookMapper;
import com.yhy.module.core.dal.mysql.infoprice.InfoPriceTreeMapper;
import com.yhy.module.core.enums.infoprice.InfoPricePublishStatusEnum;
import com.yhy.module.core.service.infoprice.InfoPriceBookService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
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 实现类
 *
 * @author yhy
 */
@Service
@Validated
@Slf4j
public class InfoPriceBookServiceImpl implements InfoPriceBookService {

    @Resource
    private InfoPriceBookMapper infoPriceBookMapper;

    @Resource
    private InfoPriceTreeMapper infoPriceTreeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createInfoPriceBook(InfoPriceBookSaveReqVO createReqVO) {
        // 1. 验证树节点存在
        validateTreeNodeExists(createReqVO.getTreeNodeId());

        // 2. 验证时间范围
        validateTimeRange(createReqVO.getStartTime(), createReqVO.getEndTime());

        // 3. 验证发布状态
        if (createReqVO.getPublishStatus() != null) {
            validatePublishStatus(createReqVO.getPublishStatus());
        }

        // 4. 构建DO对象
        InfoPriceBookDO book = BeanUtils.toBean(createReqVO, InfoPriceBookDO.class);
        Long tenantId = cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder.getTenantId();
        book.setTenantId(tenantId);

        // 5. 插入数据库（时间段重叠由数据库约束保证）
        try {
            infoPriceBookMapper.insert(book);
        } catch (Exception e) {
            // 捕获数据库约束异常
            if (e.getMessage().contains("exclude_time_overlap")) {
                throw exception(INFO_PRICE_BOOK_TIME_OVERLAP);
            }
            throw e;
        }

        return book.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateInfoPriceBook(InfoPriceBookSaveReqVO updateReqVO) {
        // 1. 验证信息价册存在
        validateBookExists(updateReqVO.getId());

        // 2. 验证树节点存在
        validateTreeNodeExists(updateReqVO.getTreeNodeId());

        // 3. 验证时间范围
        validateTimeRange(updateReqVO.getStartTime(), updateReqVO.getEndTime());

        // 4. 验证发布状态
        if (updateReqVO.getPublishStatus() != null) {
            validatePublishStatus(updateReqVO.getPublishStatus());
        }

        // 5. 更新数据
        InfoPriceBookDO updateObj = BeanUtils.toBean(updateReqVO, InfoPriceBookDO.class);
        try {
            infoPriceBookMapper.updateById(updateObj);
        } catch (Exception e) {
            // 捕获数据库约束异常
            if (e.getMessage().contains("exclude_time_overlap")) {
                throw exception(INFO_PRICE_BOOK_TIME_OVERLAP);
            }
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteInfoPriceBook(Long id) {
        // 1. 验证信息价册存在
        validateBookExists(id);

        // 2. TODO: 验证是否有信息价条目（如果需要）
        // Long itemCount = infoPriceItemMapper.countByBookId(id);
        // if (itemCount > 0) {
        //     throw exception(INFO_PRICE_BOOK_HAS_ITEMS);
        // }

        // 3. 删除信息价册
        infoPriceBookMapper.deleteById(id);
    }

    @Override
    public InfoPriceBookRespVO getInfoPriceBook(Long id) {
        InfoPriceBookDO book = validateBookExists(id);
        InfoPriceBookRespVO respVO = BeanUtils.toBean(book, InfoPriceBookRespVO.class);
        
        // 计算虚拟字段"地区"
        respVO.setRegion(calculateRegion(book.getTreeNodeId()));
        
        return respVO;
    }

    @Override
    public PageResult<InfoPriceBookRespVO> getInfoPriceBookPage(InfoPriceBookPageReqVO pageReqVO) {
        // 1. 分页查询
        PageResult<InfoPriceBookDO> pageResult = infoPriceBookMapper.selectPage(pageReqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return PageResult.empty(pageResult.getTotal());
        }

        // 2. 转换为VO
        List<InfoPriceBookRespVO> voList = BeanUtils.toBean(pageResult.getList(), InfoPriceBookRespVO.class);

        // 3. 批量计算虚拟字段"地区"
        List<Long> treeNodeIds = voList.stream()
                .map(InfoPriceBookRespVO::getTreeNodeId)
                .distinct()
                .collect(Collectors.toList());
        
        Map<Long, String> regionMap = calculateRegionBatch(treeNodeIds);
        
        voList.forEach(vo -> vo.setRegion(regionMap.get(vo.getTreeNodeId())));

        return new PageResult<>(voList, pageResult.getTotal());
    }

    // ==================== 私有方法 ====================

    /**
     * 验证信息价册存在
     */
    private InfoPriceBookDO validateBookExists(Long id) {
        InfoPriceBookDO book = infoPriceBookMapper.selectById(id);
        if (book == null) {
            throw exception(INFO_PRICE_BOOK_NOT_EXISTS);
        }
        return book;
    }

    /**
     * 验证树节点存在
     */
    private void validateTreeNodeExists(Long treeNodeId) {
        InfoPriceTreeDO tree = infoPriceTreeMapper.selectById(treeNodeId);
        if (tree == null) {
            throw exception(INFO_PRICE_TREE_NOT_EXISTS);
        }
    }

    /**
     * 验证时间范围
     */
    private void validateTimeRange(java.time.LocalDate startTime, java.time.LocalDate endTime) {
        if (startTime != null && endTime != null && endTime.isBefore(startTime)) {
            throw exception(INFO_PRICE_BOOK_TIME_INVALID);
        }
    }

    /**
     * 验证发布状态
     */
    private void validatePublishStatus(String publishStatus) {
        InfoPricePublishStatusEnum statusEnum = InfoPricePublishStatusEnum.valueOfCode(publishStatus);
        if (statusEnum == null) {
            throw exception(INFO_PRICE_BOOK_INVALID_PUBLISH_STATUS);
        }
    }

    /**
     * 计算地区路径（单个）
     */
    private String calculateRegion(Long treeNodeId) {
        if (treeNodeId == null) {
            return "";
        }

        InfoPriceTreeDO tree = infoPriceTreeMapper.selectById(treeNodeId);
        if (tree == null) {
            return "";
        }

        // 获取路径上的所有节点
        List<Long> pathIds = new java.util.ArrayList<>();
        if (tree.getPath() != null && tree.getPath().length > 0) {
            for (String id : tree.getPath()) {
                pathIds.add(Long.parseLong(id));
            }
        }
        pathIds.add(treeNodeId);

        // 查询所有节点
        List<InfoPriceTreeDO> nodes = infoPriceTreeMapper.selectBatchIds(pathIds);
        Map<Long, String> nameMap = nodes.stream()
                .collect(Collectors.toMap(InfoPriceTreeDO::getId, InfoPriceTreeDO::getName));

        // 按路径顺序拼接名称
        return pathIds.stream()
                .map(nameMap::get)
                .filter(name -> name != null)
                .collect(Collectors.joining("*"));
    }

    /**
     * 批量计算地区路径
     */
    private Map<Long, String> calculateRegionBatch(List<Long> treeNodeIds) {
        if (CollUtil.isEmpty(treeNodeIds)) {
            return java.util.Collections.emptyMap();
        }

        // 查询所有树节点
        List<InfoPriceTreeDO> trees = infoPriceTreeMapper.selectBatchIds(treeNodeIds);
        
        // 收集所有需要查询的节点ID
        java.util.Set<Long> allNodeIds = new java.util.HashSet<>();
        for (InfoPriceTreeDO tree : trees) {
            if (tree.getPath() != null && tree.getPath().length > 0) {
                for (String id : tree.getPath()) {
                    allNodeIds.add(Long.parseLong(id));
                }
            }
            allNodeIds.add(tree.getId());
        }

        // 查询所有节点
        List<InfoPriceTreeDO> allNodes = infoPriceTreeMapper.selectBatchIds(new java.util.ArrayList<>(allNodeIds));
        Map<Long, String> nameMap = allNodes.stream()
                .collect(Collectors.toMap(InfoPriceTreeDO::getId, InfoPriceTreeDO::getName));

        // 为每个树节点计算地区路径
        return trees.stream().collect(Collectors.toMap(
                InfoPriceTreeDO::getId,
                tree -> {
                    List<Long> pathIds = new java.util.ArrayList<>();
                    if (tree.getPath() != null && tree.getPath().length > 0) {
                        for (String id : tree.getPath()) {
                            pathIds.add(Long.parseLong(id));
                        }
                    }
                    pathIds.add(tree.getId());

                    return pathIds.stream()
                            .map(nameMap::get)
                            .filter(name -> name != null)
                            .collect(Collectors.joining("*"));
                }
        ));
    }
}
