using ClawdDotNet.Core.Config;
using ClawdDotNet.Core.Engine;
using ClawdDotNet.UI;
using Microsoft.Extensions.Logging;
using Microsoft.Web.WebView2.Core;

namespace ClawdDotNet;

public partial class frm_chat : Form
{
    private readonly AgentConfig _agentConfig;
    private readonly AgentEngine _engine;
    private readonly string _instanceId;
    private readonly ILogger _logger;

    private WebViewBridge? _bridge;

    public frm_chat(AgentConfig agentConfig, AgentEngine engine,
        string instanceId, ILoggerFactory loggerFactory)
    {
        _agentConfig = agentConfig;
        _engine = engine;
        _instanceId = instanceId;
        _logger = loggerFactory.CreateLogger($"ClawdDotNet.UI.Chat.{agentConfig.AgentId}");

        InitializeComponent();
        Text = $"Chat – {agentConfig.DisplayName}";
        Load += async (_, _) => await InitWebViewAsync();
    }

    public frm_chat()
    {
        _agentConfig = new AgentConfig();
        _engine = null!;
        _instanceId = "";
        _logger = LoggerFactory.Create(_ => { }).CreateLogger("Design");
        InitializeComponent();
    }

    private async Task InitWebViewAsync()
    {
        try
        {
            await webView_chat2.EnsureCoreWebView2Async();

            var uiPath = EmbeddedUiManager.GetExtractedPath();
            webView_chat2.CoreWebView2.SetVirtualHostNameToFolderMapping(
                "ui.clwd.internal", uiPath,
                CoreWebView2HostResourceAccessKind.DenyCors);

            _bridge = new WebViewBridge(webView_chat2, _logger);
            _bridge.MessageReceived += OnBridgeMessage;

            webView_chat2.CoreWebView2.Navigate(
                $"https://ui.clwd.internal/chat.html?agent={_agentConfig.AgentId}");

            await Task.Delay(500);

            await _bridge.SendAsync(new BridgeMessage(
                Type: BridgeTypes.AgentListUpdate,
                AgentId: _agentConfig.AgentId,
                Extra: new
                {
                    agents = new[]
                    {
                        new
                        {
                            agentId = _agentConfig.AgentId,
                            displayName = _agentConfig.DisplayName,
                            model = _agentConfig.Model
                        }
                    }
                }));

            await LoadChatHistoryAsync();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "frm_chat WebView2 init failed");
        }
    }

    private async void OnBridgeMessage(BridgeMessage msg)
    {
        if (InvokeRequired) { Invoke(() => OnBridgeMessage(msg)); return; }

        switch (msg.Type)
        {
            case BridgeTypes.UserMessage:
                if (msg.Content is not null)
                    await HandleUserMessageAsync(msg.Content);
                break;

            case BridgeTypes.RunNow:
                await HandleUserMessageAsync("Führe deine zugewiesenen Aufgaben aus.");
                break;

            case BridgeTypes.AbortRun:
                _engine.AbortChat(_agentConfig.AgentId);
                break;
        }
    }

    private async Task HandleUserMessageAsync(string text)
    {
        if (_bridge is null) return;

        await _bridge.SendAsync(new BridgeMessage(
            Type: BridgeTypes.ChatMessage,
            AgentId: _agentConfig.AgentId,
            Content: text,
            Extra: new { role = "user", timestamp = DateTime.Now }));

        await _bridge.SendAsync(new BridgeMessage(
            Type: BridgeTypes.ChatTyping,
            AgentId: _agentConfig.AgentId));

        _ = Task.Run(async () =>
        {
            try
            {
                var result = await _engine.ChatAsync(
                    _agentConfig, text, _instanceId, CancellationToken.None,
                    source: ChatSource.WebView);

                await _bridge.SendAsync(new BridgeMessage(
                    Type: BridgeTypes.ChatMessage,
                    AgentId: _agentConfig.AgentId,
                    Content: result.FinalMessage ?? "[Keine Antwort]",
                    Extra: new { role = "assistant", timestamp = DateTime.Now }));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Chat failed");
                await _bridge!.SendAsync(new BridgeMessage(
                    Type: BridgeTypes.ChatMessage,
                    AgentId: _agentConfig.AgentId,
                    Content: $"[Fehler: {ex.Message}]",
                    Extra: new { role = "assistant", timestamp = DateTime.Now }));
            }
        });
    }

    private async Task LoadChatHistoryAsync()
    {
        if (_bridge is null) return;

        var history = _engine.GetChatHistory(_agentConfig.AgentId);
        await _bridge.SendAsync(new BridgeMessage(
            Type: BridgeTypes.ChatHistory,
            AgentId: _agentConfig.AgentId,
            Extra: history.Select(e => new
            {
                role = e.Role,
                content = e.Content,
                timestamp = e.Timestamp
            }).ToArray()));
    }

    protected override void OnFormClosed(FormClosedEventArgs e)
    {
        _bridge?.Dispose();
        base.OnFormClosed(e);
    }
}
