package com.ycwl.basic.repository;

import com.ycwl.basic.image.enhancer.entity.BceEnhancerConfig;
import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
import com.ycwl.basic.image.pipeline.enums.ImageSource;
import com.ycwl.basic.image.pipeline.enums.ImageType;
import com.ycwl.basic.image.pipeline.enums.PipelineScene;
import com.ycwl.basic.image.pipeline.stages.*;
import com.ycwl.basic.integration.common.manager.ScenicConfigManager;
import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
import com.ycwl.basic.pipeline.core.Pipeline;
import com.ycwl.basic.pipeline.core.PipelineBuilder;
import com.ycwl.basic.pricing.dto.VoucherInfo;
import com.ycwl.basic.pricing.enums.VoucherDiscountType;
import com.ycwl.basic.pricing.service.IVoucherService;
import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.storage.exceptions.StorageUnsupportedException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Slf4j
@Component
public class SourceRepository {
    private static final ExecutorService IMAGE_PROCESS_EXECUTOR = Executors.newFixedThreadPool(
            Runtime.getRuntime().availableProcessors(),
            runnable -> {
                Thread thread = new Thread(runnable);
                thread.setName("ai-cam-image-processor-" + thread.threadId());
                thread.setDaemon(true);
                return thread;
            }
    );

    @Autowired
    private SourceMapper sourceMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private FaceRepository faceRepository;
    @Autowired
    private TemplateRepository templateRepository;
    @Autowired
    private DeviceRepository deviceRepository;
    @Autowired
    private MemberRelationRepository memberRelationRepository;
    @Autowired
    private com.ycwl.basic.biz.FaceStatusManager faceStatusManager;
    @Autowired
    private ScenicRepository scenicRepository;

    public void addSource(SourceEntity source) {
        sourceMapper.add(source);
    }

    public void setUserIsBuyItem(Long memberId, int type, Long faceId, Long orderId) {
        // 如果是AI相机照片类型(type=13),需要进行图像超分和增强处理
        boolean needsImageProcessing = (type == 13 || type == 3);

        if (type == 13) {
            type = 3; // compact
        }

        MemberSourceEntity memberSource = new MemberSourceEntity();
        memberSource.setMemberId(memberId);
        memberSource.setFaceId(faceId);
        memberSource.setType(type);
        memberSource.setOrderId(orderId);
        memberSource.setIsBuy(1);
        sourceMapper.updateRelation(memberSource);
        memberRelationRepository.clearSCacheByFace(faceId);
        faceStatusManager.invalidatePuzzleSourceVersion(faceId);

        // 如果需要图像处理,对该faceId下的所有type=3的照片进行处理
        if (needsImageProcessing) {
            processAiCamImages(faceId);
        }

        redisTemplate.delete("order_content_not_downloadable_" + orderId);
    }

    /**
     * 处理AI相机照片 - 对照片进行超分辨率和增强处理
     *
     * @param faceId 人脸ID
     */
    private void processAiCamImages(Long faceId) {
        try {
            // 1. 获取该faceId下所有type=3的照片
            List<SourceEntity> aiCamImages = sourceMapper.listAiCamImageByFaceRelation(faceId);

            if (aiCamImages == null || aiCamImages.isEmpty()) {
                log.info("没有找到需要处理的AI相机照片, faceId: {}", faceId);
                return;
            }

            log.info("开始处理AI相机照片, faceId: {}, 照片数量: {}", faceId, aiCamImages.size());

            // 2. 构建图像处理配置
            BceEnhancerConfig config = buildEnhancerConfig();

            // 3. 并发处理所有照片
            List<CompletableFuture<Void>> futures = aiCamImages.stream()
                    .map(source -> CompletableFuture.runAsync(() -> {
                        try {
                            processSingleAiCamImage(source, config);
                        } catch (Exception e) {
                            log.error("处理AI相机照片失败, sourceId: {}, error: {}", source.getId(), e.getMessage(), e);
                            // 继续处理下一张照片,不中断整个流程
                        }
                    }, IMAGE_PROCESS_EXECUTOR))
                    .collect(Collectors.toList());

            // 4. 等待所有任务完成
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

            log.info("AI相机照片处理完成, faceId: {}", faceId);

        } catch (Exception e) {
            log.error("处理AI相机照片整体流程失败, faceId: {}, error: {}", faceId, e.getMessage(), e);
            // 即使处理失败也不抛出异常,不影响订单购买流程
        }
    }

    /**
     * 处理单张AI相机照片
     *
     * @param source 原始照片
     * @param config 增强配置
     */
    private void processSingleAiCamImage(SourceEntity source, BceEnhancerConfig config) {
        // 1. 创建处理上下文
        PhotoProcessContext context = PhotoProcessContext.builder()
                .processId("aicam-" + source.getId())
                .originalUrl(source.getUrl())
                .scenicId(source.getScenicId())
                .imageType(ImageType.NORMAL_PHOTO)
                .source(ImageSource.IPC)
                .scene(PipelineScene.AI_CAM_ENHANCE)
                .build();
        context.enableStage("image_sr");
        context.enableStage("image_enhance");
        ScenicConfigManager configManager = scenicRepository.getScenicConfigManager(source.getScenicId());
        IStorageAdapter adapter;
        try {
            adapter = StorageFactory.get(configManager.getString("store_type"));
            adapter.loadConfig(configManager.getObject("store_config_json", Map.class));
        } catch (StorageUnsupportedException ignored) {
            adapter = StorageFactory.use("assets-ext");
        }
        context.setStorageAdapter(adapter);

        // 2. 设置结果URL回调 - 更新source记录
        context.setResultUrlCallback(newUrl -> {
            SourceEntity updateEntity = new SourceEntity();
            updateEntity.setId(source.getId());
            updateEntity.setUrl(newUrl);
            sourceMapper.update(updateEntity);
            log.info("已更新AI相机照片URL, sourceId: {}, oldUrl: {}, newUrl: {}",
                    source.getId(), source.getUrl(), newUrl);
        });

        // 3. 构建处理管线: 下载 -> 超分 -> 增强 -> 上传 -> 清理
        Pipeline<PhotoProcessContext> pipeline = new PipelineBuilder<PhotoProcessContext>("AiCamEnhancePipeline")
                .addStage(new DownloadStage())              // 下载原图
//                .addStage(new ImageSRStage(config))          // 图像超分辨率
                .addStage(new ImageEnhanceStage(config))     // 图像增强
                .addStage(new UploadStage())                 // 上传处理后的图片
                .addStage(new CleanupStage())                // 清理临时文件
                .build();

        // 4. 执行管线
        boolean success = pipeline.execute(context);

        if (!success) {
            log.warn("AI相机照片处理管线执行失败, sourceId: {}", source.getId());
        }
    }

    /**
     * 构建图像增强配置
     *
     * @return 增强配置
     */
    private BceEnhancerConfig buildEnhancerConfig() {
        BceEnhancerConfig config = new BceEnhancerConfig();

        // 尝试从环境变量读取
        String appId = System.getenv("BCE_IMAGE_APP_ID");
        String apiKey = System.getenv("BCE_IMAGE_API_KEY");
        String secretKey = System.getenv("BCE_IMAGE_SECRET_KEY");

        // 如果环境变量没有配置,使用默认值(与PrinterServiceImpl保持一致)
        if (appId == null || appId.isBlank()) {
            appId = "119554288";
        }
        if (apiKey == null || apiKey.isBlank()) {
            apiKey = "OX6QoijgKio3eVtA0PiUVf7f";
        }
        if (secretKey == null || secretKey.isBlank()) {
            secretKey = "dYatXReVriPeiktTjUblhfubpcmYfuMk";
        }

        config.setAppId(appId);
        config.setApiKey(apiKey);
        config.setSecretKey(secretKey);
        config.setQps(1.0f);

        return config;
    }

    public void setUserNotBuyItem(Long memberId, int type, Long faceId) {
        MemberSourceEntity memberSource = new MemberSourceEntity();
        memberSource.setMemberId(memberId);
        memberSource.setFaceId(faceId);
        memberSource.setType(type);
        memberSource.setOrderId(null);
        memberSource.setIsBuy(0);
        sourceMapper.updateRelation(memberSource);
        memberRelationRepository.clearSCacheByFace(faceId);
        faceStatusManager.invalidatePuzzleSourceVersion(faceId);
    }

    public void setUserIsBuyItemBySourceId(Long memberId, Long sourceId, Long faceId, Long orderId) {
        MemberSourceEntity memberSource = new MemberSourceEntity();
        memberSource.setMemberId(memberId);
        memberSource.setSourceId(sourceId);
        memberSource.setOrderId(orderId);
        memberSource.setIsBuy(1);
        sourceMapper.updateRelationBySourceId(memberSource);
        memberRelationRepository.clearSCacheByFace(faceId);
        faceStatusManager.invalidatePuzzleSourceVersion(faceId);
    }

    public void setUserNotBuyItemBySourceId(Long memberId, Long sourceId, Long faceId) {
        MemberSourceEntity memberSource = new MemberSourceEntity();
        memberSource.setMemberId(memberId);
        memberSource.setSourceId(sourceId);
        memberSource.setOrderId(null);
        memberSource.setIsBuy(0);
        sourceMapper.updateRelationBySourceId(memberSource);
        memberRelationRepository.clearSCacheByFace(faceId);
        faceStatusManager.invalidatePuzzleSourceVersion(faceId);
    }

    public SourceEntity getSource(Long id) {
        return sourceMapper.getEntity(id);
    }

    public Map<String, List<SourceEntity>> getTaskParams(Long faceId, Long templateId) {
        FaceEntity face = faceRepository.getFace(faceId);
        if (face == null) {
            log.info("getTaskParams: faceId:{} is not exist", faceId);
            return Map.of();
        }

        List<SourceEntity> videoSourceList = sourceMapper.listVideoByScenicFaceRelation(face.getScenicId(), faceId);
        Map<String, List<SourceEntity>> sourcesMap = videoSourceList.stream()
                .peek(item -> item.setUrl(item.getVideoUrl()))
                .filter(item -> item.getDeviceId() != null)
                .filter(item -> {
                    DeviceEntity device = deviceRepository.getDevice(item.getDeviceId());
                    if (device == null) {
                        log.info("getTaskParams: deviceId:{} is not exist", item.getDeviceId());
                        return false;
                    }
                    return Integer.valueOf(1).equals(device.getStatus());
                })
                .collect(Collectors.groupingBy(item -> item.getDeviceId().toString()));

        if (sourcesMap.isEmpty()) {
            log.info("getTaskParams: 没有视频源，templateId: {}", templateId);
            return Map.of();
        }

        List<String> templatePlaceholder = templateRepository.getTemplatePlaceholder(templateId);
        if (templatePlaceholder.stream().distinct().count() == templatePlaceholder.size()) {
            sourcesMap.forEach((key, value) -> {
                value.removeIf(item -> !value.getFirst().equals(item));
            });
        } else {
            // 找出重复的templatePlaceholder，修改对应的sourceMap[key]中的list顺序为倒序
            Map<String, Long> placeholderCounts = templatePlaceholder.stream()
                    .collect(Collectors.groupingBy(placeholder -> placeholder, Collectors.counting()));
            
            placeholderCounts.entrySet().stream()
                    .filter(entry -> entry.getValue() > 1)
                    .map(Map.Entry::getKey)
                    .forEach(duplicatePlaceholder -> {
                        // 对于重复的占位符，找到对应的设备ID并倒序sourceMap中的列表
                        if (sourcesMap.containsKey(duplicatePlaceholder)) {
                            List<SourceEntity> sourceList = sourcesMap.get(duplicatePlaceholder);
                            java.util.Collections.reverse(sourceList);
                        }
                    });
        }

        boolean hasPPlaceholder = templatePlaceholder.stream().anyMatch(placeholder -> placeholder.startsWith("P"));
        if (hasPPlaceholder) {
            List<SourceEntity> imageSourceList = sourceMapper.listImageSourcesByFaceId(faceId);
            if (!imageSourceList.isEmpty()) {
                Map<String, List<SourceEntity>> imageSourceMap = imageSourceList.stream()
                        .peek(item -> item.setUrl(item.getUrl()))
                        .filter(item -> item.getDeviceId() != null)
                        .filter(item -> {
                            DeviceEntity device = deviceRepository.getDevice(item.getDeviceId());
                            if (device == null) {
                                return false;
                            }
                            return Integer.valueOf(1).equals(device.getStatus());
                        })
                        .collect(Collectors.groupingBy(item -> "P" + item.getDeviceId().toString()));

                imageSourceMap.forEach((key, value) -> {
                    sourcesMap.merge(key, value, (existing, replacement) -> {
                        existing.addAll(replacement);
                        return existing;
                    });
                });
            }
        }

        return sourcesMap;
    }
}
