package com.njcn.rdms.module.project.dal.mysql.product;

import com.njcn.rdms.framework.common.pojo.PageResult;
import com.njcn.rdms.framework.mybatis.core.mapper.BaseMapperX;
import com.njcn.rdms.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.njcn.rdms.module.project.controller.admin.product.vo.requirement.ProductRequirementPageReqVO;
import com.njcn.rdms.module.project.dal.dataobject.product.ProductRequirementDO;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.util.Collection;
import java.util.List;

/**
 * 产品需求 Mapper
 */
@Mapper
public interface ProductRequirementMapper extends BaseMapperX<ProductRequirementDO> {

    /**
     * 分页查询需求列表
     */
    default PageResult<ProductRequirementDO> selectPage(ProductRequirementPageReqVO reqVO) {
        LambdaQueryWrapperX<ProductRequirementDO> queryWrapper = buildQueryWrapper(reqVO);
        return selectPage(reqVO, queryWrapper);
    }

    /**
     * 查询所有符合条件的需求列表（不分页，用于树形查询）
     */
    default List<ProductRequirementDO> selectList(ProductRequirementPageReqVO reqVO) {
        LambdaQueryWrapperX<ProductRequirementDO> queryWrapper = buildQueryWrapper(reqVO);
        return selectList(queryWrapper);
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapperX<ProductRequirementDO> buildQueryWrapper(ProductRequirementPageReqVO reqVO) {
        LambdaQueryWrapperX<ProductRequirementDO> queryWrapper = new LambdaQueryWrapperX<>();
        // 标题模糊搜索
        if (StringUtils.hasText(reqVO.getTitle())) {
            queryWrapper.like(ProductRequirementDO::getTitle, reqVO.getTitle());
        }
        // 分类精确匹配
        queryWrapper.eqIfPresent(ProductRequirementDO::getCategory, reqVO.getCategory())
                // 优先级精确匹配
                .eqIfPresent(ProductRequirementDO::getPriority, reqVO.getPriority())
                // 状态精确匹配
                .eqIfPresent(ProductRequirementDO::getStatusCode, reqVO.getStatusCode())
                // 负责人精确匹配
                .eqIfPresent(ProductRequirementDO::getCurrentHandlerUserId, reqVO.getCurrentHandlerUserId())
                // 来源类型精确匹配
                .eqIfPresent(ProductRequirementDO::getSourceType, reqVO.getSourceType())
                // 来源业务编号模糊匹配
                .likeIfPresent(ProductRequirementDO::getSourceBizCode, reqVO.getSourceBizCode())
                // 模块ID列表IN查询（优先使用moduleIds，用于支持子模块查询）
                .inIfPresent(ProductRequirementDO::getModuleId, reqVO.getModuleIds())
                // 模块ID精确匹配（当moduleIds为空时使用）
                .eqIfPresent(ProductRequirementDO::getModuleId, reqVO.getModuleId())
                // 父需求ID精确匹配（查询子需求时使用）
                .eqIfPresent(ProductRequirementDO::getParentId, reqVO.getParentId())
                // 产品ID精确匹配
                .eq(ProductRequirementDO::getProductId, reqVO.getProductId())
                // 按排序值升序，再按创建时间降序
                .orderByAsc(ProductRequirementDO::getSort)
                .orderByDesc(ProductRequirementDO::getCreateTime);
        return queryWrapper;
    }

    /**
     * 根据产品ID和模块ID查询需求列表
     */
    default List<ProductRequirementDO> selectListByProductIdAndModuleId(Long productId, Long moduleId) {
        return selectList(new LambdaQueryWrapperX<ProductRequirementDO>()
                .eq(ProductRequirementDO::getProductId, productId)
                .eq(ProductRequirementDO::getModuleId, moduleId)
                .orderByAsc(ProductRequirementDO::getSort)
                .orderByDesc(ProductRequirementDO::getCreateTime));
    }

    /**
     * 根据父需求ID查询子需求列表
     */
    default List<ProductRequirementDO> selectListByParentId(Long parentId) {
        return selectList(new LambdaQueryWrapperX<ProductRequirementDO>()
                .eq(ProductRequirementDO::getParentId, parentId)
                .orderByAsc(ProductRequirementDO::getSort)
                .orderByDesc(ProductRequirementDO::getCreateTime));
    }

    /**
     * 根据产品ID查询所有需求（用于模块删除时级联处理）
     */
    default List<ProductRequirementDO> selectListByProductId(Long productId) {
        return selectList(new LambdaQueryWrapperX<ProductRequirementDO>()
                .eq(ProductRequirementDO::getProductId, productId)
                .orderByAsc(ProductRequirementDO::getSort));
    }

    /**
     * 根据模块ID查询需求列表
     */
    default List<ProductRequirementDO> selectListByModuleId(Long moduleId) {
        return selectList(new LambdaQueryWrapperX<ProductRequirementDO>()
                .eq(ProductRequirementDO::getModuleId, moduleId)
                .orderByAsc(ProductRequirementDO::getSort));
    }

    /**
     * 带并发控制的状态更新（id + fromStatus 条件更新）
     */
    default int updateStatusByIdAndStatus(Long id, String fromStatus, String toStatus, String lastStatusReason) {
        return updateStatusByIdAndStatusWithProject(id, fromStatus, toStatus, lastStatusReason, null);
    }

    /**
     * 带并发控制的状态更新（支持同时更新关联项目ID）
     */
    default int updateStatusByIdAndStatusWithProject(Long id, String fromStatus, String toStatus, String lastStatusReason, Long implementProjectId) {
        ProductRequirementDO update = new ProductRequirementDO();
        update.setStatusCode(toStatus);
        update.setLastStatusReason(lastStatusReason);
        if (implementProjectId != null) {
            update.setImplementProjectId(implementProjectId);
        }
        return update(update, new LambdaQueryWrapperX<ProductRequirementDO>()
                .eq(ProductRequirementDO::getId, id)
                .eq(ProductRequirementDO::getStatusCode, fromStatus));
    }

    /**
     * 根据ID和状态删除（带并发控制）
     */
    default int deleteByIdAndStatus(Long id, String statusCode) {
        return delete(new LambdaQueryWrapperX<ProductRequirementDO>()
                .eq(ProductRequirementDO::getId, id)
                .eq(ProductRequirementDO::getStatusCode, statusCode));
    }

    /**
     * 临期/逾期告警候选：预计完成日非空且 <= maxPlannedEndDate，状态不在排除集（终态+paused）。
     * excludeStatusCodes 为空时不排除任何状态（空集守卫，与既有口径一致）。
     * 设计见 docs/domains/project/2026-06-12-临期逾期告警-设计.html。
     */
    default List<ProductRequirementDO> selectDueAlertCandidateList(LocalDate maxPlannedEndDate,
                                                                   Collection<String> excludeStatusCodes) {
        return selectList(new LambdaQueryWrapperX<ProductRequirementDO>()
                .isNotNull(ProductRequirementDO::getExpectedTime)
                .le(ProductRequirementDO::getExpectedTime, maxPlannedEndDate)
                .notIn(excludeStatusCodes != null && !excludeStatusCodes.isEmpty(),
                        ProductRequirementDO::getStatusCode, excludeStatusCodes));
    }

}
