using System.Text.Json.Nodes;
using Csob.Client;

namespace Csob.Services;

/// <summary>AISP – account information (accounts, balance, transactions, standing orders, direct debits).</summary>
public sealed class AccountsService
{
    private readonly CsobApiAccessor _accessor;

    public AccountsService(CsobApiAccessor accessor) => _accessor = accessor;

    public Task<JsonNode?> ListAsync(int? page, int? size, string? sort, string? order, CancellationToken ct)
        => _accessor.Client.GetAsync(CsobApiPaths.Accounts, Paging(page, size, sort, order), ct);

    public Task<JsonNode?> BalanceAsync(string accountId, string? currency, CancellationToken ct)
        => _accessor.Client.GetAsync(CsobApiPaths.Balance(accountId),
            new Dictionary<string, string?> { ["currency"] = currency }, ct);

    public Task<JsonNode?> TransactionsAsync(string accountId, TransactionQuery query, CancellationToken ct)
        => _accessor.Client.GetAsync(CsobApiPaths.Transactions(accountId), query.ToDictionary(), ct);

    public Task<JsonNode?> AwaitingTransactionsAsync(string accountId, int? page, int? size, CancellationToken ct)
        => _accessor.Client.GetAsync(CsobApiPaths.AwaitingTransactions(accountId), Paging(page, size, null, null), ct);

    public Task<JsonNode?> StandingOrdersAsync(string accountId, int? page, int? size, CancellationToken ct)
        => _accessor.Client.GetAsync(CsobApiPaths.AccountStandingOrders(accountId), Paging(page, size, null, null), ct);

    public Task<JsonNode?> StandingOrderDetailAsync(string accountId, string standingOrderId, CancellationToken ct)
        => _accessor.Client.GetAsync(CsobApiPaths.AccountStandingOrder(accountId, standingOrderId), null, ct);

    public Task<JsonNode?> DirectDebitsAsync(string accountId, int? page, int? size, CancellationToken ct)
        => _accessor.Client.GetAsync(CsobApiPaths.AccountDirectDebits(accountId), Paging(page, size, null, null), ct);

    private static Dictionary<string, string?> Paging(int? page, int? size, string? sort, string? order) => new()
    {
        ["page"] = page?.ToString(),
        ["size"] = size?.ToString(),
        ["sort"] = sort,
        ["order"] = order,
    };
}

/// <summary>Optional filters for the transactions listing (forwarded as query parameters).</summary>
public sealed class TransactionQuery
{
    public int? Page { get; set; }
    public int? Size { get; set; }
    public string? Sort { get; set; }
    public string? Order { get; set; }
    /// <summary>ISO date (YYYY-MM-DD) lower bound.</summary>
    public string? DateFrom { get; set; }
    /// <summary>ISO date (YYYY-MM-DD) upper bound.</summary>
    public string? DateTo { get; set; }

    public Dictionary<string, string?> ToDictionary() => new()
    {
        ["page"] = Page?.ToString(),
        ["size"] = Size?.ToString(),
        ["sort"] = Sort,
        ["order"] = Order,
        ["dateFrom"] = DateFrom,
        ["dateTo"] = DateTo,
    };
}
