using System.Net;
using Serilog;

namespace adas_core.module.ProxyDevices.Devices;

public class HttpDevice : IProxyDevice
{
    private string _domain = "";

    private bool _isInitialized;
    private string _name = "";
    private string _password = "";
    private Uri _uri = null!;
    private string _username = "";

    public void Initialize(Dictionary<string, object?> deviceParameters)
    {
        if (_isInitialized) throw new InvalidOperationException("Device already initialized");
        if (!deviceParameters.TryGetValue("url", out var urlobj) || urlobj is not string url ||
            string.IsNullOrEmpty(url.Trim()) || !Uri.TryCreate(url, UriKind.Absolute, out var uri))
            throw new ArgumentNullException(nameof(deviceParameters),
                "Device parameter 'url' is required and must be a valid ur");
        _uri = uri;
        if (deviceParameters.TryGetValue("name", out var name)) _name = name?.ToString() ?? "";
        if (deviceParameters.TryGetValue("username", out var username)) _username = username?.ToString() ?? "";
        if (deviceParameters.TryGetValue("password", out var password)) _password = password?.ToString() ?? "";
        if (deviceParameters.TryGetValue("domain", out var domain)) _domain = domain?.ToString() ?? "";
        _isInitialized = true;
    }

    public async Task<HttpResponseMessage> Process()
    {
        try
        {
            var client = GetHttpClient();
            return await client.GetAsync(_uri);
        }
        catch (TaskCanceledException ex)
        {
            Log.Error("Error getting Http Client get async. Exception:{ex}", ex.ToString());
            throw new TimeoutException("La solicitud fue cancelada debido al tiempo de espera.", ex);
        }
    }

    public async Task<HttpResponseMessage> Stream()
    {
        try
        {
            var client = GetHttpClient();
            var response = await client.GetAsync(_uri, HttpCompletionOption.ResponseHeadersRead);
            return response;
        }
        catch (TaskCanceledException ex)
        {
            Log.Error("Exception getting response. Ex: {ex}", ex.ToString());
            throw new TimeoutException("La solicitud fue cancelada debido al tiempo de espera.", ex);
        }
    }

    private HttpClient GetHttpClient()
    {
        if (!_isInitialized) throw new InvalidOperationException("Device not initialized");
        // get content via http with digest auth
        var clientHandler = new HttpClientHandler();
        if (!string.IsNullOrEmpty(_username))
            clientHandler.Credentials = new NetworkCredential(_username, _password, _domain);
        return new HttpClient(clientHandler);
    }

    public override string ToString()
    {
        return $"[HttpDevice] ({_name} {_uri} {_username} {_password} {_domain})";
    }
}