using Dapper;
using Npgsql;

namespace Modules.ERP.Items.Search;

public sealed class SearchItemsHandler(NpgsqlDataSource dataSource)
{
    public async Task<SearchItemsResponse> HandleAsync(SearchItemsRequest request, CancellationToken ct)
    {
        var page = Math.Max(request.Page, 1);
        var pageSize = Math.Clamp(request.PageSize, 1, 500);
        var offset = (page - 1) * pageSize;
        var keyword = string.IsNullOrWhiteSpace(request.Keyword) ? null : request.Keyword.Trim();

        const string sql = """
        select
            p.id,
            p.code,
            p.name,
            p.category_name as CategoryName,
            p.specification,
            p.unit,
            p.barcode,
            p.default_warehouse_id as DefaultWarehouseId,
            p.default_warehouse_name as DefaultWarehouseName,
            p.lot_managed as LotManaged,
            p.expiry_managed as ExpiryManaged,
            p.active,
            p.version
        from erp_item_search_projection p
        where (@Keyword is null or p.search_text ilike '%' || @Keyword || '%')
        order by p.code
        limit @PageSize offset @Offset;

        select count(*)::int
        from erp_item_search_projection p
        where (@Keyword is null or p.search_text ilike '%' || @Keyword || '%');
        """;

        await using var connection = await dataSource.OpenConnectionAsync(ct);
        using var multi = await connection.QueryMultipleAsync(new CommandDefinition(sql, new { Keyword = keyword, PageSize = pageSize, Offset = offset }, cancellationToken: ct));
        var items = (await multi.ReadAsync<ItemMasterRow>()).AsList();
        var count = await multi.ReadSingleAsync<int>();
        return new(items, count);
    }
}
