using DramaLing.Api.Models.DTOs;
using DramaLing.Api.Models.Configuration;
using Microsoft.Extensions.Options;
using System.Text.Json;
using System.Text;
using System.Diagnostics;

namespace DramaLing.Api.Services.AI;

/// <summary>
/// Google Gemini AI 提供商實作
/// </summary>
public class GeminiAIProvider : IAIProvider
{
    private readonly HttpClient _httpClient;
    private readonly ILogger<GeminiAIProvider> _logger;
    private readonly GeminiOptions _options;
    private AIProviderStats _stats;

    public GeminiAIProvider(HttpClient httpClient, IOptions<GeminiOptions> options, ILogger<GeminiAIProvider> logger)
    {
        _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _options = options.Value ?? throw new ArgumentNullException(nameof(options));

        _stats = new AIProviderStats();

        _httpClient.Timeout = TimeSpan.FromSeconds(_options.TimeoutSeconds);
        _httpClient.DefaultRequestHeaders.Add("User-Agent", "DramaLing/1.0");

        _logger.LogInformation("GeminiAIProvider initialized with model: {Model}, timeout: {Timeout}s",
            _options.Model, _options.TimeoutSeconds);
    }

    #region IAIProvider 屬性

    public string ProviderName => "Google Gemini";

    public bool IsAvailable => !string.IsNullOrEmpty(_options.ApiKey);

    public decimal CostPerRequest => 0.001m; // 大概每次請求成本

    public int MaxInputLength => _options.MaxOutputTokens / 4; // 粗略估計

    public int AverageResponseTimeMs => _stats.AverageResponseTimeMs;

    #endregion

    #region 核心功能

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

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

            var prompt = BuildAnalysisPrompt(inputText);
            var aiResponse = await CallGeminiAPIAsync(prompt);

            if (string.IsNullOrWhiteSpace(aiResponse))
            {
                throw new InvalidOperationException("Gemini API returned empty response");
            }

            var analysisData = ParseAIResponse(inputText, aiResponse);

            stopwatch.Stop();
            RecordSuccessfulRequest(stopwatch.ElapsedMilliseconds);

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

            return analysisData;
        }
        catch (Exception ex)
        {
            stopwatch.Stop();
            RecordFailedRequest(stopwatch.ElapsedMilliseconds);

            _logger.LogError(ex, "Error analyzing sentence: {Text}", inputText);
            throw;
        }
    }

    public async Task<AIProviderHealthStatus> CheckHealthAsync()
    {
        var stopwatch = Stopwatch.StartNew();

        try
        {
            var testPrompt = "Test health check prompt";
            var response = await CallGeminiAPIAsync(testPrompt);

            stopwatch.Stop();

            return new AIProviderHealthStatus
            {
                IsHealthy = !string.IsNullOrEmpty(response),
                CheckedAt = DateTime.UtcNow,
                ResponseTimeMs = (int)stopwatch.ElapsedMilliseconds
            };
        }
        catch (Exception ex)
        {
            stopwatch.Stop();

            return new AIProviderHealthStatus
            {
                IsHealthy = false,
                ErrorMessage = ex.Message,
                CheckedAt = DateTime.UtcNow,
                ResponseTimeMs = (int)stopwatch.ElapsedMilliseconds
            };
        }
    }

    public Task<AIProviderStats> GetStatsAsync()
    {
        return Task.FromResult(_stats);
    }

    #endregion

    #region 私有方法

    private string BuildAnalysisPrompt(string inputText)
    {
        return $@"You are an English learning assistant. Analyze this sentence and return ONLY a valid JSON response.

**Input Sentence**: ""{inputText}""

**Required JSON Structure:**
{{
  ""sentenceTranslation"": ""Traditional Chinese translation of the entire sentence"",
  ""hasGrammarErrors"": true/false,
  ""grammarCorrections"": [
    {{
      ""original"": ""incorrect text"",
      ""corrected"": ""correct text"",
      ""type"": ""error type (tense/subject-verb/preposition/word-order)"",
      ""explanation"": ""brief explanation in Traditional Chinese""
    }}
  ],
  ""vocabularyAnalysis"": {{
    ""word1"": {{
      ""word"": ""the word"",
      ""translation"": ""Traditional Chinese translation"",
      ""definition"": ""English definition"",
      ""partOfSpeech"": ""noun/verb/adjective/etc"",
      ""pronunciation"": ""/phonetic/"",
      ""difficultyLevel"": ""A1/A2/B1/B2/C1/C2"",
      ""frequency"": ""high/medium/low"",
      ""synonyms"": [""synonym1"", ""synonym2""],
      ""example"": ""example sentence"",
      ""exampleTranslation"": ""Traditional Chinese example translation""
    }}
  }},
  ""idioms"": [
    {{
      ""idiom"": ""idiomatic expression"",
      ""translation"": ""Traditional Chinese meaning"",
      ""definition"": ""English explanation"",
      ""pronunciation"": ""/phonetic notation/"",
      ""difficultyLevel"": ""A1/A2/B1/B2/C1/C2"",
      ""frequency"": ""high/medium/low"",
      ""synonyms"": [""synonym1"", ""synonym2""],
      ""example"": ""usage example"",
      ""exampleTranslation"": ""Traditional Chinese example""
    }}
  ]
}}

**Analysis Guidelines:**
1. **Grammar Check**: Detect tense errors, subject-verb agreement, preposition usage, word order
2. **Vocabulary Analysis**: Include ALL significant words (exclude articles: a, an, the)
3. **CEFR Levels**: Assign accurate A1-C2 levels for each word
4. **Idioms**: Identify any idiomatic expressions or phrasal verbs
5. **Translations**: Use Traditional Chinese (Taiwan standard)

**IMPORTANT**: Return ONLY the JSON object, no additional text or explanation.";
    }

    private async Task<string> CallGeminiAPIAsync(string prompt)
    {
        try
        {
            var requestBody = new
            {
                contents = new[]
                {
                    new
                    {
                        parts = new[]
                        {
                            new { text = prompt }
                        }
                    }
                },
                generationConfig = new
                {
                    temperature = _options.Temperature,
                    topK = 40,
                    topP = 0.95,
                    maxOutputTokens = _options.MaxOutputTokens
                }
            };

            var json = JsonSerializer.Serialize(requestBody);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync(
                $"{_options.BaseUrl}/v1beta/models/{_options.Model}:generateContent?key={_options.ApiKey}",
                content);

            response.EnsureSuccessStatusCode();

            var responseJson = await response.Content.ReadAsStringAsync();
            _logger.LogDebug("Raw Gemini API response: {Response}",
                responseJson.Substring(0, Math.Min(500, responseJson.Length)));

            return ExtractTextFromResponse(responseJson);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Gemini API call failed");
            throw;
        }
    }

    private string ExtractTextFromResponse(string responseJson)
    {
        using var document = JsonDocument.Parse(responseJson);
        var root = document.RootElement;

        if (root.TryGetProperty("candidates", out var candidatesElement) &&
            candidatesElement.ValueKind == JsonValueKind.Array)
        {
            var firstCandidate = candidatesElement.EnumerateArray().FirstOrDefault();
            if (firstCandidate.ValueKind != JsonValueKind.Undefined &&
                firstCandidate.TryGetProperty("content", out var contentElement) &&
                contentElement.TryGetProperty("parts", out var partsElement) &&
                partsElement.ValueKind == JsonValueKind.Array)
            {
                var firstPart = partsElement.EnumerateArray().FirstOrDefault();
                if (firstPart.TryGetProperty("text", out var textElement))
                {
                    return textElement.GetString() ?? string.Empty;
                }
            }
        }

        // 檢查是否有安全過濾
        if (root.TryGetProperty("promptFeedback", out _))
        {
            _logger.LogWarning("Gemini content filtered due to safety policies");
            return "The content analysis is temporarily unavailable due to safety filtering.";
        }

        return string.Empty;
    }

    private SentenceAnalysisData ParseAIResponse(string inputText, string aiResponse)
    {
        try
        {
            var cleanJson = CleanAIResponse(aiResponse);
            var aiAnalysis = JsonSerializer.Deserialize<AiAnalysisResponse>(cleanJson, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            });

            if (aiAnalysis == null)
            {
                throw new InvalidOperationException("Failed to parse AI response JSON");
            }

            return new SentenceAnalysisData
            {
                OriginalText = inputText,
                SentenceMeaning = aiAnalysis.SentenceTranslation ?? "",
                VocabularyAnalysis = ConvertVocabularyAnalysis(aiAnalysis.VocabularyAnalysis ?? new()),
                Idioms = ConvertIdioms(aiAnalysis.Idioms ?? new()),
                GrammarCorrection = ConvertGrammarCorrection(aiAnalysis),
                Metadata = new AnalysisMetadata
                {
                    ProcessingDate = DateTime.UtcNow,
                    AnalysisModel = _options.Model,
                    AnalysisVersion = "2.0"
                }
            };
        }
        catch (JsonException ex)
        {
            _logger.LogError(ex, "Failed to parse AI response as JSON: {Response}", aiResponse);
            return CreateFallbackAnalysis(inputText, aiResponse);
        }
    }

    private string CleanAIResponse(string aiResponse)
    {
        var cleanJson = aiResponse.Trim();
        if (cleanJson.StartsWith("```json"))
        {
            cleanJson = cleanJson.Substring(7);
        }
        if (cleanJson.EndsWith("```"))
        {
            cleanJson = cleanJson.Substring(0, cleanJson.Length - 3);
        }
        return cleanJson.Trim();
    }

    private Dictionary<string, VocabularyAnalysisDto> ConvertVocabularyAnalysis(Dictionary<string, AiVocabularyAnalysis> aiVocab)
    {
        var result = new Dictionary<string, VocabularyAnalysisDto>();

        foreach (var kvp in aiVocab)
        {
            var aiWord = kvp.Value;
            result[kvp.Key] = new VocabularyAnalysisDto
            {
                Word = aiWord.Word ?? kvp.Key,
                Translation = aiWord.Translation ?? "",
                Definition = aiWord.Definition ?? "",
                PartOfSpeech = aiWord.PartOfSpeech ?? "unknown",
                Pronunciation = aiWord.Pronunciation ?? $"/{kvp.Key}/",
                DifficultyLevel = aiWord.DifficultyLevel ?? "A2",
                Frequency = aiWord.Frequency ?? "medium",
                Synonyms = aiWord.Synonyms ?? new List<string>(),
                Example = aiWord.Example,
                ExampleTranslation = aiWord.ExampleTranslation,
            };
        }

        return result;
    }

    private List<IdiomDto> ConvertIdioms(List<AiIdiom> aiIdioms)
    {
        var result = new List<IdiomDto>();

        foreach (var aiIdiom in aiIdioms)
        {
            result.Add(new IdiomDto
            {
                Idiom = aiIdiom.Idiom ?? "",
                Translation = aiIdiom.Translation ?? "",
                Definition = aiIdiom.Definition ?? "",
                Pronunciation = aiIdiom.Pronunciation ?? "",
                DifficultyLevel = aiIdiom.DifficultyLevel ?? "B2",
                Frequency = aiIdiom.Frequency ?? "medium",
                Synonyms = aiIdiom.Synonyms ?? new List<string>(),
                Example = aiIdiom.Example,
                ExampleTranslation = aiIdiom.ExampleTranslation
            });
        }

        return result;
    }

    private GrammarCorrectionDto? ConvertGrammarCorrection(AiAnalysisResponse aiAnalysis)
    {
        if (!aiAnalysis.HasGrammarErrors || aiAnalysis.GrammarCorrections == null || !aiAnalysis.GrammarCorrections.Any())
        {
            return null;
        }

        var corrections = aiAnalysis.GrammarCorrections.Select(gc => new GrammarErrorDto
        {
            Error = gc.Original ?? "",
            Correction = gc.Corrected ?? "",
            Type = gc.Type ?? "grammar",
            Explanation = gc.Explanation ?? "",
            Severity = "medium",
            Position = new ErrorPosition { Start = 0, End = 0 }
        }).ToList();

        return new GrammarCorrectionDto
        {
            HasErrors = true,
            CorrectedText = string.Join(" ", corrections.Select(c => c.Correction)),
            Corrections = corrections
        };
    }

    private SentenceAnalysisData CreateFallbackAnalysis(string inputText, string aiResponse)
    {
        _logger.LogWarning("Using fallback analysis due to JSON parsing failure");

        return new SentenceAnalysisData
        {
            OriginalText = inputText,
            SentenceMeaning = aiResponse,
            VocabularyAnalysis = new Dictionary<string, VocabularyAnalysisDto>(),
            Metadata = new AnalysisMetadata
            {
                ProcessingDate = DateTime.UtcNow,
                AnalysisModel = $"{_options.Model}-fallback",
                AnalysisVersion = "2.0"
            },
        };
    }

    private void RecordSuccessfulRequest(long elapsedMs)
    {
        _stats.SuccessfulRequests++;
        _stats.LastUsedAt = DateTime.UtcNow;
        _stats.TotalCost += CostPerRequest;
        UpdateAverageResponseTime((int)elapsedMs);
    }

    private void RecordFailedRequest(long elapsedMs)
    {
        _stats.FailedRequests++;
        UpdateAverageResponseTime((int)elapsedMs);
    }

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

    #endregion
}

#region AI Response Models (重用現有的模型)

internal class AiAnalysisResponse
{
    public string? SentenceTranslation { get; set; }
    public bool HasGrammarErrors { get; set; }
    public List<AiGrammarCorrection>? GrammarCorrections { get; set; }
    public Dictionary<string, AiVocabularyAnalysis>? VocabularyAnalysis { get; set; }
    public List<AiIdiom>? Idioms { get; set; }
}

internal class AiGrammarCorrection
{
    public string? Original { get; set; }
    public string? Corrected { get; set; }
    public string? Type { get; set; }
    public string? Explanation { get; set; }
}

internal class AiVocabularyAnalysis
{
    public string? Word { get; set; }
    public string? Translation { get; set; }
    public string? Definition { get; set; }
    public string? PartOfSpeech { get; set; }
    public string? Pronunciation { get; set; }
    public string? DifficultyLevel { get; set; }
    public string? Frequency { get; set; }
    public List<string>? Synonyms { get; set; }
    public string? Example { get; set; }
    public string? ExampleTranslation { get; set; }
}

internal class AiIdiom
{
    public string? Idiom { get; set; }
    public string? Translation { get; set; }
    public string? Definition { get; set; }
    public string? Pronunciation { get; set; }
    public string? DifficultyLevel { get; set; }
    public string? Frequency { get; set; }
    public List<string>? Synonyms { get; set; }
    public string? Example { get; set; }
    public string? ExampleTranslation { get; set; }
}

#endregion