package com.ycwl.basic.face.pipeline.stages;

import com.ycwl.basic.face.pipeline.core.FaceMatchingContext;
import com.ycwl.basic.pipeline.annotation.StageConfig;
import com.ycwl.basic.pipeline.core.AbstractPipelineStage;
import com.ycwl.basic.pipeline.core.StageResult;
import com.ycwl.basic.pipeline.enums.StageOptionalMode;
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 按时间范围筛选样本Stage
 * 负责根据景区配置的游览时间(tour_time)筛选匹配样本
 *
 * 职责:
 * 1. 从context.scenicConfig读取tour_time配置(分钟)
 * 2. 从context.faceSamples读取样本实体缓存
 * 3. 找到最新的样本,以其拍摄时间为基准
 * 4. 筛选出时间范围内(最新样本时间 ± tour_time分钟)的样本
 * 5. 更新context.sampleListIds
 *
 * 前置条件:
 * - context.faceSamples不为空 (由LoadMatchedSamplesStage加载)
 * - context.scenicConfig配置了tour_time
 *
 * 配置说明: tour_time=0或null表示不限制时间范围
 */
@Slf4j
@Component
@StageConfig(
    stageId = "filter_by_time_range",
    optionalMode = StageOptionalMode.SUPPORT,
    description = "按游览时间范围筛选样本",
    defaultEnabled = true
)
public class FilterByTimeRangeStage extends AbstractPipelineStage<FaceMatchingContext> {

    @Override
    public String getName() {
        return "FilterByTimeRange";
    }

    @Override
    protected boolean shouldExecuteByBusinessLogic(FaceMatchingContext context) {
        // 检查faceSamples是否为空
        List<FaceSampleEntity> faceSamples = context.getFaceSamples();
        if (faceSamples == null || faceSamples.isEmpty()) {
            log.debug("faceSamples为空,跳过时间范围筛选,faceId={}", context.getFaceId());
            return false;
        }

        // 检查是否配置了tour_time
        Integer tourMinutes = context.getScenicConfig() != null
                ? context.getScenicConfig().getInteger("tour_time")
                : null;
        if (tourMinutes == null || tourMinutes <= 0) {
            log.debug("景区未配置tour_time或配置为0,跳过时间范围筛选,faceId={}", context.getFaceId());
            return false;
        }

        return true;
    }

    @Override
    protected StageResult<FaceMatchingContext> doExecute(FaceMatchingContext context) {
        List<FaceSampleEntity> faceSamples = context.getFaceSamples();
        List<Long> sampleListIds = context.getSampleListIds();
        Long faceId = context.getFaceId();

        // 防御性检查：faceSamples为空
        if (faceSamples == null || faceSamples.isEmpty()) {
            log.debug("faceSamples为空,跳过时间范围筛选,faceId={}", faceId);
            return StageResult.skipped("faceSamples为空");
        }

        // 防御性检查：tour_time配置
        Integer tourMinutes = context.getScenicConfig() != null
                ? context.getScenicConfig().getInteger("tour_time")
                : null;
        if (tourMinutes == null || tourMinutes <= 0) {
            log.debug("景区未配置tour_time或配置为0,跳过时间范围筛选,faceId={}", faceId);
            return StageResult.skipped("未配置tour_time");
        }

        try {
            // 1. 构建样本ID到实体的映射
            Map<Long, FaceSampleEntity> sampleMap = faceSamples.stream()
                    .collect(Collectors.toMap(FaceSampleEntity::getId, sample -> sample, (a, b) -> a));

            // 2. 找到最新的样本(拍摄时间最晚)
            FaceSampleEntity topMatchSample = faceSamples.stream()
                    .filter(sample -> sample.getCreateAt() != null)
                    .max(Comparator.comparing(FaceSampleEntity::getCreateAt))
                    .orElse(null);

            if (topMatchSample == null || topMatchSample.getCreateAt() == null) {
                log.warn("未找到有效的样本拍摄时间,保留所有样本,faceId={}", faceId);
                return StageResult.success("样本无拍摄时间,保留所有");
            }

            Date referenceTime = topMatchSample.getCreateAt();
            long referenceMillis = referenceTime.getTime();
            long tourMillis = tourMinutes * 60 * 1000L;

            // 3. 筛选时间范围内的样本
            List<Long> filteredIds = sampleListIds.stream()
                    .filter(sampleId -> {
                        FaceSampleEntity sample = sampleMap.get(sampleId);
                        if (sample == null || sample.getCreateAt() == null) {
                            return false; // 无时间信息的样本被过滤
                        }
                        long timeDiff = Math.abs(sample.getCreateAt().getTime() - referenceMillis);
                        return timeDiff <= tourMillis;
                    })
                    .collect(Collectors.toList());

            // 4. 更新context
            context.setSampleListIds(filteredIds);

            log.info("时间范围筛选完成: faceId={}, tour_time={}分钟, 原始样本数={}, 筛选后数={}",
                    faceId, tourMinutes, sampleListIds.size(), filteredIds.size());

            return StageResult.success(String.format("时间筛选: %d → %d",
                    sampleListIds.size(), filteredIds.size()));

        } catch (Exception e) {
            log.error("时间范围筛选失败,faceId={}", faceId, e);
            // 筛选失败不影响主流程,返回降级
            return StageResult.degraded("时间范围筛选失败: " + e.getMessage());
        }
    }
}
