package com.ycwl.basic.service.mobile.impl;

import com.ycwl.basic.exception.BaseException;
import com.ycwl.basic.facebody.FaceBodyFactory;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.facebody.entity.SearchFaceResp;
import com.ycwl.basic.facebody.entity.SearchFaceResultItem;
import com.ycwl.basic.integration.common.manager.DeviceConfigManager;
import com.ycwl.basic.integration.common.manager.ScenicConfigManager;
import com.ycwl.basic.mapper.FaceDetectLogAiCamMapper;
import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.model.mobile.face.FaceRecognizeResp;
import com.ycwl.basic.model.mobile.goods.GoodsDetailVO;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
import com.ycwl.basic.model.pc.faceDetectLog.entity.FaceDetectLogAiCamEntity;
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.mobile.AppAiCamService;
import com.ycwl.basic.service.pc.FaceDetectLogAiCamService;
import com.ycwl.basic.service.pc.FaceService;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.utils.JacksonUtil;
import com.ycwl.basic.utils.SnowFlakeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

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

/**
 * AI相机相关服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AppAiCamServiceImpl implements AppAiCamService {

    private final FaceDetectLogAiCamMapper faceDetectLogAiCamMapper;
    private final SourceMapper sourceMapper;
    private final FaceMapper faceMapper;
    private final DeviceRepository deviceRepository;
    private final FaceSampleMapper faceSampleMapper;

    private static final float DEFAULT_SCORE_THRESHOLD = 0.8f;
    private static final int DEFAULT_PHOTO_LIMIT = 10;
    private static final int AI_CAM_SOURCE_TYPE = 3;
    private final FaceService faceService;
    private final FaceDetectLogAiCamService faceDetectLogAiCamService;
    private final ScenicService scenicService;
    private final ScenicRepository scenicRepository;

    @Override
    public List<GoodsDetailVO> getAiCamGoodsByFaceId(Long faceId) {
        // 1. 查询该faceId的所有识别记录
        List<FaceDetectLogAiCamEntity> detectLogs = faceDetectLogAiCamMapper.listByFaceId(faceId);
        if (detectLogs == null || detectLogs.isEmpty()) {
            return Collections.emptyList();
        }

        // 2. 按设备分组并根据设备配置过滤faceSampleId
        Map<Long, List<Long>> deviceFaceSampleMap = new LinkedHashMap<>();

        // 按设备分组识别记录
        Map<Long, List<FaceDetectLogAiCamEntity>> deviceLogsMap = detectLogs.stream()
            .collect(Collectors.groupingBy(FaceDetectLogAiCamEntity::getDeviceId));

        // 遍历每个设备的识别记录
        for (Map.Entry<Long, List<FaceDetectLogAiCamEntity>> entry : deviceLogsMap.entrySet()) {
            Long deviceId = entry.getKey();
            List<FaceDetectLogAiCamEntity> deviceLogs = entry.getValue();

            // 获取设备配置
            DeviceConfigManager configManager = deviceRepository.getDeviceConfigManager(deviceId);

            // 获取该设备的分数阈值(百分制,需要转换为0-1)
            float scoreThreshold = DEFAULT_SCORE_THRESHOLD;
            if (configManager != null) {
                Float thresholdPercent = configManager.getFloat("ai_cam_face_score_threshold");
                if (thresholdPercent != null) {
                    scoreThreshold = thresholdPercent / 100.0f;
                    log.debug("设备{}使用配置的分数阈值: {}% ({})", deviceId, thresholdPercent, scoreThreshold);
                }
            }

            // 获取该设备的照片数量限制
            int photoLimit = DEFAULT_PHOTO_LIMIT;
            if (configManager != null) {
                Integer limit = configManager.getInteger("ai_cam_photo_limit");
                if (limit != null && limit > 0) {
                    photoLimit = limit;
                    log.debug("设备{}使用配置的照片限制: {}", deviceId, photoLimit);
                }
            }

            // 获取该设备的时间范围限制(分钟)
            Integer timeRangeMin = null;
            if (configManager != null) {
                Integer range = configManager.getInteger("ai_cam_time_range_min");
                if (range != null && range > 0) {
                    timeRangeMin = range;
                    log.debug("设备{}使用配置的时间范围: {}分钟", deviceId, timeRangeMin);
                }
            }

            // 收集该设备符合阈值的faceSampleId,同时记录分数和时间信息用于后续过滤
            class DetectResult {
                Long faceSampleId;
                Float score;
                Date detectTime;

                DetectResult(Long faceSampleId, Float score, Date detectTime) {
                    this.faceSampleId = faceSampleId;
                    this.score = score;
                    this.detectTime = detectTime;
                }
            }

            List<DetectResult> detectResults = new ArrayList<>();
            for (FaceDetectLogAiCamEntity detectLog : deviceLogs) {
                if (detectLog.getMatchRawResult() == null) {
                    continue;
                }
                try {
                    SearchFaceResp resp = JacksonUtil.parseObject(detectLog.getMatchRawResult(), SearchFaceResp.class);
                    if (resp != null && resp.getResult() != null) {
                        for (SearchFaceResultItem item : resp.getResult()) {
                            // 使用设备配置的分数阈值
                            if (item.getScore() != null && item.getScore() >= scoreThreshold && item.getExtData() != null) {
                                try {
                                    Long faceSampleId = Long.parseLong(item.getExtData());
                                    detectResults.add(new DetectResult(
                                        faceSampleId,
                                        item.getScore(),
                                        detectLog.getCreateTime()
                                    ));
                                } catch (NumberFormatException e) {
                                    log.warn("解析faceSampleId失败: extData={}", item.getExtData());
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("解析matchRawResult失败: logId={}", detectLog.getId(), e);
                }
            }

            // 应用照片数量限制(保留前N个)
            if (detectResults.size() > photoLimit) {
                log.debug("设备{}的照片数量{}超过限制{},截取前{}张",
                    deviceId, detectResults.size(), photoLimit, photoLimit);
                detectResults = detectResults.subList(0, photoLimit);
            }

            // 应用时间范围限制
            List<Long> deviceFaceSampleIds;
            if (timeRangeMin != null && !detectResults.isEmpty()) {
                // 找到分数最高的照片
                DetectResult highestScoreResult = detectResults.stream()
                    .max(Comparator.comparing(r -> r.score))
                    .orElse(null);

                if (highestScoreResult != null && highestScoreResult.detectTime != null) {
                    Date baseTime = highestScoreResult.detectTime;
                    long halfRangeMillis = (long) timeRangeMin * 60 * 1000 / 2;
                    Date startTime = new Date(baseTime.getTime() - halfRangeMillis);
                    Date endTime = new Date(baseTime.getTime() + halfRangeMillis);

                    // 过滤出时间范围内的照片
                    List<DetectResult> filteredResults = detectResults.stream()
                        .filter(r -> r.detectTime != null
                            && !r.detectTime.before(startTime)
                            && !r.detectTime.after(endTime))
                        .collect(Collectors.toList());

                    log.debug("设备{}应用时间范围{}分钟过滤: {}张 -> {}张 (基准时间: {})",
                        deviceId, timeRangeMin, detectResults.size(), filteredResults.size(), baseTime);

                    deviceFaceSampleIds = filteredResults.stream()
                        .map(r -> r.faceSampleId)
                        .collect(Collectors.toList());
                } else {
                    // 没有时间信息,不过滤
                    deviceFaceSampleIds = detectResults.stream()
                        .map(r -> r.faceSampleId)
                        .collect(Collectors.toList());
                }
            } else {
                // 不限制时间范围
                deviceFaceSampleIds = detectResults.stream()
                    .map(r -> r.faceSampleId)
                    .collect(Collectors.toList());
            }

            if (!deviceFaceSampleIds.isEmpty()) {
                deviceFaceSampleMap.put(deviceId, deviceFaceSampleIds);
            }
        }

        // 3. 合并所有设备的faceSampleId(去重)
        Set<Long> faceSampleIds = new HashSet<>();
        for (List<Long> ids : deviceFaceSampleMap.values()) {
            faceSampleIds.addAll(ids);
        }

        if (faceSampleIds.isEmpty()) {
            log.debug("没有符合条件的faceSampleId, faceId={}", faceId);
            return Collections.emptyList();
        }

        log.info("人脸{}在{}个设备上识别到{}个不重复的faceSampleId",
            faceId, deviceFaceSampleMap.size(), faceSampleIds.size());

        // 4. 根据faceSampleId列表查询type=3的source记录
        List<SourceEntity> sources = sourceMapper.listByFaceSampleIdsAndType(
            new ArrayList<>(faceSampleIds), AI_CAM_SOURCE_TYPE
        );

        if (sources == null || sources.isEmpty()) {
            log.debug("未找到type=3的source记录, faceId={}", faceId);
            return Collections.emptyList();
        }

        log.info("查询到{}条AI相机图像记录, faceId={}", sources.size(), faceId);

        // 5. 查询Face信息以获取scenicId
        FaceEntity face = faceMapper.get(faceId);
        if (face == null) {
            log.warn("Face不存在: faceId={}", faceId);
            return Collections.emptyList();
        }

        // 6. 转换为GoodsDetailVO
        return sources.stream().map(source -> {
            GoodsDetailVO vo = new GoodsDetailVO();
            vo.setFaceId(faceId);
            vo.setScenicId(face.getScenicId());
            vo.setGoodsType(2); // 2表示原素材
            vo.setGoodsId(source.getId());
            vo.setUrl(source.getUrl());
            vo.setVideoUrl(source.getVideoUrl());
            vo.setCreateTime(source.getCreateTime());
            vo.setIsBuy(source.getIsBuy() != null ? source.getIsBuy() : 0);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public int addMemberSourceRelations(Long faceId, List<Long> sourceIds) {
        if (sourceIds == null || sourceIds.isEmpty()) {
            return 0;
        }

        // 查询Face信息
        FaceEntity face = faceMapper.get(faceId);
        if (face == null) {
            throw new IllegalArgumentException("Face不存在: faceId=" + faceId);
        }

        if (face.getMemberId() == null) {
            throw new IllegalArgumentException("Face未关联会员: faceId=" + faceId);
        }

        // 在删除之前，先查询已有的免费记录
        List<MemberSourceEntity> existingFreeRelations = sourceMapper.listByFaceRelation(faceId, AI_CAM_SOURCE_TYPE);
        Set<Long> existingFreeSourceIds = existingFreeRelations.stream()
            .filter(r -> r.getIsFree() != null && r.getIsFree() == 1)
            .map(MemberSourceEntity::getSourceId)
            .collect(Collectors.toSet());
        boolean hasGivenFree = !existingFreeSourceIds.isEmpty();

        // 删除该faceId对应的旧的type=3关系
        int deleted = sourceMapper.deleteRelationsByFaceIdAndType(faceId, AI_CAM_SOURCE_TYPE);
        log.info("删除faceId={}的旧AI相机关联记录: {}条", faceId, deleted);

        // 获取景区配置中的免费照片数量
        int freePhotoCount = 0;
        if (!hasGivenFree) {
            try {
                ScenicConfigManager configManager =
                    scenicRepository.getScenicConfigManager(face.getScenicId());
                if (configManager != null) {
                    Integer aiCamFreeNum = configManager.getInteger("ai_cam_free_num");
                    if (aiCamFreeNum != null && aiCamFreeNum > 0) {
                        freePhotoCount = aiCamFreeNum;
                        log.info("景区{}配置免费赠送{}张AI相机照片", face.getScenicId(), freePhotoCount);
                    }
                }
            } catch (Exception e) {
                log.error("获取景区配置失败", e);
            }
        }

        // 如果需要赠送免费照片，随机选择
        Set<Long> freeSourceIds = new HashSet<>(existingFreeSourceIds);
        if (!hasGivenFree && freePhotoCount > 0) {
            List<Long> shuffledIds = new ArrayList<>(sourceIds);
            Collections.shuffle(shuffledIds);
            int actualFreeCount = Math.min(freePhotoCount, shuffledIds.size());
            freeSourceIds.addAll(shuffledIds.subList(0, actualFreeCount));
            log.info("为faceId={}随机赠送{}张免费照片", faceId, actualFreeCount);
        } else if (hasGivenFree) {
            log.info("faceId={}已赠送过免费照片，保留{}张原有免费照片", faceId, existingFreeSourceIds.size());
        }

        // 构建MemberSourceEntity列表
        List<MemberSourceEntity> relations = sourceIds.stream().map(sourceId -> {
            MemberSourceEntity entity = new MemberSourceEntity();
            entity.setMemberId(face.getMemberId());
            entity.setScenicId(face.getScenicId());
            entity.setFaceId(faceId);
            entity.setSourceId(sourceId);
            entity.setType(AI_CAM_SOURCE_TYPE);
            entity.setIsBuy(0);
            entity.setIsFree(freeSourceIds.contains(sourceId) ? 1 : 0);
            return entity;
        }).collect(Collectors.toList());

        // 批量插入
        int inserted = sourceMapper.addRelations(relations);
        log.info("为faceId={}添加新AI相机关联记录: {}条 (其中免费: {}张)", faceId, inserted, freeSourceIds.size());

        return inserted;
    }

    @Override
    public FaceRecognizeResp useSample(Long userId, Long faceSampleId) {
        // 1. 查询 faceSample 获取其 URL
        FaceSampleEntity faceSample = faceSampleMapper.getEntity(faceSampleId);
        if (faceSample == null) {
            throw new BaseException("人脸样本不存在");
        }

        String faceUrl = faceSample.getFaceUrl();
        if (StringUtils.isBlank(faceUrl)) {
            throw new BaseException("人脸样本URL为空");
        }

        Long scenicId = faceSample.getScenicId();

        // 2. 检查face数据库中有没有同用户、同URL的face记录
        FaceEntity existingFace = null;
        Long faceId = null;

        // 查询该用户在该景区的所有人脸记录
        List<FaceRespVO> userFaces = faceMapper.listByScenicAndUserId(scenicId, userId);

        // 查找是否存在相同URL的记录
        for (FaceRespVO faceResp : userFaces) {
            if (faceUrl.equals(faceResp.getFaceUrl())) {
                existingFace = faceMapper.get(faceResp.getId());
                faceId = existingFace.getId();
                break;
            }
        }

        // 3. 如果不存在,则新建一个face记录
        if (existingFace == null) {
            faceId = SnowFlakeUtil.getLongId();
            FaceEntity newFace = new FaceEntity();
            newFace.setId(faceId);
            newFace.setCreateAt(new Date());
            newFace.setScenicId(scenicId);
            newFace.setMemberId(userId);
            newFace.setFaceUrl(faceUrl);
            faceMapper.add(newFace);

            log.info("创建新的face记录, userId: {}, faceSampleId: {}, faceId: {}, faceUrl: {}",
                    userId, faceSampleId, faceId, faceUrl);
        } else {
            log.info("使用已存在的face记录, userId: {}, faceSampleId: {}, faceId: {}, faceUrl: {}",
                    userId, faceSampleId, faceId, faceUrl);
        }

        // 4. 查询对应的 type=3 的 source 记录并自动添加关联
        SourceEntity sourceEntity = sourceMapper.getBySampleIdAndType(faceSampleId, AI_CAM_SOURCE_TYPE);
        if (sourceEntity != null && existingFace == null) {
            // 检查是否已存在该source的关联
            List<GoodsDetailVO> existingGoods = getAiCamGoodsByFaceId(faceId);
            boolean alreadyExists = existingGoods.stream()
                    .anyMatch(item -> Objects.equals(item.getGoodsId(), sourceEntity.getId()));

            if (!alreadyExists) {
                // 添加关联
                MemberSourceEntity relation = new MemberSourceEntity();
                relation.setMemberId(userId);
                relation.setScenicId(scenicId);
                relation.setFaceId(faceId);
                relation.setSourceId(sourceEntity.getId());
                relation.setType(AI_CAM_SOURCE_TYPE);
                relation.setIsBuy(0);
                relation.setIsFree(0);
                sourceMapper.addRelations(Collections.singletonList(relation));
                log.info("自动添加AI相机照片关联: userId={}, faceId={}, sourceId={}",
                        userId, faceId, sourceEntity.getId());
            }
        }

        // 5. 返回结果
        FaceRecognizeResp resp = new FaceRecognizeResp();
        resp.setUrl(faceUrl);
        resp.setFaceId(faceId);
        resp.setScenicId(scenicId);
        IFaceBodyAdapter faceBodyAdapter = scenicService.getScenicFaceBodyAdapter(scenicId);
        try {
            faceService.matchFaceId(faceId);
            faceDetectLogAiCamService.searchAndLog(scenicId, faceId, faceUrl, faceBodyAdapter);
        } catch (Exception e) {
            // 人脸匹配失败不可以阻止正常流程
            log.error("人脸匹配失败", e);
        }
        return resp;
    }
}
