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

namespace CashLineERP.Api.Tests;

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

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

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

        var outbound = await CreateAndActivateEndpointAsync("HTTP Paymob outbound", "PAYMOB", "OUTBOUND", "/checkout");
        var inbound = await CreateAndActivateEndpointAsync("HTTP Paymob callback", "PAYMOB", "INBOUND", "/callback");

        var createResponse = await _client.PostAsJsonAsync("/api/v1/finance/payment-channels", new CreatePaymentChannelConfigurationRequest(
            ChannelName: "HTTP Paymob saved-card channel",
            BranchId: 1,
            IntegrationProviderCode: "PAYMOB",
            ChannelTypeCode: "CARD_TOKEN",
            UsageCode: "CUSTOMER_COLLECTION",
            CurrencyCode: "EGP",
            OutboundIntegrationEndpointId: outbound.IntegrationEndpointId,
            InboundIntegrationEndpointId: inbound.IntegrationEndpointId,
            SupportsCardTokenReferences: true,
            UsesWalletRuleEngine: false,
            RequiresCustomerReference: true,
            MinimumAmount: 10m,
            MaximumAmount: 5000m,
            SettlementLeadDays: 1,
            Notes: "HTTP payment channel"));
        Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode);
        var created = await createResponse.Content.ReadFromJsonAsync<PaymentChannelConfigurationResponse>();
        Assert.NotNull(created);
        Assert.Equal("DRAFT", created!.StatusCode);

        var submitResponse = await _client.PostAsync($"/api/v1/finance/payment-channels/{created.PaymentChannelConfigurationId}/submit", null);
        Assert.Equal(HttpStatusCode.OK, submitResponse.StatusCode);

        await _client.AuthenticateAsFinanceCheckerAsync();

        var approveResponse = await _client.PostAsync($"/api/v1/finance/payment-channels/{created.PaymentChannelConfigurationId}/approve", null);
        Assert.Equal(HttpStatusCode.OK, approveResponse.StatusCode);

        var activateResponse = await _client.PostAsync($"/api/v1/finance/payment-channels/{created.PaymentChannelConfigurationId}/activate", null);
        Assert.Equal(HttpStatusCode.OK, activateResponse.StatusCode);
        var activated = await activateResponse.Content.ReadFromJsonAsync<PaymentChannelConfigurationResponse>();
        Assert.NotNull(activated);
        Assert.True(activated!.IsActive);

        var detailResponse = await _client.GetAsync($"/api/v1/finance/payment-channels/{created.PaymentChannelConfigurationId}");
        Assert.Equal(HttpStatusCode.OK, detailResponse.StatusCode);

        var listResponse = await _client.GetAsync("/api/v1/finance/payment-channels?activeOnly=true&integrationProviderCode=PAYMOB&channelTypeCode=CARD_TOKEN&usageCode=CUSTOMER_COLLECTION");
        Assert.Equal(HttpStatusCode.OK, listResponse.StatusCode);
        var list = await listResponse.Content.ReadFromJsonAsync<PaymentChannelConfigurationResponse[]>();
        Assert.NotNull(list);
        Assert.Single(list!);
    }

    private async Task<IntegrationEndpointResponse> CreateAndActivateEndpointAsync(string endpointName, string providerCode, string directionCode, string relativePath)
    {
        var createResponse = await _client.PostAsJsonAsync("/api/v1/integrations/endpoints", new CreateIntegrationEndpointRequest(
            EndpointName: endpointName,
            IntegrationProviderCode: providerCode,
            EnvironmentCode: "UAT",
            DirectionCode: directionCode,
            TransportCode: "REST",
            HttpMethodCode: "POST",
            BaseUrl: "https://gateway.uat.example",
            RelativePath: relativePath,
            AuthenticationModeCode: "SIGNATURE",
            CredentialReference: $"secret://{providerCode.ToLowerInvariant()}/uat/key",
            TimeoutSeconds: 20,
            RetryPolicyCode: "STANDARD",
            MaxRetryCount: 2,
            IsIdempotencyKeyRequired: true,
            Notes: "HTTP payment channel endpoint"));
        Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode);
        var created = await createResponse.Content.ReadFromJsonAsync<IntegrationEndpointResponse>();
        Assert.NotNull(created);

        var submitResponse = await _client.PostAsync($"/api/v1/integrations/endpoints/{created!.IntegrationEndpointId}/submit", null);
        Assert.Equal(HttpStatusCode.OK, submitResponse.StatusCode);

        await _client.AuthenticateAsFinanceCheckerAsync();

        var approveResponse = await _client.PostAsync($"/api/v1/integrations/endpoints/{created.IntegrationEndpointId}/approve", null);
        Assert.Equal(HttpStatusCode.OK, approveResponse.StatusCode);

        var activateResponse = await _client.PostAsync($"/api/v1/integrations/endpoints/{created.IntegrationEndpointId}/activate", null);
        Assert.Equal(HttpStatusCode.OK, activateResponse.StatusCode);
        var activated = await activateResponse.Content.ReadFromJsonAsync<IntegrationEndpointResponse>();
        Assert.NotNull(activated);

        await _client.AuthenticateAsFinanceMakerAsync();
        return activated!;
    }
}
