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

namespace Books.Api.EventFlow.Repositories;

public class ProductRepository(NpgsqlDataSource dataSource) : IProductRepository
{
    private const string SelectColumns = """
        aggregate_id AS Id,
        company_id AS CompanyId,
        product_number AS ProductNumber,
        name AS Name,
        description AS Description,
        unit_price AS UnitPrice,
        vat_code AS VatCode,
        unit AS Unit,
        default_account_id AS DefaultAccountId,
        ean AS Ean,
        manufacturer AS Manufacturer,
        is_active AS IsActive,
        create_time AS CreatedAt,
        update_time AS UpdatedAt
        """;

    public async Task<ProductReadModelDto?> GetByIdAsync(string id, CancellationToken cancellationToken = default)
    {
        await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);

        var sql = $"""
            SELECT {SelectColumns}
            FROM product_read_models
            WHERE aggregate_id = @Id
            """;

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

    public async Task<IReadOnlyList<ProductReadModelDto>> GetByCompanyIdAsync(string companyId, CancellationToken cancellationToken = default)
    {
        await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);

        var sql = $"""
            SELECT {SelectColumns}
            FROM product_read_models
            WHERE company_id = @CompanyId
            ORDER BY COALESCE(product_number, ''), name
            """;

        var result = await connection.QueryAsync<ProductReadModelDto>(sql, new { CompanyId = companyId });
        return result.ToList();
    }

    public async Task<IReadOnlyList<ProductReadModelDto>> GetActiveByCompanyIdAsync(string companyId, CancellationToken cancellationToken = default)
    {
        await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);

        var sql = $"""
            SELECT {SelectColumns}
            FROM product_read_models
            WHERE company_id = @CompanyId AND is_active = TRUE
            ORDER BY COALESCE(product_number, ''), name
            """;

        var result = await connection.QueryAsync<ProductReadModelDto>(sql, new { CompanyId = companyId });
        return result.ToList();
    }

    public async Task<ProductReadModelDto?> GetByCompanyAndNumberAsync(string companyId, string productNumber, CancellationToken cancellationToken = default)
    {
        await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);

        var sql = $"""
            SELECT {SelectColumns}
            FROM product_read_models
            WHERE company_id = @CompanyId AND product_number = @ProductNumber
            """;

        return await connection.QuerySingleOrDefaultAsync<ProductReadModelDto>(sql, new { CompanyId = companyId, ProductNumber = productNumber });
    }
}
