using System.Data;
using FluentAssertions;
using Npgsql;
using SatelliteProvider.Common.Enums;
using SatelliteProvider.DataAccess.TypeHandlers;

namespace SatelliteProvider.Tests;

public class EnumStringTypeHandlerTests
{
    [Theory]
    [InlineData(RegionStatus.Queued, "queued")]
    [InlineData(RegionStatus.Processing, "processing")]
    [InlineData(RegionStatus.Completed, "completed")]
    [InlineData(RegionStatus.Failed, "failed")]
    public void SetValue_RegionStatus_WritesLowercaseString_AZ370_AC1(RegionStatus value, string expected)
    {
        var handler = new EnumStringTypeHandler<RegionStatus>();
        var param = new NpgsqlParameter();

        handler.SetValue(param, value);

        param.Value.Should().Be(expected);
        param.DbType.Should().Be(DbType.String);
    }

    [Theory]
    [InlineData(RoutePointType.Start, "start")]
    [InlineData(RoutePointType.End, "end")]
    [InlineData(RoutePointType.Action, "action")]
    [InlineData(RoutePointType.Intermediate, "intermediate")]
    public void SetValue_RoutePointType_WritesLowercaseString_AZ370_AC1(RoutePointType value, string expected)
    {
        var handler = new EnumStringTypeHandler<RoutePointType>();
        var param = new NpgsqlParameter();

        handler.SetValue(param, value);

        param.Value.Should().Be(expected);
        param.DbType.Should().Be(DbType.String);
    }

    [Theory]
    [InlineData("queued", RegionStatus.Queued)]
    [InlineData("processing", RegionStatus.Processing)]
    [InlineData("completed", RegionStatus.Completed)]
    [InlineData("failed", RegionStatus.Failed)]
    [InlineData("Completed", RegionStatus.Completed)]
    public void Parse_RegionStatus_AcceptsAnyCase_AZ370_AC2(string raw, RegionStatus expected)
    {
        var handler = new EnumStringTypeHandler<RegionStatus>();

        var result = handler.Parse(raw);

        result.Should().Be(expected);
    }

    [Theory]
    [InlineData("start", RoutePointType.Start)]
    [InlineData("end", RoutePointType.End)]
    [InlineData("action", RoutePointType.Action)]
    [InlineData("intermediate", RoutePointType.Intermediate)]
    public void Parse_RoutePointType_AcceptsLowercase_AZ370_AC2(string raw, RoutePointType expected)
    {
        var handler = new EnumStringTypeHandler<RoutePointType>();

        var result = handler.Parse(raw);

        result.Should().Be(expected);
    }

    [Theory]
    [InlineData(RegionStatus.Queued)]
    [InlineData(RegionStatus.Processing)]
    [InlineData(RegionStatus.Completed)]
    [InlineData(RegionStatus.Failed)]
    public void RoundTrip_RegionStatus_PreservesValue_AZ370_AC2(RegionStatus value)
    {
        var handler = new EnumStringTypeHandler<RegionStatus>();
        var param = new NpgsqlParameter();
        handler.SetValue(param, value);

        var roundTripped = handler.Parse(param.Value!);

        roundTripped.Should().Be(value);
    }

    [Theory]
    [InlineData(RoutePointType.Start)]
    [InlineData(RoutePointType.End)]
    [InlineData(RoutePointType.Action)]
    [InlineData(RoutePointType.Intermediate)]
    public void RoundTrip_RoutePointType_PreservesValue_AZ370_AC2(RoutePointType value)
    {
        var handler = new EnumStringTypeHandler<RoutePointType>();
        var param = new NpgsqlParameter();
        handler.SetValue(param, value);

        var roundTripped = handler.Parse(param.Value!);

        roundTripped.Should().Be(value);
    }

    [Fact]
    public void Parse_NullValue_ThrowsDataException()
    {
        var handler = new EnumStringTypeHandler<RegionStatus>();

        Action act = () => handler.Parse(null!);

        act.Should().Throw<DataException>();
    }

    [Fact]
    public void Parse_DbNullValue_ThrowsDataException()
    {
        var handler = new EnumStringTypeHandler<RegionStatus>();

        Action act = () => handler.Parse(DBNull.Value);

        act.Should().Throw<DataException>();
    }

    [Fact]
    public void Parse_UnknownString_ThrowsDataException()
    {
        var handler = new EnumStringTypeHandler<RegionStatus>();

        Action act = () => handler.Parse("not-a-status");

        act.Should().Throw<DataException>();
    }

    [Fact]
    public void RegisterAll_IsIdempotent()
    {
        DapperEnumTypeHandlers.RegisterAll();
        DapperEnumTypeHandlers.RegisterAll();
    }
}
