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

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import com.yhy.module.core.controller.admin.infoprice.vo.InfoPriceResourcePageReqVO;
import com.yhy.module.core.controller.admin.infoprice.vo.InfoPriceResourceRespVO;
import com.yhy.module.core.controller.admin.infoprice.vo.InfoPriceResourceSaveReqVO;
import com.yhy.module.core.dal.dataobject.infoprice.InfoPriceBookDO;
import com.yhy.module.core.dal.dataobject.infoprice.InfoPriceCategoryTreeDO;
import com.yhy.module.core.dal.dataobject.infoprice.InfoPriceResourceDO;
import com.yhy.module.core.dal.dataobject.infoprice.InfoPriceTreeDO;
import com.yhy.module.core.dal.dataobject.resource.ResourceItemDO;
import com.yhy.module.core.dal.mysql.infoprice.InfoPriceBookMapper;
import com.yhy.module.core.dal.mysql.infoprice.InfoPriceCategoryTreeMapper;
import com.yhy.module.core.dal.mysql.infoprice.InfoPriceResourceMapper;
import com.yhy.module.core.dal.mysql.infoprice.InfoPriceResourcePriceMapper;
import com.yhy.module.core.dal.mysql.infoprice.InfoPriceTreeMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceItemMapper;
import com.yhy.module.core.enums.infoprice.InfoPriceCategoryNodeTypeEnum;
import com.yhy.module.core.service.infoprice.InfoPriceResourceService;
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.Optional;
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 芋道源码
 */
@Service
@Validated
@Slf4j
public class InfoPriceResourceServiceImpl implements InfoPriceResourceService {

    @Resource
    private InfoPriceResourceMapper resourceMapper;

    @Resource
    private InfoPriceCategoryTreeMapper categoryTreeMapper;

    @Resource
    private InfoPriceResourcePriceMapper infoPriceResourcePriceMapper;

    @Resource
    private ResourceItemMapper resourceItemMapper;

    @Resource
    private InfoPriceBookMapper infoPriceBookMapper;

    @Resource
    private InfoPriceTreeMapper infoPriceTreeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createResource(InfoPriceResourceSaveReqVO createReqVO) {
        // 0. 创建时 categoryTreeId 必填
        if (createReqVO.getCategoryTreeId() == null) {
            throw exception(INFO_PRICE_CATEGORY_TREE_NOT_EXISTS);
        }
        // 1. 校验分类树节点存在且为内容节点
        validateContentNode(createReqVO.getCategoryTreeId());

        // 2. 校验编码唯一性
        validateCodeUnique(createReqVO.getCategoryTreeId(), createReqVO.getCode(), null);

        // 3. 查找或创建工料机
        Long resourceItemId = findOrCreateResourceItem(createReqVO.getName(), createReqVO.getSpec(), createReqVO.getUnit());

        // 4. 插入
        InfoPriceResourceDO resource = new InfoPriceResourceDO();
        resource.setCategoryTreeId(createReqVO.getCategoryTreeId());
        resource.setCode(createReqVO.getCode());
        resource.setSourceResourceItemId(resourceItemId);
        resource.setPriceTaxExcl(createReqVO.getPriceTaxExcl());
        resource.setTaxRate(createReqVO.getTaxRate());
        resource.setPriceTaxIncl(createReqVO.getPriceTaxIncl());
        resource.setDrawingUrl(createReqVO.getDrawingUrl());
        resource.setCategoryId(createReqVO.getCategoryId());
        resource.setRemark(createReqVO.getRemark());
        resource.setAttributes(createReqVO.getAttributes());
        
        // 计算排序
        List<InfoPriceResourceDO> siblings = resourceMapper.selectListByCategoryTreeId(createReqVO.getCategoryTreeId());
        resource.setSortOrder(siblings.size() + 1);

        resourceMapper.insert(resource);
        return resource.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateResource(InfoPriceResourceSaveReqVO updateReqVO) {
        // 1. 校验存在
        InfoPriceResourceDO resource = validateResourceExists(updateReqVO.getId());

        // 2. 校验编码唯一性
        validateCodeUnique(resource.getCategoryTreeId(), updateReqVO.getCode(), updateReqVO.getId());

        // 3. 查找或创建工料机
        Long resourceItemId = findOrCreateResourceItem(updateReqVO.getName(), updateReqVO.getSpec(), updateReqVO.getUnit());

        // 4. 更新
        InfoPriceResourceDO updateObj = new InfoPriceResourceDO();
        updateObj.setId(updateReqVO.getId());
        updateObj.setCode(updateReqVO.getCode());
        updateObj.setSourceResourceItemId(resourceItemId);
        updateObj.setPriceTaxExcl(updateReqVO.getPriceTaxExcl());
        updateObj.setTaxRate(updateReqVO.getTaxRate());
        updateObj.setPriceTaxIncl(updateReqVO.getPriceTaxIncl());
        updateObj.setDrawingUrl(updateReqVO.getDrawingUrl());
        updateObj.setCategoryId(updateReqVO.getCategoryId());
        updateObj.setRemark(updateReqVO.getRemark());
        updateObj.setAttributes(updateReqVO.getAttributes());
        resourceMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteResource(Long id) {
        // 1. 校验存在
        validateResourceExists(id);

        // 2. 校验是否有价格历史
        long priceCount = infoPriceResourcePriceMapper.selectCount("resource_id", id);
        if (priceCount > 0) {
            throw exception(INFO_PRICE_RESOURCE_HAS_PRICES);
        }

        // 3. 删除
        resourceMapper.deleteById(id);
    }

    @Override
    public InfoPriceResourceRespVO getResource(Long id) {
        InfoPriceResourceDO resource = resourceMapper.selectById(id);
        return convertToVO(resource);
    }

    @Override
    public PageResult<InfoPriceResourceRespVO> getResourcePage(InfoPriceResourcePageReqVO pageReqVO) {
        // 如果有地区筛选，先找出匹配的categoryTreeIds
        List<Long> matchingCategoryTreeIds = null;
        if (pageReqVO.getTreeNodeId() != null && !pageReqVO.getTreeNodeId().isEmpty()) {
            try {
                Long treeNodeId = Long.parseLong(pageReqVO.getTreeNodeId());
                matchingCategoryTreeIds = findMatchingCategoryTreeIds(treeNodeId);
                if (matchingCategoryTreeIds.isEmpty()) {
                    // 没有匹配的地区，直接返回空结果
                    return new PageResult<>(java.util.Collections.emptyList(), 0L);
                }
            } catch (NumberFormatException e) {
                // 忽略无效的ID
            }
        }
        
        // 执行数据库查询（带categoryTreeIds过滤）
        List<Long> finalMatchingCategoryTreeIds = matchingCategoryTreeIds;
        PageResult<InfoPriceResourceDO> pageResult =
                (pageReqVO.getHistory()!= null && pageReqVO.getHistory()) ? TenantUtils.executeIgnore(() -> resourceMapper.selectPageWithCategoryTreeIds(pageReqVO, finalMatchingCategoryTreeIds)):
                        TenantUtils.executeIsAdmin(()->resourceMapper.selectPageWithCategoryTreeIds(pageReqVO, finalMatchingCategoryTreeIds));

        // 在 Service 层进行虚拟字段过滤（name、spec、professionType）
        List<InfoPriceResourceRespVO> filteredList =
                pageResult.getList().stream()
                        .map(m-> TenantUtils.executeIgnore(() -> convertToVO(m)))
                        .collect(Collectors.toList());

        
        // 按名称过滤（模糊匹配）
        if (pageReqVO.getName() != null && !pageReqVO.getName().isEmpty()) {
            String nameLower = pageReqVO.getName().toLowerCase();
            filteredList = filteredList.stream()
                    .filter(vo -> vo.getName() != null && vo.getName().toLowerCase().contains(nameLower))
                    .collect(Collectors.toList());
        }
        
        // 按规格型号过滤（模糊匹配）
        if (pageReqVO.getSpec() != null && !pageReqVO.getSpec().isEmpty()) {
            String specLower = pageReqVO.getSpec().toLowerCase();
            filteredList = filteredList.stream()
                    .filter(vo -> vo.getSpec() != null && vo.getSpec().toLowerCase().contains(specLower))
                    .collect(Collectors.toList());
        }
        
        // 按专业类型过滤（精确匹配）
        if (pageReqVO.getProfessionType() != null && !pageReqVO.getProfessionType().isEmpty()) {
            filteredList = filteredList.stream()
                    .filter(vo -> pageReqVO.getProfessionType().equals(vo.getProfessionType()))
                    .collect(Collectors.toList());
        }
        
        // 排除指定的ID列表（用于未关联表格排除已关联数据）
        if (pageReqVO.getExcludeIds() != null && !pageReqVO.getExcludeIds().isEmpty()) {
            java.util.Set<Long> excludeIdSet = new java.util.HashSet<>(pageReqVO.getExcludeIds());
            filteredList = filteredList.stream()
                    .filter(vo -> !excludeIdSet.contains(vo.getId()))
                    .collect(Collectors.toList());
        }
        
        return new PageResult<>(filteredList, (long) filteredList.size());
    }
    
    /**
     * 根据地区节点ID找出所有匹配的categoryTreeIds
     * 匹配规则：信息价册的treeNodeId等于过滤节点，或过滤节点在信息价册treeNodeId的路径中
     */
    private List<Long> findMatchingCategoryTreeIds(Long treeNodeId) {
        log.info("[findMatchingCategoryTreeIds] 开始查找匹配地区节点: treeNodeId={}", treeNodeId);
        
        // 1. 找出所有匹配地区的信息价册
        List<InfoPriceBookDO> allBooks = infoPriceBookMapper.selectList();
        log.info("[findMatchingCategoryTreeIds] 查询到所有信息价册数量: {}", allBooks.size());
        
        List<Long> matchingBookIds = allBooks.stream()
                .filter(book -> {
                    if (book.getTreeNodeId() == null) return false;
                    // 精确匹配
                    if (book.getTreeNodeId().equals(treeNodeId)) {
                        log.debug("[findMatchingCategoryTreeIds] 精确匹配: bookId={}, bookTreeNodeId={}", book.getId(), book.getTreeNodeId());
                        return true;
                    }
                    // 检查路径（过滤节点是信息价册地区的祖先）
                    InfoPriceTreeDO treeNode = infoPriceTreeMapper.selectById(book.getTreeNodeId());
                    if (treeNode != null && treeNode.getPath() != null) {
                        for (String pathId : treeNode.getPath()) {
                            try {
                                // 使用equals比较Long，避免大数==比较失败
                                if (treeNodeId.equals(Long.parseLong(pathId))) {
                                    log.debug("[findMatchingCategoryTreeIds] 路径匹配: bookId={}, bookTreeNodeId={}, path={}", 
                                            book.getId(), book.getTreeNodeId(), treeNode.getPath());
                                    return true;
                                }
                            } catch (NumberFormatException e) {
                                // 忽略
                            }
                        }
                    }
                    return false;
                })
                .map(InfoPriceBookDO::getId)
                .collect(Collectors.toList());
        
        log.info("[findMatchingCategoryTreeIds] 匹配的信息价册IDs: {}", matchingBookIds);
        
        if (matchingBookIds.isEmpty()) {
            log.warn("[findMatchingCategoryTreeIds] 没有找到匹配的信息价册，返回空列表");
            return java.util.Collections.emptyList();
        }
        
        // 2. 找出属于这些信息价册的所有categoryTreeIds
        List<InfoPriceCategoryTreeDO> categoryTrees = categoryTreeMapper.selectListByBookIds(matchingBookIds);
        List<Long> categoryTreeIds = categoryTrees.stream()
                .map(InfoPriceCategoryTreeDO::getId)
                .collect(Collectors.toList());
        
        log.info("[findMatchingCategoryTreeIds] 匹配的categoryTreeIds数量: {}", categoryTreeIds.size());
        return categoryTreeIds;
    }
    
    /**
     * 检查工料机是否匹配指定的树节点（包括子节点）
     */
    private boolean matchTreeNode(InfoPriceResourceRespVO vo, Long treeNodeId) {
        if (vo.getCategoryTreeId() == null) {
            return false;
        }
        // 获取分类树节点
        InfoPriceCategoryTreeDO categoryTree = categoryTreeMapper.selectById(vo.getCategoryTreeId());
        if (categoryTree == null || categoryTree.getBookId() == null) {
            return false;
        }
        // 获取信息价册
        InfoPriceBookDO book = infoPriceBookMapper.selectById(categoryTree.getBookId());
        if (book == null || book.getTreeNodeId() == null) {
            return false;
        }
        // 检查是否匹配（精确匹配或在路径中）
        if (book.getTreeNodeId().equals(treeNodeId)) {
            return true;
        }
        // 检查路径
        InfoPriceTreeDO treeNode = infoPriceTreeMapper.selectById(book.getTreeNodeId());
        if (treeNode != null && treeNode.getPath() != null) {
            for (String pathId : treeNode.getPath()) {
                try {
                    if (Long.parseLong(pathId) == treeNodeId) {
                        return true;
                    }
                } catch (NumberFormatException e) {
                    // 忽略
                }
            }
        }
        return false;
    }

    @Override
    public List<InfoPriceResourceRespVO> getResourceList(Long categoryTreeId) {
        List<InfoPriceResourceDO> list = resourceMapper.selectListByCategoryTreeId(categoryTreeId);
        return list.stream().map(this::convertToVO).collect(Collectors.toList());
    }

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

    private InfoPriceResourceDO validateResourceExists(Long id) {
        InfoPriceResourceDO resource = resourceMapper.selectById(id);
        if (resource == null) {
            throw exception(INFO_PRICE_RESOURCE_NOT_EXISTS);
        }
        return resource;
    }

    private void validateContentNode(Long categoryTreeId) {
        InfoPriceCategoryTreeDO node = categoryTreeMapper.selectById(categoryTreeId);
        if (node == null) {
            throw exception(INFO_PRICE_CATEGORY_TREE_NOT_EXISTS);
        }
        if (!InfoPriceCategoryNodeTypeEnum.CONTENT.getType().equals(node.getNodeType())) {
            throw exception(INFO_PRICE_RESOURCE_ONLY_UNDER_CONTENT_NODE);
        }
    }

    private void validateCodeUnique(Long categoryTreeId, String code, Long excludeId) {
        InfoPriceResourceDO existing = resourceMapper.selectByCategoryTreeIdAndCode(categoryTreeId, code);
        if (existing != null && !existing.getId().equals(excludeId)) {
            throw exception(INFO_PRICE_RESOURCE_CODE_DUPLICATE, code);
        }
    }

    /**
     * 查找或创建工料机
     * 根据（名称、型号规格、单位）查找工料机，如果不存在则创建
     */
    private Long findOrCreateResourceItem(String name, String spec, String unit) {
        // 1. 查找已存在的工料机
        ResourceItemDO existingItem = resourceItemMapper.selectByNameSpecUnit(name, spec, unit);
        if (existingItem != null) {
            return existingItem.getId();
        }

        // 2. 创建新的工料机
        ResourceItemDO newItem = new ResourceItemDO();
        newItem.setName(name);
        newItem.setSpec(spec);
        newItem.setUnit(unit);
        newItem.setSourceType(ResourceItemDO.SOURCE_TYPE_INFO_PRICE);
        // 默认类型为材料
        newItem.setType("material");
        // 设置默认 catalog_item_id（信息价创建的工料机使用默认值1）
        newItem.setCatalogItemId(1L);
        resourceItemMapper.insert(newItem);
        log.info("创建信息价工料机：name={}, spec={}, unit={}, id={}", name, spec, unit, newItem.getId());
        return newItem.getId();
    }

    /**
     * 将 DO 转换为 VO，填充工料机信息和信息价册信息
     */
    private InfoPriceResourceRespVO convertToVO(InfoPriceResourceDO resource) {
        if (resource == null) {
            return null;
        }
        InfoPriceResourceRespVO vo = new InfoPriceResourceRespVO();
        vo.setId(resource.getId());
        vo.setTenantId(resource.getTenantId());
        vo.setCategoryTreeId(resource.getCategoryTreeId());
        vo.setCode(resource.getCode());
        vo.setSourceResourceItemId(resource.getSourceResourceItemId());
        vo.setPriceTaxExcl(resource.getPriceTaxExcl());
        vo.setTaxRate(resource.getTaxRate());
        vo.setPriceTaxIncl(resource.getPriceTaxIncl());
        vo.setDrawingUrl(resource.getDrawingUrl());
        vo.setCategoryId(resource.getCategoryId());
        vo.setRemark(resource.getRemark());
        vo.setSortOrder(resource.getSortOrder());
        vo.setAttributes(resource.getAttributes());
        vo.setCreateTime(resource.getCreateTime());

        // 从工料机表获取 name/spec/unit
        if (resource.getSourceResourceItemId() != null) {
            ResourceItemDO resourceItem = resourceItemMapper.selectById(resource.getSourceResourceItemId());
            if (resourceItem != null) {
                vo.setName(resourceItem.getName());
                vo.setSpec(resourceItem.getSpec());
                vo.setUnit(resourceItem.getUnit());
            }
        }

        // 从分类树获取信息价册信息（附件、专业、地区）
        if (resource.getCategoryTreeId() != null) {
            InfoPriceCategoryTreeDO categoryTree = categoryTreeMapper.selectById(resource.getCategoryTreeId());
            if (categoryTree != null && categoryTree.getBookId() != null) {
                InfoPriceBookDO book = infoPriceBookMapper.selectById(categoryTree.getBookId());
                if (book != null) {
                    vo.setBookName(book.getName());
                    vo.setBookAttachment(book.getAttachment());
                    
                    // 获取信息价树节点（专业和地区）
                    if (book.getTreeNodeId() != null) {
                        InfoPriceTreeDO treeNode = infoPriceTreeMapper.selectById(book.getTreeNodeId());
                        if (treeNode != null) {
                            vo.setProfessionType(treeNode.getEnumType());
                            // 获取完整地区路径
                            vo.setFullRegion(buildFullRegionPath(treeNode));
                        }
                    }
                }
            }
        }
        return vo;
    }

    /**
     * 构建完整地区路径（从根节点到当前节点的名称拼接）
     */
    private String buildFullRegionPath(InfoPriceTreeDO treeNode) {
        if (treeNode == null) {
            return "";
        }
        
        // 获取路径中的所有节点ID
        String[] pathIds = treeNode.getPath();
        if (pathIds == null || pathIds.length == 0) {
            return treeNode.getName();
        }
        
        // 查询路径中所有节点的名称
        StringBuilder pathBuilder = new StringBuilder();
        for (String pathId : pathIds) {
            try {
                Long id = Long.parseLong(pathId);
                InfoPriceTreeDO pathNode = infoPriceTreeMapper.selectById(id);
                if (pathNode != null && pathNode.getName() != null && !pathNode.getName().isEmpty()) {
                    if (pathBuilder.length() > 0) {
                        pathBuilder.append(" / ");
                    }
                    pathBuilder.append(pathNode.getName());
                }
            } catch (NumberFormatException e) {
                // 忽略无效的ID
            }
        }
        
        // 添加当前节点名称
        if (pathBuilder.length() > 0) {
            pathBuilder.append(" / ");
        }
        pathBuilder.append(treeNode.getName());
        
        return pathBuilder.toString();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> createResourceBatch(List<InfoPriceResourceSaveReqVO> createReqVOList) {
        if (createReqVOList == null || createReqVOList.isEmpty()) {
            return new java.util.ArrayList<>();
        }
        List<InfoPriceResourceDO> resourceList = TenantUtils.execute(1L,() -> {
            List<InfoPriceResourceDO> list = new java.util.ArrayList<>();
            for (InfoPriceResourceSaveReqVO item : createReqVOList) {

                // 查找或创建工料机
                Long resourceItemId = findOrCreateResourceItem(item.getName(), item.getSpec(), item.getUnit());

                InfoPriceResourceDO resource = new InfoPriceResourceDO();
                resource.setCategoryTreeId(item.getCategoryTreeId());
                resource.setCode(item.getCode());
                resource.setSourceResourceItemId(resourceItemId);
                resource.setPriceTaxExcl(item.getPriceTaxExcl());
                resource.setTaxRate(item.getTaxRate());
                resource.setPriceTaxIncl(item.getPriceTaxIncl());
                resource.setDrawingUrl(item.getDrawingUrl());
                resource.setCategoryId(item.getCategoryId());
                resource.setRemark(item.getRemark());
                resource.setAttributes(item.getAttributes());
                list.add(resource);
            }
            return list;
        });

        
        // 批量插入
        resourceMapper.insertBatch(resourceList);

        // 返回ID列表
        return resourceList.stream()
                .map(InfoPriceResourceDO::getId)
                .collect(Collectors.toList());
    }

    @Override
    public List<InfoPriceResourceRespVO> getResourceListBySourceResourceItemId(Long sourceResourceItemId) {
        List<InfoPriceResourceDO> resourceList = resourceMapper.selectList(new LambdaQueryWrapperX<InfoPriceResourceDO>()
                .eq(InfoPriceResourceDO::getSourceResourceItemId, sourceResourceItemId));
        
        return BeanUtils.toBean(resourceList, InfoPriceResourceRespVO.class);
    }

}
