using Books.Api.AiBookkeeper;
using AwesomeAssertions;

namespace Books.Api.Tests.AiBookkeeper;

/// <summary>
/// Unit tests for ToonFormatConverter.
/// Verifies that ChartOfAccountsDto is correctly converted to .toon format.
/// </summary>
[Trait("Category", "Unit")]
public class ToonFormatConverterTests
{
    [Fact]
    public void ConvertToToon_EuGoodsAccount_HasEuRegion()
    {
        // Arrange
        var chartOfAccounts = CreateChartOfAccounts(
            CreateAccount("2050", "EU-erhvervelser varer", "cogs", "IEUV"));

        // Act
        var result = ToonFormatConverter.ConvertToToon(chartOfAccounts);

        // Assert - Account 2050 should have region EU
        result.Should().Contain("2050,EU-erhvervelser varer,Variable omkostninger,IEUV,EU,,");
    }

    [Fact]
    public void ConvertToToon_EuServicesAccount_HasEuRegion()
    {
        // Arrange
        var chartOfAccounts = CreateChartOfAccounts(
            CreateAccount("2100", "EU-erhvervelser ydelser", "cogs", "IEUY"));

        // Act
        var result = ToonFormatConverter.ConvertToToon(chartOfAccounts);

        // Assert - Account 2100 should have region EU
        result.Should().Contain("2100,EU-erhvervelser ydelser,Variable omkostninger,IEUY,EU,,");
    }

    [Fact]
    public void ConvertToToon_WorldGoodsAccount_HasWorldRegion()
    {
        // Arrange
        var chartOfAccounts = CreateChartOfAccounts(
            CreateAccount("2150", "Varekøb verden", "cogs", "IVV"));

        // Act
        var result = ToonFormatConverter.ConvertToToon(chartOfAccounts);

        // Assert - Account 2150 should have region WORLD
        result.Should().Contain("2150,Varekøb verden,Variable omkostninger,IVV,WORLD,,");
    }

    [Fact]
    public void ConvertToToon_WorldServicesAccount_HasWorldRegion()
    {
        // Arrange
        var chartOfAccounts = CreateChartOfAccounts(
            CreateAccount("2200", "Ydelseskøb verden", "cogs", "IVY"));

        // Act
        var result = ToonFormatConverter.ConvertToToon(chartOfAccounts);

        // Assert - Account 2200 should have region WORLD
        result.Should().Contain("2200,Ydelseskøb verden,Variable omkostninger,IVY,WORLD,,");
    }

    [Fact]
    public void ConvertToToon_DomesticAccount_HasEmptyRegion()
    {
        // Arrange
        var chartOfAccounts = CreateChartOfAccounts(
            CreateAccount("7320", "Køb af software", "expense", "I25"));

        // Act
        var result = ToonFormatConverter.ConvertToToon(chartOfAccounts);

        // Assert - Account 7320 should have empty region (available for all regions)
        result.Should().Contain("7320,Køb af software,Administrationsomkostninger,I25,,,");
    }

    [Fact]
    public void ConvertToToon_AccountWithNoVatCode_HasEmptyRegion()
    {
        // Arrange
        var chartOfAccounts = CreateChartOfAccounts(
            CreateAccount("7000", "Kontorartikler", "expense", null));

        // Act
        var result = ToonFormatConverter.ConvertToToon(chartOfAccounts);

        // Assert - Account with no VAT code should have empty region
        result.Should().Contain("7000,Kontorartikler,Administrationsomkostninger,,,,");
    }

    [Fact]
    public void ConvertToToon_MixedAccounts_CorrectRegionsAssigned()
    {
        // Arrange
        var chartOfAccounts = CreateChartOfAccounts(
            CreateAccount("2000", "Vareforbrug", "cogs", "I25"),
            CreateAccount("2050", "EU-erhvervelser varer", "cogs", "IEUV"),
            CreateAccount("2150", "Varekøb verden", "cogs", "IVV"),
            CreateAccount("7320", "Køb af software", "expense", "I25"));

        // Act
        var result = ToonFormatConverter.ConvertToToon(chartOfAccounts);

        // Assert
        result.Should().Contain("2000,Vareforbrug,Variable omkostninger,I25,,,");      // Empty region
        result.Should().Contain("2050,EU-erhvervelser varer,Variable omkostninger,IEUV,EU,,");  // EU
        result.Should().Contain("2150,Varekøb verden,Variable omkostninger,IVV,WORLD,,");       // WORLD
        result.Should().Contain("7320,Køb af software,Administrationsomkostninger,I25,,,");     // Empty region
    }

    [Fact]
    public void ConvertToToon_ContainsMetaSection()
    {
        // Arrange
        var chartOfAccounts = CreateChartOfAccounts(
            CreateAccount("7000", "Kontorartikler", "expense", "I25"));

        // Act
        var result = ToonFormatConverter.ConvertToToon(chartOfAccounts);

        // Assert
        result.Should().Contain("meta:");
        result.Should().Contain("source: Books API");
        result.Should().Contain("organizationId: company-1");
        result.Should().Contain("accountType: expense");
        result.Should().Contain("totalAccounts: 1");
    }

    [Fact]
    public void ConvertToToon_ContainsAccountsHeader()
    {
        // Arrange
        var chartOfAccounts = CreateChartOfAccounts(
            CreateAccount("7000", "Kontorartikler", "expense", "I25"),
            CreateAccount("7100", "Porto", "expense", "I25"));

        // Act
        var result = ToonFormatConverter.ConvertToToon(chartOfAccounts);

        // Assert
        result.Should().Contain("accounts[2]{number,name,category,vatCode,region,vatRubric,suggestions}:");
    }

    [Fact]
    public void MapCategory_ExpenseAccount_ReturnsAdministrationsomkostninger()
    {
        var result = ToonFormatConverter.MapCategory("expense");
        result.Should().Be("Administrationsomkostninger");
    }

    [Fact]
    public void MapCategory_CogsAccount_ReturnsVariableOmkostninger()
    {
        var result = ToonFormatConverter.MapCategory("cogs");
        result.Should().Be("Variable omkostninger");
    }

    [Fact]
    public void MapCategory_PersonnelAccount_ReturnsLønomkostninger()
    {
        var result = ToonFormatConverter.MapCategory("personnel");
        result.Should().Be("Lønomkostninger");
    }

    [Fact]
    public void MapCategory_FinancialAccount_ReturnsRenteudgifter()
    {
        var result = ToonFormatConverter.MapCategory("financial");
        result.Should().Be("Renteudgifter");
    }

    [Fact]
    public void GenerateSuggestions_IncludesWordsFromName()
    {
        var result = ToonFormatConverter.GenerateSuggestions("Køb af software", "7320");
        result.Should().Contain("køb");
        result.Should().Contain("software");
        result.Should().Contain("7320");
    }

    [Fact]
    public void GenerateSuggestions_ExcludesShortWords()
    {
        var result = ToonFormatConverter.GenerateSuggestions("IT og software", "7320");
        result.Should().NotContain("og");  // "og" has only 2 characters
        result.Should().Contain("software");
    }

    private static ChartOfAccountsDto CreateChartOfAccounts(params AiAccountDto[] accounts)
    {
        return new ChartOfAccountsDto
        {
            CompanyId = "company-1",
            Accounts = accounts.ToList()
        };
    }

    private static AiAccountDto CreateAccount(string number, string name, string type, string? vatCode)
    {
        return new AiAccountDto
        {
            AccountNumber = number,
            Name = name,
            AccountType = type,
            VatCodeId = vatCode
        };
    }
}
