using System.Net.Http.Json;
using CashLineERP.Contracts.Finance;

namespace CashLineERP.Api.Tests;

public sealed class CashAccountAndTreasuryTransferQaTests : IClassFixture<ApiTestFactory>
{
    private readonly HttpClient _client;

    public CashAccountAndTreasuryTransferQaTests(ApiTestFactory factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task Cash_Accounts_And_Treasury_Transfer_HTTP_Flow_Work_End_To_End()
    {
        await _client.AuthenticateAsFinanceMakerAsync();

        var createCashAccountResponse = await _client.PostAsJsonAsync("/api/v1/finance/cash-accounts", new CreateCashAccountRequest(
            AccountCode: "CASH-EGP-002",
            AccountName: "Branch Cash Desk",
            AccountType: "CASH",
            CurrencyCode: "EGP",
            BranchId: 1,
            OpeningBalanceAmount: 1000m));
        Assert.True(createCashAccountResponse.IsSuccessStatusCode, await createCashAccountResponse.Content.ReadAsStringAsync());
        var destinationAccount = await createCashAccountResponse.Content.ReadFromJsonAsync<CashAccountResponse>();
        Assert.NotNull(destinationAccount);

        var createTransferResponse = await _client.PostAsJsonAsync("/api/v1/finance/treasury-transfers", new CreateTreasuryTransferRequest(
            FromCashAccountId: 2,
            ToCashAccountId: destinationAccount!.CashAccountId,
            TransferDate: new DateOnly(2026, 4, 30),
            CurrencyCode: "EGP",
            AmountAmount: 500m,
            ReferenceNumber: "TREASURY-HTTP-0001",
            Notes: "HTTP treasury transfer"));
        Assert.True(createTransferResponse.IsSuccessStatusCode, await createTransferResponse.Content.ReadAsStringAsync());
        var transfer = await createTransferResponse.Content.ReadFromJsonAsync<TreasuryTransferResponse>();
        Assert.NotNull(transfer);

        var submitResponse = await _client.PostAsync($"/api/v1/finance/treasury-transfers/{transfer!.TreasuryTransferId}/submit", null);
        Assert.True(submitResponse.IsSuccessStatusCode, await submitResponse.Content.ReadAsStringAsync());

        await _client.AuthenticateAsFinanceCheckerAsync();
        var approveResponse = await _client.PostAsync($"/api/v1/finance/treasury-transfers/{transfer.TreasuryTransferId}/approve", null);
        Assert.True(approveResponse.IsSuccessStatusCode, await approveResponse.Content.ReadAsStringAsync());

        var postResponse = await _client.PostAsync($"/api/v1/finance/treasury-transfers/{transfer.TreasuryTransferId}/post", null);
        Assert.True(postResponse.IsSuccessStatusCode, await postResponse.Content.ReadAsStringAsync());
        var postedTransfer = await postResponse.Content.ReadFromJsonAsync<TreasuryTransferResponse>();
        Assert.NotNull(postedTransfer);
        Assert.Equal("POSTED", postedTransfer!.StatusCode);
        Assert.NotNull(postedTransfer.GeneralLedgerBatchId);
        Assert.Equal("EGP", postedTransfer.BaseCurrencyCode);
        Assert.Equal(1m, postedTransfer.FxRateToBase);
        Assert.Equal(500m, postedTransfer.BaseAmount);

        await _client.AuthenticateAsFinanceMakerAsync();
        var sourceAccountResponse = await _client.GetAsync("/api/v1/finance/cash-accounts/2");
        var destinationAccountResponse = await _client.GetAsync($"/api/v1/finance/cash-accounts/{destinationAccount.CashAccountId}");
        Assert.True(sourceAccountResponse.IsSuccessStatusCode, await sourceAccountResponse.Content.ReadAsStringAsync());
        Assert.True(destinationAccountResponse.IsSuccessStatusCode, await destinationAccountResponse.Content.ReadAsStringAsync());
        var sourceAccount = await sourceAccountResponse.Content.ReadFromJsonAsync<CashAccountResponse>();
        var refreshedDestinationAccount = await destinationAccountResponse.Content.ReadFromJsonAsync<CashAccountResponse>();
        Assert.NotNull(sourceAccount);
        Assert.NotNull(refreshedDestinationAccount);
        Assert.Equal(24500m, sourceAccount!.CurrentBalanceAmount);
        Assert.Equal(1500m, refreshedDestinationAccount!.CurrentBalanceAmount);
    }
}
