using DramaLing.Api.Models.DTOs;
using DramaLing.Api.Services.Caching;
using System.Security.Cryptography;
using System.Text;
using System.Diagnostics;

namespace DramaLing.Api.Services;

/// <summary>
/// 分析服務實作，整合快取和 AI 服務
/// </summary>
public class AnalysisService : IAnalysisService
{
    private readonly IGeminiService _geminiService;
    private readonly ICacheService _cacheService;
    private readonly ILogger<AnalysisService> _logger;
    private static readonly AnalysisStats _stats = new();

    public AnalysisService(
        IGeminiService geminiService,
        ICacheService cacheService,
        ILogger<AnalysisService> logger)
    {
        _geminiService = geminiService ?? throw new ArgumentNullException(nameof(geminiService));
        _cacheService = cacheService ?? throw new ArgumentNullException(nameof(cacheService));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<SentenceAnalysisData> AnalyzeSentenceAsync(string inputText, AnalysisOptions options)
    {
        var stopwatch = Stopwatch.StartNew();
        var cacheKey = GenerateCacheKey(inputText, options);

        try
        {
            _logger.LogInformation("Starting analysis for text: {Text} (cache key: {CacheKey})",
                inputText.Substring(0, Math.Min(50, inputText.Length)), cacheKey);

            // 1. 快取檢查
            var cachedResult = await _cacheService.GetAsync<SentenceAnalysisData>(cacheKey);
            if (cachedResult != null)
            {
                stopwatch.Stop();
                _stats.CachedAnalyses++;
                _stats.TotalAnalyses++;

                _logger.LogInformation("Cache hit for analysis in {ElapsedMs}ms", stopwatch.ElapsedMilliseconds);
                return cachedResult;
            }

            // 2. 快取未命中，執行 AI 分析
            _logger.LogInformation("Cache miss, calling AI service");
            var analysisResult = await _geminiService.AnalyzeSentenceAsync(inputText, options);

            // 3. 存入快取 (三層快取會自動同步到資料庫)
            await _cacheService.SetAsync(cacheKey, analysisResult, TimeSpan.FromHours(2));

            // 4. 更新統計
            stopwatch.Stop();
            _stats.TotalAnalyses++;
            _stats.LastAnalysisAt = DateTime.UtcNow;
            UpdateAverageResponseTime((int)stopwatch.ElapsedMilliseconds);

            _logger.LogInformation("AI analysis completed and cached in {ElapsedMs}ms", stopwatch.ElapsedMilliseconds);

            return analysisResult;
        }
        catch (Exception ex)
        {
            stopwatch.Stop();
            _logger.LogError(ex, "Error in analysis service for text: {Text}", inputText);
            throw;
        }
    }

    public async Task<bool> HasCachedAnalysisAsync(string inputText, AnalysisOptions options)
    {
        try
        {
            var cacheKey = GenerateCacheKey(inputText, options);
            return await _cacheService.ExistsAsync(cacheKey);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error checking cache existence");
            return false;
        }
    }

    public async Task<bool> ClearAnalysisCacheAsync(string inputText, AnalysisOptions options)
    {
        try
        {
            var cacheKey = GenerateCacheKey(inputText, options);
            return await _cacheService.RemoveAsync(cacheKey);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error clearing analysis cache");
            return false;
        }
    }

    public Task<AnalysisStats> GetAnalysisStatsAsync()
    {
        _stats.ProviderUsageStats["Gemini"] = _stats.TotalAnalyses - _stats.CachedAnalyses;
        return Task.FromResult(_stats);
    }

    #region 私有方法

    private string GenerateCacheKey(string inputText, AnalysisOptions options)
    {
        // 根據輸入和選項生成穩定的快取鍵
        var optionsString = $"{options.IncludeGrammarCheck}_{options.IncludeVocabularyAnalysis}_{options.IncludeIdiomDetection}";
        var combinedInput = $"{inputText}_{optionsString}";

        using var sha256 = SHA256.Create();
        var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combinedInput));
        var hash = Convert.ToHexString(hashBytes)[..16];

        return $"analysis:{hash}";
    }

    private void UpdateAverageResponseTime(int responseTimeMs)
    {
        if (_stats.AverageResponseTimeMs == 0)
        {
            _stats.AverageResponseTimeMs = responseTimeMs;
        }
        else
        {
            _stats.AverageResponseTimeMs = (_stats.AverageResponseTimeMs + responseTimeMs) / 2;
        }
    }

    #endregion
}