using System.Net;
using adas_core.module.ProxyDevices.Devices;
using Microsoft.Extensions.Options;

namespace adas_core.module.ProxyDevices.Services;

public class ProxyDeviceService(IOptions<ProxyDeviceSettings> settings) : IProxyDeviceService
{
    private readonly Dictionary<string, IProxyDevice?> _cache = new();

    public async Task<HttpResponseMessage> Process(string deviceId)
    {
        try
        {
            var device = GetDevice(deviceId);
            if (device == null)
                return new HttpResponseMessage(HttpStatusCode.NotFound)
                    { ReasonPhrase = $"Proxy device not found. deviceId:{deviceId}" };

            return await device.Process();
        }
        catch (HttpRequestException e)
        {
            return new HttpResponseMessage(e.StatusCode ?? HttpStatusCode.NotFound) { ReasonPhrase = e.Message };
        }
    }

    public async Task<HttpResponseMessage> Stream(string deviceId)
    {
        try
        {
            var device = GetDevice(deviceId);
            if (device == null)
                return new HttpResponseMessage(HttpStatusCode.NotFound)
                    { ReasonPhrase = $"Proxy device not found. deviceId:{deviceId}" };

            return await device.Stream();
        }
        catch (HttpRequestException e)
        {
            return new HttpResponseMessage(e.StatusCode ?? HttpStatusCode.NotFound) { ReasonPhrase = e.Message };
        }
    }

    private IProxyDevice? GetDevice(string deviceId)
    {
        var device = settings.Value.FirstOrDefault(d => d.Id == deviceId);
        if (device is not { Enabled: true })
            throw new HttpRequestException("Device not found or not enabled", null, HttpStatusCode.NotFound);
        IProxyDevice? deviceInstance = null;
        lock (_cache)
        {
            if (_cache.TryGetValue(deviceId, out var value))
            {
                deviceInstance = value;
            }
            else
            {
                var deviceType = Type.GetType("adas_core.module.ProxyDevices.Devices." + device.Type + "Device") ??
                                 throw new HttpRequestException("Device not implemented", null,
                                     HttpStatusCode.NotImplemented);
                var instance = Activator.CreateInstance(deviceType);
                if (instance is IProxyDevice proxyDevice)
                {
                    deviceInstance = proxyDevice;
                    deviceInstance.Initialize(device.Parameters);
                }

                _cache.Add(deviceId, deviceInstance);
            }
        }

        return deviceInstance;
    }
}