using Anthropic.SDK;
using Anthropic.SDK.Messaging;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using PowderCoating.Application.Interfaces;

namespace PowderCoating.Infrastructure.Services;

public class AiHelpService : IAiHelpService
{
    private readonly ILogger<AiHelpService> _logger;
    private readonly AnthropicClient? _client;

    private const int MaxHistoryTurns = 10; // keep last 10 exchanges to limit tokens
    private const string Model = "claude-sonnet-4-6";

    /// <summary>
    /// Initializes <see cref="AiHelpService"/> and eagerly creates the
    /// <see cref="AnthropicClient"/> if the API key is configured. The client is stored as a
    /// nullable field rather than throwing at construction time so that the rest of the
    /// application continues to function when the AI key is absent — the null is checked in
    /// <see cref="SendMessageAsync"/> and returns a user-friendly message instead of a 500
    /// error. The client is constructed once here (rather than per call) because
    /// <see cref="AnthropicClient"/> is thread-safe and reuse avoids the overhead of
    /// recreating the HTTP client on each chat message.
    /// </summary>
    public AiHelpService(IConfiguration config, ILogger<AiHelpService> logger)
    {
        _logger = logger;
        var apiKey = config["AI:Anthropic:ApiKey"];
        if (!string.IsNullOrWhiteSpace(apiKey))
            _client = new AnthropicClient(apiKey);
    }

    /// <summary>
    /// Sends a user message to Claude with the full conversation history and the
    /// <c>HelpKnowledgeBase</c>-sourced system prompt, then returns the assistant's plain-text
    /// response. The conversation history is trimmed to the last
    /// <see cref="MaxHistoryTurns"/> × 2 messages (10 exchanges = 20 turns) before being
    /// sent to keep prompt tokens within budget — older context is dropped because users
    /// asking help questions rarely need to reference what they said more than 10 turns ago,
    /// and the system prompt already contains the full knowledge base as grounding. A 60-second
    /// cancellation token is applied to prevent slow AI responses from holding an ASP.NET
    /// request thread indefinitely; the controller's <c>[EnableRateLimiting]</c> attribute
    /// provides the outer rate-limit layer so this method does not need to enforce it. When
    /// the API key is not configured, a friendly "not configured" message is returned so
    /// that users see a clear explanation rather than an unhandled exception or empty response.
    /// </summary>
    public async Task<string> SendMessageAsync(
        List<AiHelpMessage> conversationHistory,
        string userMessage,
        string systemPrompt)
    {
        if (_client == null)
        {
            _logger.LogWarning("AI Help: Anthropic API key not configured.");
            return "The AI Help Assistant is not configured yet. Please contact your system administrator.";
        }

        try
        {
            var trimmedHistory = conversationHistory
                .TakeLast(MaxHistoryTurns * 2)
                .ToList();

            var messages = trimmedHistory
                .Select(m => new Message
                {
                    Role = m.Role == "user" ? RoleType.User : RoleType.Assistant,
                    Content = new List<ContentBase> { new TextContent { Text = m.Content } }
                })
                .ToList();

            messages.Add(new Message
            {
                Role = RoleType.User,
                Content = new List<ContentBase> { new TextContent { Text = userMessage } }
            });

            var request = new MessageParameters
            {
                Model = Model,
                MaxTokens = 1024,
                SystemMessage = systemPrompt,
                Messages = messages
            };

            using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
            var response = await _client.Messages.GetClaudeMessageAsync(request, cts.Token);

            return response.FirstMessage?.Text
                   ?? response.Content?.OfType<TextContent>().FirstOrDefault()?.Text
                   ?? "I wasn't able to generate a response. Please try again.";
        }
        catch (OperationCanceledException)
        {
            _logger.LogWarning("AI Help: Request timed out.");
            return "The request took too long to process. Please try again.";
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "AI Help: Error calling Anthropic API.");
            return "I encountered an error processing your request. Please try again in a moment.";
        }
    }
}
