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

namespace CashLineERP.Api.Tests;

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

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

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

        var createReceiptResponse = await _client.PostAsJsonAsync("/api/v1/finance/ar-receipts", new CreateAccountsReceivableReceiptRequest(
            CustomerId: 2,
            ReceiptDate: new DateOnly(2026, 5, 14),
            ReceiptMethod: "BANK_TRANSFER",
            CurrencyCode: "EGP",
            AmountAmount: 220m,
            ReferenceNumber: "HTTP-RFND-0001",
            Notes: "Receipt for customer refund",
            Allocations: []));
        Assert.Equal(HttpStatusCode.OK, createReceiptResponse.StatusCode);
        var createdReceipt = await createReceiptResponse.Content.ReadFromJsonAsync<AccountsReceivableReceiptResponse>();
        Assert.NotNull(createdReceipt);

        var submitReceiptResponse = await _client.PostAsync($"/api/v1/finance/ar-receipts/{createdReceipt!.AccountsReceivableReceiptId}/submit", null);
        Assert.Equal(HttpStatusCode.OK, submitReceiptResponse.StatusCode);

        await _client.AuthenticateAsFinanceCheckerAsync();

        var approveReceiptResponse = await _client.PostAsync($"/api/v1/finance/ar-receipts/{createdReceipt.AccountsReceivableReceiptId}/approve", null);
        Assert.Equal(HttpStatusCode.OK, approveReceiptResponse.StatusCode);

        var postReceiptResponse = await _client.PostAsync($"/api/v1/finance/ar-receipts/{createdReceipt.AccountsReceivableReceiptId}/post", null);
        Assert.Equal(HttpStatusCode.OK, postReceiptResponse.StatusCode);

        await _client.AuthenticateAsFinanceMakerAsync();

        var createRefundResponse = await _client.PostAsJsonAsync("/api/v1/finance/customer-refunds", new CreateCustomerRefundRequest(
            CustomerId: 2,
            SourceAccountsReceivableReceiptId: createdReceipt.AccountsReceivableReceiptId,
            RefundDate: new DateOnly(2026, 5, 15),
            RefundMethod: "BANK_TRANSFER",
            CurrencyCode: "EGP",
            AmountAmount: 90m,
            PaymentChannelConfigurationId: null,
            ReferenceNumber: "HTTP-RFND-0001",
            Notes: "HTTP customer refund"));
        Assert.Equal(HttpStatusCode.OK, createRefundResponse.StatusCode);

        var refund = await createRefundResponse.Content.ReadFromJsonAsync<CustomerRefundResponse>();
        Assert.NotNull(refund);
        Assert.Equal("DRAFT", refund!.StatusCode);

        var submitRefundResponse = await _client.PostAsync($"/api/v1/finance/customer-refunds/{refund.CustomerRefundId}/submit", null);
        Assert.Equal(HttpStatusCode.OK, submitRefundResponse.StatusCode);

        await _client.AuthenticateAsFinanceCheckerAsync();

        var approveRefundResponse = await _client.PostAsync($"/api/v1/finance/customer-refunds/{refund.CustomerRefundId}/approve", null);
        Assert.Equal(HttpStatusCode.OK, approveRefundResponse.StatusCode);

        var postRefundResponse = await _client.PostAsync($"/api/v1/finance/customer-refunds/{refund.CustomerRefundId}/post", null);
        Assert.Equal(HttpStatusCode.OK, postRefundResponse.StatusCode);
        var postedRefund = await postRefundResponse.Content.ReadFromJsonAsync<CustomerRefundResponse>();
        Assert.NotNull(postedRefund);
        Assert.Equal("POSTED", postedRefund!.StatusCode);

        await _client.AuthenticateAsFinanceMakerAsync();

        var createBankStatementResponse = await _client.PostAsJsonAsync("/api/v1/finance/bank-statements", new CreateBankStatementRequest(
            BankAccountCode: "CIB-EGP-HTTP-RFND-001",
            StatementDate: new DateOnly(2026, 5, 15),
            CurrencyCode: "EGP",
            OpeningBalanceAmount: 2000m,
            ClosingBalanceAmount: 1910m,
            Lines:
            [
                new CreateBankStatementLineRequest(
                    TransactionDate: new DateOnly(2026, 5, 15),
                    ExternalReference: "HTTP-RFND-0001",
                    DescriptionText: "Customer refund bank transfer",
                    DebitAmount: 90m,
                    CreditAmount: 0m,
                    RunningBalanceAmount: 1910m)
            ]));
        Assert.Equal(HttpStatusCode.OK, createBankStatementResponse.StatusCode);
        var bankStatement = await createBankStatementResponse.Content.ReadFromJsonAsync<BankStatementResponse>();
        Assert.NotNull(bankStatement);

        var runSettlementResponse = await _client.PostAsJsonAsync("/api/v1/finance/reconciliations/run-settlement", new RunReceiptReconciliationRequest(
            AccountingPeriodId: 2,
            BankStatementId: bankStatement!.BankStatementId,
            ActorUserId: 4));
        Assert.Equal(HttpStatusCode.OK, runSettlementResponse.StatusCode);
        var run = await runSettlementResponse.Content.ReadFromJsonAsync<ReconciliationRunResponse>();
        Assert.NotNull(run);
        Assert.Contains(run!.Items, item => item.MatchedDocumentType == "CUSTOMER_REFUND" && item.CustomerRefundId == postedRefund.CustomerRefundId);

        var getRefundResponse = await _client.GetAsync($"/api/v1/finance/customer-refunds/{postedRefund.CustomerRefundId}");
        Assert.Equal(HttpStatusCode.OK, getRefundResponse.StatusCode);
    }
}
