using Books.Api.Domain.Companies;
using Books.Api.EventFlow.ReadModels;
using Dapper;
using Npgsql;

namespace Books.Api.EventFlow.Repositories;

public class CompanyRepository(NpgsqlDataSource dataSource) : ICompanyRepository
{
    public async Task<CompanyReadModelDto?> GetByIdAsync(string id, CancellationToken cancellationToken = default)
    {
        await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);

        const string sql = """
            SELECT
                aggregate_id AS Id,
                name AS Name,
                cvr AS Cvr,
                address AS Address,
                postal_code AS PostalCode,
                city AS City,
                country AS Country,
                fiscal_year_start_month AS FiscalYearStartMonth,
                currency AS Currency,
                vat_registered AS VatRegistered,
                vat_period_frequency AS VatPeriodFrequency,
                create_time AS CreatedAt,
                updated_time AS UpdatedAt
            FROM company_read_models
            WHERE aggregate_id = @Id
            """;

        return await connection.QuerySingleOrDefaultAsync<CompanyReadModelDto>(sql, new { Id = id });
    }

    public async Task<IEnumerable<CompanyReadModelDto>> GetByIds(List<CompanyId> ids,
        CancellationToken cancellationToken = default)
    {
        await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);

        const string sql = """
            SELECT
                aggregate_id AS Id,
                name AS Name,
                cvr AS Cvr,
                address AS Address,
                postal_code AS PostalCode,
                city AS City,
                country AS Country,
                fiscal_year_start_month AS FiscalYearStartMonth,
                currency AS Currency,
                vat_registered AS VatRegistered,
                vat_period_frequency AS VatPeriodFrequency,
                create_time AS CreatedAt,
                updated_time AS UpdatedAt
            FROM company_read_models
            WHERE aggregate_id = ANY(@Ids)
            """;

        return await connection.QueryAsync<CompanyReadModelDto>(sql, new { Ids = ids.Select(i => i.Value).ToArray() });
    }

    public async Task<IReadOnlyList<CompanyReadModelDto>> GetAllAsync(CancellationToken cancellationToken = default)
    {
        await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);

        const string sql = """
            SELECT
                aggregate_id AS Id,
                name AS Name,
                cvr AS Cvr,
                address AS Address,
                postal_code AS PostalCode,
                city AS City,
                country AS Country,
                fiscal_year_start_month AS FiscalYearStartMonth,
                currency AS Currency,
                vat_registered AS VatRegistered,
                vat_period_frequency AS VatPeriodFrequency,
                create_time AS CreatedAt,
                updated_time AS UpdatedAt
            FROM company_read_models
            ORDER BY name
            """;

        var result = await connection.QueryAsync<CompanyReadModelDto>(sql);
        return result.ToList();
    }
}
