using Books.Api.EventFlow.Repositories;
using Books.Api.Tests.Helpers;
using Books.Api.Tests.Infrastructure;
using AwesomeAssertions;
using Microsoft.Extensions.DependencyInjection;

namespace Books.Api.Tests.GraphQL;

/// <summary>
/// Integration tests for Account GraphQL operations.
/// Each test class runs with its own isolated database.
/// </summary>
[Trait("Category", "Integration")]
public class AccountGraphQLTests(TestWebApplicationFactory factory)
    : IntegrationTestBase(factory)
{
    [Fact]
    public async Task Query_Accounts_FailsWithoutCompanyHeader()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        // Note: We're NOT setting X-Company-Id header

        // Act - query accounts without X-Company-Id header
        var response = await graphqlClient.QueryAsync<AccountsResponse>("""
            query {
                accounts(companyId: "nonexistent") {
                    id
                    name
                }
            }
            """);

        // Assert - Should fail with authorization error
        response.HasErrors.Should().BeTrue();
        var errorInfo = string.Join(" ", response.Errors!.Select(e =>
            e.Message + " " + (e.Extensions?.GetValueOrDefault("details")?.ToString() ?? "")));
        errorInfo.Should().Contain("No company selected");
    }

    [Fact]
    public async Task Mutation_CreateAccount_CreatesAccountSuccessfully()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);

        // First create a company (which doesn't auto-create accounts in this test)
        var companyId = await CreateCompanyAsync(graphqlClient, "Account Test Company");

        // Act - Create an account
        var response = await graphqlClient.MutateAsync<CreateAccountResponse>("""
            mutation CreateAccount($input: CreateAccountInput!) {
                createAccount(input: $input) {
                    id
                    companyId
                    accountNumber
                    name
                    accountType
                    isActive
                    isSystemAccount
                }
            }
            """,
            new
            {
                input = new
                {
                    companyId,
                    accountNumber = "9999",
                    name = "Test Konto",
                    accountType = "EXPENSE",
                    description = "En testkonto"
                }
            });

        // Assert
        response.EnsureNoErrors();
        response.Data.Should().NotBeNull();
        response.Data!.CreateAccount.Should().NotBeNull();
        response.Data.CreateAccount!.AccountNumber.Should().Be("9999");
        response.Data.CreateAccount.Name.Should().Be("Test Konto");
        response.Data.CreateAccount.AccountType.Should().Be("expense");
        response.Data.CreateAccount.IsActive.Should().BeTrue();
        response.Data.CreateAccount.IsSystemAccount.Should().BeFalse();
    }

    [Fact]
    public async Task Mutation_UpdateAccount_UpdatesAccountSuccessfully()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "Update Account Test");

        // Create an account
        var createResponse = await graphqlClient.MutateAsync<CreateAccountResponse>("""
            mutation CreateAccount($input: CreateAccountInput!) {
                createAccount(input: $input) { id name }
            }
            """,
            new
            {
                input = new
                {
                    companyId,
                    accountNumber = "8888",
                    name = "Original Name",
                    accountType = "EXPENSE"
                }
            });

        createResponse.EnsureNoErrors();
        var accountId = createResponse.Data!.CreateAccount!.Id;

        // Wait for eventual consistency
        await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            return await repo.GetByIdAsync(accountId);
        });

        // Act - Update the account
        var updateResponse = await graphqlClient.MutateAsync<UpdateAccountResponse>("""
            mutation UpdateAccount($id: ID!, $input: UpdateAccountInput!) {
                updateAccount(id: $id, input: $input) {
                    id
                    name
                    description
                }
            }
            """,
            new
            {
                id = accountId,
                input = new
                {
                    name = "Updated Name",
                    description = "Updated description"
                }
            });

        // Assert
        updateResponse.EnsureNoErrors();

        var updatedAccount = await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            var account = await repo.GetByIdAsync(accountId);
            return account?.Name == "Updated Name" ? account : null;
        });

        updatedAccount.Should().NotBeNull();
        updatedAccount!.Name.Should().Be("Updated Name");
        updatedAccount.Description.Should().Be("Updated description");
    }

    [Fact]
    public async Task Mutation_DeactivateAccount_DeactivatesAccountSuccessfully()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "Deactivate Account Test");

        var createResponse = await graphqlClient.MutateAsync<CreateAccountResponse>("""
            mutation CreateAccount($input: CreateAccountInput!) {
                createAccount(input: $input) { id isActive }
            }
            """,
            new
            {
                input = new
                {
                    companyId,
                    accountNumber = "7777",
                    name = "Deactivate Test",
                    accountType = "EXPENSE"
                }
            });

        createResponse.EnsureNoErrors();
        var accountId = createResponse.Data!.CreateAccount!.Id;

        await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            return await repo.GetByIdAsync(accountId);
        });

        // Act
        var deactivateResponse = await graphqlClient.MutateAsync<DeactivateAccountResponse>("""
            mutation DeactivateAccount($id: ID!) {
                deactivateAccount(id: $id) {
                    id
                    isActive
                }
            }
            """,
            new { id = accountId });

        // Assert
        deactivateResponse.EnsureNoErrors();

        var deactivatedAccount = await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            var account = await repo.GetByIdAsync(accountId);
            return account?.IsActive == false ? account : null;
        });

        deactivatedAccount.Should().NotBeNull();
        deactivatedAccount!.IsActive.Should().BeFalse();
    }

    [Fact]
    public async Task Mutation_ReactivateAccount_ReactivatesAccountSuccessfully()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "Reactivate Account Test");

        var createResponse = await graphqlClient.MutateAsync<CreateAccountResponse>("""
            mutation CreateAccount($input: CreateAccountInput!) {
                createAccount(input: $input) { id }
            }
            """,
            new
            {
                input = new
                {
                    companyId,
                    accountNumber = "6666",
                    name = "Reactivate Test",
                    accountType = "EXPENSE"
                }
            });

        createResponse.EnsureNoErrors();
        var accountId = createResponse.Data!.CreateAccount!.Id;

        await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            return await repo.GetByIdAsync(accountId);
        });

        // Deactivate first
        await graphqlClient.MutateAsync<DeactivateAccountResponse>("""
            mutation { deactivateAccount(id: $id) { id } }
            """.Replace("$id", $"\"{accountId}\""));

        await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            var account = await repo.GetByIdAsync(accountId);
            return account?.IsActive == false ? account : null;
        });

        // Act
        var reactivateResponse = await graphqlClient.MutateAsync<ReactivateAccountResponse>("""
            mutation ReactivateAccount($id: ID!) {
                reactivateAccount(id: $id) {
                    id
                    isActive
                }
            }
            """,
            new { id = accountId });

        // Assert
        reactivateResponse.EnsureNoErrors();

        var reactivatedAccount = await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            var account = await repo.GetByIdAsync(accountId);
            return account?.IsActive == true ? account : null;
        });

        reactivatedAccount.Should().NotBeNull();
        reactivatedAccount!.IsActive.Should().BeTrue();
    }

    [Fact]
    public async Task Query_ActiveAccounts_ExcludesDeactivatedAccounts()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "Active Accounts Test");

        // Wait for standard accounts to be created
        var initialAccounts = await Eventually.GetListAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            return await repo.GetByCompanyIdAsync(companyId);
        }, 50, timeout: TimeSpan.FromSeconds(30)); // At least 50 standard accounts

        var initialActiveCount = initialAccounts.Count(a => a.IsActive);

        // Create a custom account
        var customAccountId = await CreateAccountAsync(graphqlClient, companyId, "5553", "Custom To Deactivate");

        await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            return await repo.GetByIdAsync(customAccountId);
        });

        // Deactivate the custom account
        await graphqlClient.MutateAsync<DeactivateAccountResponse>(
            $"mutation {{ deactivateAccount(id: \"{customAccountId}\") {{ id }} }}");

        await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            var account = await repo.GetByIdAsync(customAccountId);
            return account?.IsActive == false ? account : null;
        });

        // Act
        var response = await graphqlClient.QueryAsync<ActiveAccountsResponse>("""
            query ActiveAccounts($companyId: ID!) {
                activeAccounts(companyId: $companyId) {
                    id
                    name
                    isActive
                }
            }
            """,
            new { companyId });

        // Assert
        response.EnsureNoErrors();
        // Should have initial active accounts (deactivated one is excluded)
        response.Data!.ActiveAccounts.Should().HaveCount(initialActiveCount);
        response.Data.ActiveAccounts.Should().AllSatisfy(a => a.IsActive.Should().BeTrue());
        response.Data.ActiveAccounts.Should().NotContain(a => a.Id == customAccountId);
    }

    [Fact]
    public async Task Mutation_CreateAccount_FailsWithInvalidAccountNumber()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "Invalid Number Test");

        // Act - Try to create account with invalid number (too short)
        var response = await graphqlClient.MutateAsync<CreateAccountResponse>("""
            mutation CreateAccount($input: CreateAccountInput!) {
                createAccount(input: $input) {
                    id
                }
            }
            """,
            new
            {
                input = new
                {
                    companyId,
                    accountNumber = "12", // Invalid - must be 4-10 digits
                    name = "Invalid Account",
                    accountType = "EXPENSE"
                }
            });

        // Assert - Domain validation error is wrapped by GraphQL
        response.HasErrors.Should().BeTrue();
        // Check that the error is related to account validation (could be in message or extensions)
        var errorDetails = response.Errors!.First().Extensions?.GetValueOrDefault("details")?.ToString() ?? "";
        var hasAccountError = response.Errors!.Any(e =>
            e.Message.Contains("INVALID_ACCOUNT_NUMBER") ||
            e.Message.Contains("createAccount") ||
            errorDetails.Contains("INVALID_ACCOUNT_NUMBER") ||
            errorDetails.Contains("4-10 digits"));
        hasAccountError.Should().BeTrue("Expected an error related to invalid account number");
    }

    [Fact]
    public async Task Mutation_UpdateAccount_FailsForSystemAccount()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "System Account Update Test");

        // Wait for chart of accounts to be initialized
        var systemAccount = await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            var accounts = await repo.GetByCompanyIdAsync(companyId);
            return accounts.FirstOrDefault(a => a.IsSystemAccount);
        }, timeout: TimeSpan.FromSeconds(30));

        systemAccount.Should().NotBeNull("Expected at least one system account from chart initialization");

        // Act - Try to update a system account
        var response = await graphqlClient.MutateAsync<UpdateAccountResponse>("""
            mutation UpdateAccount($id: ID!, $input: UpdateAccountInput!) {
                updateAccount(id: $id, input: $input) {
                    id
                    name
                }
            }
            """,
            new
            {
                id = systemAccount!.Id,
                input = new { name = "Attempting to rename system account" }
            });

        // Assert
        response.HasErrors.Should().BeTrue();
        var errorDetails = response.Errors!.First().Extensions?.GetValueOrDefault("details")?.ToString() ?? "";
        (response.Errors!.Any(e => e.Message.Contains("SYSTEM_ACCOUNT_READONLY")) ||
         errorDetails.Contains("SYSTEM_ACCOUNT_READONLY") ||
         errorDetails.Contains("System accounts cannot be modified")).Should().BeTrue();
    }

    [Fact]
    public async Task Mutation_DeactivateAccount_FailsForSystemAccount()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "System Account Deactivate Test");

        // Wait for chart of accounts to be initialized
        var systemAccount = await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            var accounts = await repo.GetByCompanyIdAsync(companyId);
            return accounts.FirstOrDefault(a => a.IsSystemAccount);
        }, timeout: TimeSpan.FromSeconds(30));

        systemAccount.Should().NotBeNull("Expected at least one system account from chart initialization");

        // Act - Try to deactivate a system account
        var response = await graphqlClient.MutateAsync<DeactivateAccountResponse>("""
            mutation DeactivateAccount($id: ID!) {
                deactivateAccount(id: $id) {
                    id
                    isActive
                }
            }
            """,
            new { id = systemAccount!.Id });

        // Assert
        response.HasErrors.Should().BeTrue();
        var errorDetails = response.Errors!.First().Extensions?.GetValueOrDefault("details")?.ToString() ?? "";
        (response.Errors!.Any(e => e.Message.Contains("SYSTEM_ACCOUNT_READONLY")) ||
         errorDetails.Contains("SYSTEM_ACCOUNT_READONLY") ||
         errorDetails.Contains("System accounts cannot be deactivated")).Should().BeTrue();
    }

    [Fact]
    public async Task Mutation_DeactivateAccount_FailsWhenAlreadyInactive()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "Double Deactivate Test");
        var accountId = await CreateAccountAsync(graphqlClient, companyId, "4444", "Double Deactivate");

        await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            return await repo.GetByIdAsync(accountId);
        });

        // First deactivation - should succeed
        await graphqlClient.MutateAsync<DeactivateAccountResponse>("""
            mutation DeactivateAccount($id: ID!) {
                deactivateAccount(id: $id) { id }
            }
            """,
            new { id = accountId });

        await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            var account = await repo.GetByIdAsync(accountId);
            return account?.IsActive == false ? account : null;
        });

        // Act - Try to deactivate again
        var response = await graphqlClient.MutateAsync<DeactivateAccountResponse>("""
            mutation DeactivateAccount($id: ID!) {
                deactivateAccount(id: $id) {
                    id
                    isActive
                }
            }
            """,
            new { id = accountId });

        // Assert
        response.HasErrors.Should().BeTrue();
        var errorDetails = response.Errors!.First().Extensions?.GetValueOrDefault("details")?.ToString() ?? "";
        (response.Errors!.Any(e => e.Message.Contains("ACCOUNT_ALREADY_INACTIVE")) ||
         errorDetails.Contains("ACCOUNT_ALREADY_INACTIVE") ||
         errorDetails.Contains("already inactive")).Should().BeTrue();
    }

    [Fact]
    public async Task Mutation_ReactivateAccount_FailsWhenAlreadyActive()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "Reactivate Active Test");
        var accountId = await CreateAccountAsync(graphqlClient, companyId, "3333", "Already Active");

        await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            return await repo.GetByIdAsync(accountId);
        });

        // Act - Try to reactivate an already active account
        var response = await graphqlClient.MutateAsync<ReactivateAccountResponse>("""
            mutation ReactivateAccount($id: ID!) {
                reactivateAccount(id: $id) {
                    id
                    isActive
                }
            }
            """,
            new { id = accountId });

        // Assert
        response.HasErrors.Should().BeTrue();
        var errorDetails = response.Errors!.First().Extensions?.GetValueOrDefault("details")?.ToString() ?? "";
        (response.Errors!.Any(e => e.Message.Contains("ACCOUNT_ALREADY_ACTIVE")) ||
         errorDetails.Contains("ACCOUNT_ALREADY_ACTIVE") ||
         errorDetails.Contains("already active")).Should().BeTrue();
    }

    [Fact]
    public async Task Mutation_CreateAccount_AcceptsMinimumDigits()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "Min Digits Test");

        // Act - Create account with exactly 4 digits (minimum allowed)
        // Use a number not in the standard chart of accounts
        var response = await graphqlClient.MutateAsync<CreateAccountResponse>("""
            mutation CreateAccount($input: CreateAccountInput!) {
                createAccount(input: $input) {
                    id
                    accountNumber
                }
            }
            """,
            new
            {
                input = new
                {
                    companyId,
                    accountNumber = "9990", // Exactly 4 digits, not in standard chart
                    name = "Minimum Digits Account",
                    accountType = "ASSET"
                }
            });

        // Assert - Should succeed
        response.EnsureNoErrors();
        response.Data!.CreateAccount!.AccountNumber.Should().Be("9990");
    }

    [Fact]
    public async Task Mutation_CreateAccount_FailsWithTooFewDigits()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "Too Few Digits Test");

        // Act - Create account with 3 digits (below minimum)
        var response = await graphqlClient.MutateAsync<CreateAccountResponse>("""
            mutation CreateAccount($input: CreateAccountInput!) {
                createAccount(input: $input) {
                    id
                }
            }
            """,
            new
            {
                input = new
                {
                    companyId,
                    accountNumber = "999", // Only 3 digits
                    name = "Too Few Digits",
                    accountType = "EXPENSE"
                }
            });

        // Assert
        response.HasErrors.Should().BeTrue();
        var errorDetails = response.Errors!.First().Extensions?.GetValueOrDefault("details")?.ToString() ?? "";
        (response.Errors!.Any(e => e.Message.Contains("INVALID_ACCOUNT_NUMBER")) ||
         errorDetails.Contains("INVALID_ACCOUNT_NUMBER") ||
         errorDetails.Contains("4-10 digits")).Should().BeTrue();
    }

    [Fact]
    public async Task Mutation_CreateAccount_IsDeterministic()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var companyId = await CreateCompanyAsync(graphqlClient, "Deterministic ID Test");

        // Act - Create same account twice (use number not in standard chart)
        var response1 = await graphqlClient.MutateAsync<CreateAccountResponse>("""
            mutation CreateAccount($input: CreateAccountInput!) {
                createAccount(input: $input) {
                    id
                    accountNumber
                }
            }
            """,
            new
            {
                input = new
                {
                    companyId,
                    accountNumber = "9991",
                    name = "Deterministic Test",
                    accountType = "EXPENSE"
                }
            });

        response1.EnsureNoErrors();
        var firstId = response1.Data!.CreateAccount!.Id;

        // Wait for eventual consistency
        await Eventually.GetAsync(async () =>
        {
            var repo = GetService<IAccountRepository>();
            return await repo.GetByIdAsync(firstId);
        });

        // Second attempt with same input
        var response2 = await graphqlClient.MutateAsync<CreateAccountResponse>("""
            mutation CreateAccount($input: CreateAccountInput!) {
                createAccount(input: $input) {
                    id
                    accountNumber
                }
            }
            """,
            new
            {
                input = new
                {
                    companyId,
                    accountNumber = "9991",
                    name = "Deterministic Test",
                    accountType = "EXPENSE"
                }
            });

        // Assert - Second call should fail with ACCOUNT_EXISTS error (idempotency)
        response2.HasErrors.Should().BeTrue();
        var errorDetails = response2.Errors!.First().Extensions?.GetValueOrDefault("details")?.ToString() ?? "";
        (response2.Errors!.Any(e => e.Message.Contains("ACCOUNT_EXISTS")) ||
         errorDetails.Contains("ACCOUNT_EXISTS") ||
         errorDetails.Contains("already exists")).Should().BeTrue();
    }

    [Fact]
    public async Task Mutation_UpdateAccount_FailsForNonExistentAccount()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var nonExistentAccountId = $"account-{Guid.NewGuid():N}";

        // Act - Try to update a non-existent account
        var response = await graphqlClient.MutateAsync<UpdateAccountResponse>("""
            mutation UpdateAccount($id: ID!, $input: UpdateAccountInput!) {
                updateAccount(id: $id, input: $input) {
                    id
                    name
                }
            }
            """,
            new
            {
                id = nonExistentAccountId,
                input = new { name = "New Name" }
            });

        // Assert - Domain exception is wrapped by GraphQL/EventFlow
        response.HasErrors.Should().BeTrue();
        var errorInfo = string.Join(" ", response.Errors!.Select(e =>
            e.Message + " " + (e.Extensions?.GetValueOrDefault("details")?.ToString() ?? "")));
        (errorInfo.Contains("ACCOUNT_NOT_FOUND") ||
         errorInfo.Contains("Account does not exist") ||
         errorInfo.Contains("does not exist") ||
         errorInfo.Contains("updateAccount")).Should().BeTrue(
             $"Expected account not found error, got: {errorInfo}");
    }

    [Fact]
    public async Task Mutation_DeactivateAccount_FailsForNonExistentAccount()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var nonExistentAccountId = $"account-{Guid.NewGuid():N}";

        // Act - Try to deactivate a non-existent account
        var response = await graphqlClient.MutateAsync<DeactivateAccountResponse>("""
            mutation DeactivateAccount($id: ID!) {
                deactivateAccount(id: $id) {
                    id
                    isActive
                }
            }
            """,
            new { id = nonExistentAccountId });

        // Assert - Domain exception is wrapped by GraphQL/EventFlow
        response.HasErrors.Should().BeTrue();
        var errorInfo = string.Join(" ", response.Errors!.Select(e =>
            e.Message + " " + (e.Extensions?.GetValueOrDefault("details")?.ToString() ?? "")));
        (errorInfo.Contains("ACCOUNT_NOT_FOUND") ||
         errorInfo.Contains("Account does not exist") ||
         errorInfo.Contains("does not exist") ||
         errorInfo.Contains("deactivateAccount")).Should().BeTrue(
             $"Expected account not found error, got: {errorInfo}");
    }

    [Fact]
    public async Task Mutation_ReactivateAccount_FailsForNonExistentAccount()
    {
        // Arrange
        var graphqlClient = new GraphQLTestClient(Client);
        var nonExistentAccountId = $"account-{Guid.NewGuid():N}";

        // Act - Try to reactivate a non-existent account
        var response = await graphqlClient.MutateAsync<ReactivateAccountResponse>("""
            mutation ReactivateAccount($id: ID!) {
                reactivateAccount(id: $id) {
                    id
                    isActive
                }
            }
            """,
            new { id = nonExistentAccountId });

        // Assert - Domain exception is wrapped by GraphQL/EventFlow
        response.HasErrors.Should().BeTrue();
        var errorInfo = string.Join(" ", response.Errors!.Select(e =>
            e.Message + " " + (e.Extensions?.GetValueOrDefault("details")?.ToString() ?? "")));
        (errorInfo.Contains("ACCOUNT_NOT_FOUND") ||
         errorInfo.Contains("Account does not exist") ||
         errorInfo.Contains("does not exist") ||
         errorInfo.Contains("reactivateAccount")).Should().BeTrue(
             $"Expected account not found error, got: {errorInfo}");
    }

    private async Task<string> CreateCompanyAsync(GraphQLTestClient client, string name)
    {
        var response = await client.MutateAsync<CreateCompanyResponse>("""
            mutation CreateCompany($input: CreateCompanyInput!) {
                createCompany(input: $input) { id }
            }
            """,
            new { input = new { name } });

        response.EnsureNoErrors();
        var companyId = response.Data!.CreateCompany!.Id;

        // Set the company ID header for subsequent requests
        client.SetCompanyId(companyId);

        return companyId;
    }

    private async Task<string> CreateAccountAsync(GraphQLTestClient client, string companyId, string number, string name)
    {
        var response = await client.MutateAsync<CreateAccountResponse>("""
            mutation CreateAccount($input: CreateAccountInput!) {
                createAccount(input: $input) { id }
            }
            """,
            new
            {
                input = new
                {
                    companyId,
                    accountNumber = number,
                    name,
                    accountType = "EXPENSE"
                }
            });

        response.EnsureNoErrors();
        return response.Data!.CreateAccount!.Id;
    }

    // Response DTOs
    private class AccountsResponse { public List<AccountDto> Accounts { get; set; } = []; }
    private class ActiveAccountsResponse { public List<AccountDto> ActiveAccounts { get; set; } = []; }
    private class AccountResponse { public AccountDto? Account { get; set; } }
    private class CreateAccountResponse { public AccountDto? CreateAccount { get; set; } }
    private class UpdateAccountResponse { public AccountDto? UpdateAccount { get; set; } }
    private class DeactivateAccountResponse { public AccountDto? DeactivateAccount { get; set; } }
    private class ReactivateAccountResponse { public AccountDto? ReactivateAccount { get; set; } }
    private class CreateCompanyResponse { public CompanyDto? CreateCompany { get; set; } }

    private class AccountDto
    {
        public string Id { get; set; } = string.Empty;
        public string CompanyId { get; set; } = string.Empty;
        public string AccountNumber { get; set; } = string.Empty;
        public string Name { get; set; } = string.Empty;
        public string AccountType { get; set; } = string.Empty;
        public string? Description { get; set; }
        public bool IsActive { get; set; }
        public bool IsSystemAccount { get; set; }
    }

    private class CompanyDto { public string Id { get; set; } = string.Empty; }
}
