using CashLineERP.Application.Finance;
using CashLineERP.Application.Integration;
using CashLineERP.Contracts.Finance;
using CashLineERP.Contracts.Integration;
using CashLineERP.Infrastructure.Persistence.Repositories;

namespace CashLineERP.Api.Tests;

public sealed class PaymentChannelConfigurationServiceQaTests
{
    [Fact]
    public void Payment_Channel_Activation_Requires_Active_Matching_Endpoints_And_Preserves_Feature_Flags()
    {
        using var dbContext = QaDbContextFactory.CreateContext();

        var integrationService = new IntegrationEndpointRegistryService(new IntegrationEndpointRegistryRepository(dbContext));
        var paymentChannelService = new PaymentChannelConfigurationService(new PaymentChannelConfigurationRepository(dbContext));

        var outbound = CreateAndActivateEndpoint(integrationService, "Paymob outbound", "PAYMOB", "OUTBOUND", "/checkout", 3, 4);
        var inbound = CreateAndActivateEndpoint(integrationService, "Paymob callback", "PAYMOB", "INBOUND", "/callback", 3, 4);

        var created = paymentChannelService.CreatePaymentChannel(new CreatePaymentChannelConfigurationRequest(
            ChannelName: "Paymob saved-card collections",
            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: "Saved-card channel"));

        paymentChannelService.SubmitPaymentChannel(created.PaymentChannelConfigurationId, 3);
        paymentChannelService.ApprovePaymentChannel(created.PaymentChannelConfigurationId, 4);
        var activated = paymentChannelService.ActivatePaymentChannel(created.PaymentChannelConfigurationId, 4);

        Assert.True(activated.IsActive);
        Assert.True(activated.SupportsCardTokenReferences);
        Assert.False(activated.UsesWalletRuleEngine);
        Assert.Equal(outbound.IntegrationEndpointId, activated.OutboundIntegrationEndpointId);
        Assert.Equal(inbound.IntegrationEndpointId, activated.InboundIntegrationEndpointId);
    }

    [Fact]
    public void Payment_Channel_Maker_Checker_Blocks_Self_Approval()
    {
        using var dbContext = QaDbContextFactory.CreateContext();

        var integrationService = new IntegrationEndpointRegistryService(new IntegrationEndpointRegistryRepository(dbContext));
        var paymentChannelService = new PaymentChannelConfigurationService(new PaymentChannelConfigurationRepository(dbContext));

        var outbound = CreateAndActivateEndpoint(integrationService, "Fawry outbound", "FAWRY", "OUTBOUND", "/collect", 3, 4);

        var created = paymentChannelService.CreatePaymentChannel(new CreatePaymentChannelConfigurationRequest(
            ChannelName: "Fawry wallet collections",
            BranchId: null,
            IntegrationProviderCode: "FAWRY",
            ChannelTypeCode: "MOBILE_WALLET",
            UsageCode: "CUSTOMER_COLLECTION",
            CurrencyCode: "EGP",
            OutboundIntegrationEndpointId: outbound.IntegrationEndpointId,
            InboundIntegrationEndpointId: null,
            SupportsCardTokenReferences: false,
            UsesWalletRuleEngine: true,
            RequiresCustomerReference: true,
            MinimumAmount: 5m,
            MaximumAmount: 3000m,
            SettlementLeadDays: 2,
            Notes: "Wallet setup"));

        paymentChannelService.SubmitPaymentChannel(created.PaymentChannelConfigurationId, 3);

        var exception = Assert.Throws<InvalidOperationException>(() =>
            paymentChannelService.ApprovePaymentChannel(created.PaymentChannelConfigurationId, 3));

        Assert.Contains("maker-checker", exception.Message, StringComparison.OrdinalIgnoreCase);
    }

    private static IntegrationEndpointResponse CreateAndActivateEndpoint(
        IntegrationEndpointRegistryService integrationService,
        string endpointName,
        string providerCode,
        string directionCode,
        string relativePath,
        long makerUserId,
        long checkerUserId)
    {
        var created = integrationService.CreateIntegrationEndpoint(new CreateIntegrationEndpointRequest(
            EndpointName: endpointName,
            IntegrationProviderCode: providerCode,
            EnvironmentCode: "UAT",
            DirectionCode: directionCode,
            TransportCode: "REST",
            HttpMethodCode: directionCode == "INBOUND" ? "POST" : "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: "Payment channel QA endpoint"));

        integrationService.SubmitIntegrationEndpoint(created.IntegrationEndpointId, makerUserId);
        integrationService.ApproveIntegrationEndpoint(created.IntegrationEndpointId, checkerUserId);
        return integrationService.ActivateIntegrationEndpoint(created.IntegrationEndpointId, checkerUserId);
    }
}
