using adas_core.Domain.Exceptions;

namespace adas_core.Infrastructure.Utils;

/// <summary>
/// Provides static utility methods for working with types.
/// </summary>
public static class TypesUtils
{
    /// <summary>
    /// Retrieves the driver <see cref="Type"/> associated with the specified device type and device.
    /// Supports "Relay" (mapped to adas-core.module.Relays) and "LightBeacon" (mapped to adas-core.module.LightBeacons) device types.
    /// </summary>
    /// <param name="deviceType">The category of the device used to determine the appropriate driver type.</param>
    /// <param name="device">The specific device identifier used when resolving the driver type.</param>
    /// <returns>The <see cref="Type"/> of the driver that corresponds to the given device type.</returns>
    /// <exception cref="AdasException">Thrown when the provided <paramref name="deviceType"/> is not a recognized value.</exception>
    public static Type GetDriver(string deviceType, string device)
        {
            return deviceType switch
            {
                "Relay" => GetType("adas-core.module.Relays", device, deviceType),
                "LightBeacon" => GetType("adas-core.module.LightBeacons", device, deviceType),
                _ => throw new AdasException($"Device type {deviceType} not found")
            };
        }

    private static Type GetType(string typeName, string device, string deviceType)
    {
        var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
        var assembly = loadedAssemblies.FirstOrDefault(a =>
        {
            var name = a.GetName().Name;
            return name != null && name.Contains(typeName);
        });

        if (assembly == null)
            // El ensamblado no está cargado. Lanzar excepción o manejar el fallo.
            throw new AdasException($"Assembly '{typeName}' not loaded.");

        var fullClassName = $"{typeName.Replace('-', '_')}.Devices.{device}{deviceType}";

        var type = assembly.GetType(fullClassName,
            true,
            true);

        if (type != null) return type;

        throw new AdasException($"{typeName} driver not found");
    }
}