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

import com.ycwl.basic.facebody.FaceBodyFactory;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.pay.PayFactory;
import com.ycwl.basic.pay.adapter.IPayAdapter;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.storage.exceptions.StorageUnsupportedException;
import com.ycwl.basic.integration.common.manager.ScenicConfigManager;
import com.ycwl.basic.util.TtlCacheMap;
import com.ycwl.basic.utils.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author：longbinbin
 * @Date：2024/12/3 15:25
 */
@Slf4j
@Service
public class ScenicServiceImpl implements ScenicService {
    @Autowired
    private ScenicRepository scenicRepository;
    
    // TTL缓存配置，默认10分钟过期
    private static final long DEFAULT_CACHE_TTL_MINUTES = 10;
    
    // 使用TTL缓存替代静态Map
    private static final TtlCacheMap<Long, IStorageAdapter> scenicStorageAdapterCache = 
        new TtlCacheMap<>(TimeUnit.MINUTES.toMillis(DEFAULT_CACHE_TTL_MINUTES));
    private static final TtlCacheMap<Long, IStorageAdapter> scenicTmpStorageAdapterCache = 
        new TtlCacheMap<>(TimeUnit.MINUTES.toMillis(DEFAULT_CACHE_TTL_MINUTES));
    private static final TtlCacheMap<Long, IStorageAdapter> scenicLocalStorageAdapterCache = 
        new TtlCacheMap<>(TimeUnit.MINUTES.toMillis(DEFAULT_CACHE_TTL_MINUTES));
    private static final TtlCacheMap<Long, IFaceBodyAdapter> scenicFaceBodyAdapterCache = 
        new TtlCacheMap<>(TimeUnit.MINUTES.toMillis(DEFAULT_CACHE_TTL_MINUTES));
    private static final TtlCacheMap<Long, IPayAdapter> scenicPayAdapterCache = 
        new TtlCacheMap<>(TimeUnit.MINUTES.toMillis(DEFAULT_CACHE_TTL_MINUTES));

    @Override
    @Deprecated
    public ApiResponse<List<ScenicV2DTO>> list(ScenicReqQuery scenicReqQuery) {
        return ApiResponse.success(scenicRepository.list(scenicReqQuery));
    }

    @Override
    public IStorageAdapter getScenicStorageAdapter(Long scenicId) {
        return scenicStorageAdapterCache.computeIfAbsent(scenicId, (key) -> {
            IStorageAdapter adapter;
            ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(scenicId);
            if (Strings.isNotBlank(scenicConfig.getString("store_type"))) {
                try {
                    adapter = StorageFactory.get(scenicConfig.getString("store_type"));
                    adapter.loadConfig(scenicConfig.getObject("store_config_json", Map.class));
                } catch (StorageUnsupportedException ignored) {
                    return StorageFactory.use("video");
                }
            } else {
                adapter = StorageFactory.use("video");
            }
            return adapter;
        });
    }
    @Override
    public IStorageAdapter getScenicTmpStorageAdapter(Long scenicId) {
        return scenicTmpStorageAdapterCache.computeIfAbsent(scenicId, (key) -> {
            IStorageAdapter adapter;
            ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(scenicId);
            if (Strings.isNotBlank(scenicConfig.getString("tmp_store_type"))) {
                try {
                    adapter = StorageFactory.get(scenicConfig.getString("tmp_store_type"));
                    adapter.loadConfig(scenicConfig.getObject("tmp_store_config_json", Map.class));
                } catch (StorageUnsupportedException ignored) {
                    return getScenicStorageAdapter(scenicId);
                }
            } else {
                return getScenicStorageAdapter(scenicId);
            }
            return adapter;
        });
    }
    @Override
    public IStorageAdapter getScenicLocalStorageAdapter(Long scenicId) {
        return scenicLocalStorageAdapterCache.computeIfAbsent(scenicId, (key) -> {
            IStorageAdapter adapter;
            ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(scenicId);
            if (Strings.isNotBlank(scenicConfig.getString("local_store_type"))) {
                try {
                    adapter = StorageFactory.get(scenicConfig.getString("local_store_type"));
                    adapter.loadConfig(scenicConfig.getObject("local_store_config_json", Map.class));
                } catch (StorageUnsupportedException ignored) {
                    return getScenicStorageAdapter(scenicId);
                }
            } else {
                return getScenicStorageAdapter(scenicId);
            }
            return adapter;
        });
    }

    @Override
    public IFaceBodyAdapter getScenicFaceBodyAdapter(Long scenicId) {
        return scenicFaceBodyAdapterCache.computeIfAbsent(scenicId, (key) -> {
            IFaceBodyAdapter adapter;
            ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(scenicId);
            if (Strings.isNotBlank(scenicConfig.getString("face_type"))) {
                adapter = FaceBodyFactory.getAdapter(scenicConfig.getString("face_type"));
                adapter.loadConfig(scenicConfig.getObject("face_config_json", Map.class));
            } else {
                adapter = FaceBodyFactory.use();
            }
            return adapter;
        });
    }

    @Override
    public IPayAdapter getScenicPayAdapter(Long scenicId) {
        return scenicPayAdapterCache.computeIfAbsent(scenicId, (key) -> {
            IPayAdapter adapter;
            ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(scenicId);
            if (Strings.isNotBlank(scenicConfig.getString("pay_type"))) {
                adapter = PayFactory.getAdapter(scenicConfig.getString("pay_type"));
                adapter.loadConfig(scenicConfig.getObject("pay_config_json", Map.class));
            } else {
                adapter = PayFactory.use();
            }
            return adapter;
        });
    }
    
    // ==================== 缓存管理方法 ====================
    
    /**
     * 清除指定景区的所有适配器缓存
     * 
     * @param scenicId 景区ID
     */
    public void clearScenicAdapterCache(Long scenicId) {
        log.info("清除景区 {} 的所有适配器缓存", scenicId);
        scenicStorageAdapterCache.remove(scenicId);
        scenicTmpStorageAdapterCache.remove(scenicId);
        scenicLocalStorageAdapterCache.remove(scenicId);
        scenicFaceBodyAdapterCache.remove(scenicId);
        scenicPayAdapterCache.remove(scenicId);
    }
    
    /**
     * 清除所有适配器缓存
     */
    public void clearAllAdapterCache() {
        log.info("清除所有适配器缓存");
        scenicStorageAdapterCache.clear();
        scenicTmpStorageAdapterCache.clear();
        scenicLocalStorageAdapterCache.clear();
        scenicFaceBodyAdapterCache.clear();
        scenicPayAdapterCache.clear();
    }
    
    /**
     * 手动触发过期缓存清理
     * 
     * @return 清理的过期缓存项总数
     */
    public int cleanupExpiredCache() {
        log.info("手动触发过期缓存清理");
        int totalCleaned = 0;
        totalCleaned += scenicStorageAdapterCache.cleanupExpired();
        totalCleaned += scenicTmpStorageAdapterCache.cleanupExpired();
        totalCleaned += scenicLocalStorageAdapterCache.cleanupExpired();
        totalCleaned += scenicFaceBodyAdapterCache.cleanupExpired();
        totalCleaned += scenicPayAdapterCache.cleanupExpired();
        log.info("清理了 {} 个过期缓存项", totalCleaned);
        return totalCleaned;
    }
    
    /**
     * 获取缓存统计信息
     * 
     * @return 缓存统计信息
     */
    public String getCacheStats() {
        StringBuilder stats = new StringBuilder();
        stats.append("=== ScenicServiceImpl 缓存统计信息 ===\n");
        stats.append("Storage Adapter Cache: ").append(scenicStorageAdapterCache.getStats()).append("\n");
        stats.append("Tmp Storage Adapter Cache: ").append(scenicTmpStorageAdapterCache.getStats()).append("\n");
        stats.append("Local Storage Adapter Cache: ").append(scenicLocalStorageAdapterCache.getStats()).append("\n");
        stats.append("FaceBody Adapter Cache: ").append(scenicFaceBodyAdapterCache.getStats()).append("\n");
        stats.append("Pay Adapter Cache: ").append(scenicPayAdapterCache.getStats()).append("\n");
        return stats.toString();
    }
    
    /**
     * 重置所有缓存统计信息
     */
    public void resetCacheStats() {
        log.info("重置所有缓存统计信息");
        scenicStorageAdapterCache.resetStats();
        scenicTmpStorageAdapterCache.resetStats();
        scenicLocalStorageAdapterCache.resetStats();
        scenicFaceBodyAdapterCache.resetStats();
        scenicPayAdapterCache.resetStats();
    }
    
    /**
     * 获取指定景区缓存的剩余TTL时间
     * 
     * @param scenicId 景区ID
     * @return 各类型适配器缓存的剩余TTL时间（毫秒）
     */
    public String getScenicCacheTtl(Long scenicId) {
        StringBuilder ttlInfo = new StringBuilder();
        ttlInfo.append("景区 ").append(scenicId).append(" 缓存TTL信息:\n");
        ttlInfo.append("Storage: ").append(scenicStorageAdapterCache.getRemainTtl(scenicId)).append("ms\n");
        ttlInfo.append("TmpStorage: ").append(scenicTmpStorageAdapterCache.getRemainTtl(scenicId)).append("ms\n");
        ttlInfo.append("LocalStorage: ").append(scenicLocalStorageAdapterCache.getRemainTtl(scenicId)).append("ms\n");
        ttlInfo.append("FaceBody: ").append(scenicFaceBodyAdapterCache.getRemainTtl(scenicId)).append("ms\n");
        ttlInfo.append("Pay: ").append(scenicPayAdapterCache.getRemainTtl(scenicId)).append("ms\n");
        return ttlInfo.toString();
    }
}
