using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using OpenQA.Selenium;

namespace TestersAI.SeleniumSupport;

public sealed class TestersAIDriver
{
    private readonly IWebDriver _driver;
    private readonly TestersAIClient _client;
    private readonly List<Action<AnalysisResult>> _sinks;

    public TestersAIDriver(IWebDriver driver, Action<AnalysisResult>? frameworkLog = null)
    {
        _driver = driver;
        var cfg = Config.FromEnv();
        _client = new TestersAIClient(cfg);
        _sinks = Sinks.Build(cfg, frameworkLog);
    }

    IReadOnlyDictionary<string, object?> Ctx()
    {
        try { return new Dictionary<string, object?> { ["url"] = _driver.Url, ["title"] = _driver.Title }; }
        catch { return new Dictionary<string, object?>(); }
    }

    public async Task<AnalysisResult> AnalyzeScreenshotAsync()
    {
        var bytes = ((ITakesScreenshot)_driver).GetScreenshot().AsByteArray;
        return Sinks.Dispatch(await _client.AnalyzeScreenshotAsync(bytes, Ctx()), _sinks);
    }

    public async Task<AnalysisResult> AnalyzeConsoleAsync()
    {
        var entries = new List<IDictionary<string, object?>>();
        try
        {
            var logs = _driver.Manage().Logs.GetLog("browser");
            foreach (var e in logs)
                entries.Add(new Dictionary<string, object?> {
                    ["level"] = e.Level.ToString().ToLowerInvariant(), ["text"] = e.Message });
        }
        catch { /* some drivers don't support */ }
        return Sinks.Dispatch(await _client.AnalyzeConsoleAsync(entries, Ctx()), _sinks);
    }

    public async Task<AnalysisResult> AnalyzePageTextAsync()
    {
        string src = "";
        try { src = _driver.PageSource; } catch { }
        return Sinks.Dispatch(await _client.AnalyzePageTextAsync(src, Ctx()), _sinks);
    }

    public async Task<AnalysisResult> AnalyzeNetworkAsync(object har)
        => Sinks.Dispatch(await _client.AnalyzeNetworkAsync(har, Ctx()), _sinks);
}
