using System.Net;
using System.Net.Http.Json;
using CashLineERP.Contracts.Parties;
using CashLineERP.Contracts.Suppliers;

namespace CashLineERP.Api.Tests;

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

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

    [Fact]
    public async Task Supplier_Profile_Endpoints_Support_Create_Submit_Approve_Activate_And_Reads()
    {
        await _client.AuthenticateAsInternalAsync();

        var partyResponse = await _client.PostAsJsonAsync("/api/v1/parties", new CreateBusinessPartyRequest(
            $"SUP-HTTP-{Guid.NewGuid():N}"[..17].ToUpperInvariant(),
            "HTTP Supplier",
            "SUPPLIER",
            "EG",
            null,
            "HTTP-TAX-001",
            "001",
            "supplier-http@example.com",
            "+201000000123",
            "Heliopolis",
            null,
            null,
            false,
            null));

        Assert.Equal(HttpStatusCode.OK, partyResponse.StatusCode);
        var party = await partyResponse.Content.ReadFromJsonAsync<BusinessPartyResponse>();
        Assert.NotNull(party);

        var complianceResponse = await _client.PostAsJsonAsync(
            $"/api/v1/parties/{party!.PartyId}/compliance-documents",
            new RecordBusinessPartyComplianceDocumentRequest(
                "COMMERCIAL_REGISTER",
                "commercial-register.pdf",
                "managed://supplier/commercial-register.pdf",
                "application/pdf",
                2048));
        Assert.Equal(HttpStatusCode.OK, complianceResponse.StatusCode);

        var createResponse = await _client.PostAsJsonAsync("/api/v1/suppliers", new CreateSupplierProfileRequest(
            party.PartyId,
            null,
            "LOCAL_VENDOR",
            "EGP",
            "BANK_TRANSFER",
            30,
            5,
            500m,
            "CIB",
            "1122334455667788",
            "CIBEEGCX",
            "Preferred local supplier"));

        Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode);
        var created = await createResponse.Content.ReadFromJsonAsync<SupplierProfileResponse>();
        Assert.NotNull(created);
        Assert.Equal("DRAFT", created!.StatusCode);

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

        await _client.AuthenticateAsFinanceCheckerAsync();

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

        var verifyBankResponse = await _client.PostAsJsonAsync(
            $"/api/v1/suppliers/{created.SupplierProfileId}/verify-bank",
            new VerifySupplierBankRequest("BANK-HTTP-001"));
        Assert.Equal(HttpStatusCode.OK, verifyBankResponse.StatusCode);

        var performanceReviewResponse = await _client.PostAsJsonAsync(
            $"/api/v1/suppliers/{created.SupplierProfileId}/performance-review",
            new RecordSupplierPerformanceReviewRequest("LOW", 94m, 96m, 95m, "Strong strategic supplier"));
        Assert.Equal(HttpStatusCode.OK, performanceReviewResponse.StatusCode);

        var activateResponse = await _client.PostAsync($"/api/v1/suppliers/{created.SupplierProfileId}/activate", null);
        Assert.Equal(HttpStatusCode.OK, activateResponse.StatusCode);
        var activated = await activateResponse.Content.ReadFromJsonAsync<SupplierProfileResponse>();
        Assert.NotNull(activated);
        Assert.True(activated!.IsActive);
        Assert.Equal("APPROVED", activated.ComplianceStatusCode);
        Assert.Equal("VERIFIED", activated.BankVerificationStatusCode);
        Assert.Equal("LOW", activated.RiskRatingCode);

        var detailResponse = await _client.GetAsync($"/api/v1/suppliers/{created.SupplierProfileId}");
        Assert.Equal(HttpStatusCode.OK, detailResponse.StatusCode);

        var listResponse = await _client.GetAsync($"/api/v1/suppliers?activeOnly=true&businessPartyId={party.PartyId}");
        Assert.Equal(HttpStatusCode.OK, listResponse.StatusCode);
        var list = await listResponse.Content.ReadFromJsonAsync<SupplierProfileResponse[]>();
        Assert.NotNull(list);
        Assert.Single(list!);
    }

    [Fact]
    public async Task Supplier_Profile_Approval_Is_Blocked_Without_Compliance_Document()
    {
        await _client.AuthenticateAsInternalAsync();

        var partyResponse = await _client.PostAsJsonAsync("/api/v1/parties", new CreateBusinessPartyRequest(
            $"SUP-HTTP-{Guid.NewGuid():N}"[..17].ToUpperInvariant(),
            "Incomplete Supplier",
            "SUPPLIER",
            "EG",
            null,
            "HTTP-TAX-002",
            "001",
            "supplier-incomplete@example.com",
            "+201000000124",
            "Giza",
            null,
            null,
            false,
            null));

        var party = await partyResponse.Content.ReadFromJsonAsync<BusinessPartyResponse>();
        Assert.NotNull(party);

        var createResponse = await _client.PostAsJsonAsync("/api/v1/suppliers", new CreateSupplierProfileRequest(
            party!.PartyId,
            null,
            "IMPORT_VENDOR",
            "USD",
            "BANK_TRANSFER",
            45,
            10,
            null,
            "QNB",
            "8877665544332211",
            null,
            null));
        var created = await createResponse.Content.ReadFromJsonAsync<SupplierProfileResponse>();
        Assert.NotNull(created);

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

        await _client.AuthenticateAsFinanceCheckerAsync();

        var approveResponse = await _client.PostAsync($"/api/v1/suppliers/{created.SupplierProfileId}/approve", null);
        Assert.Equal(HttpStatusCode.BadRequest, approveResponse.StatusCode);
        var payload = await approveResponse.Content.ReadAsStringAsync();
        Assert.Contains("compliance", payload, StringComparison.OrdinalIgnoreCase);
    }

    [Fact]
    public async Task Supplier_Profile_Activation_Is_Blocked_Until_Bank_Verification_Is_Completed()
    {
        await _client.AuthenticateAsInternalAsync();

        var partyResponse = await _client.PostAsJsonAsync("/api/v1/parties", new CreateBusinessPartyRequest(
            $"SUP-HTTP-{Guid.NewGuid():N}"[..17].ToUpperInvariant(),
            "Bank Pending Supplier",
            "SUPPLIER",
            "EG",
            null,
            "HTTP-TAX-003",
            "001",
            "supplier-bank-pending@example.com",
            "+201000000125",
            "Nasr City",
            null,
            null,
            false,
            null));

        var party = await partyResponse.Content.ReadFromJsonAsync<BusinessPartyResponse>();
        Assert.NotNull(party);

        var complianceResponse = await _client.PostAsJsonAsync(
            $"/api/v1/parties/{party!.PartyId}/compliance-documents",
            new RecordBusinessPartyComplianceDocumentRequest(
                "COMMERCIAL_REGISTER",
                "commercial-register.pdf",
                "managed://supplier/commercial-register-two.pdf",
                "application/pdf",
                2048));
        Assert.Equal(HttpStatusCode.OK, complianceResponse.StatusCode);

        var createResponse = await _client.PostAsJsonAsync("/api/v1/suppliers", new CreateSupplierProfileRequest(
            party.PartyId,
            null,
            "LOCAL_VENDOR",
            "EGP",
            "BANK_TRANSFER",
            30,
            5,
            500m,
            "CIB",
            "1122334455667799",
            "CIBEEGCX",
            "Supplier pending bank verification"));
        var created = await createResponse.Content.ReadFromJsonAsync<SupplierProfileResponse>();
        Assert.NotNull(created);

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

        await _client.AuthenticateAsFinanceCheckerAsync();

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

        var activateResponse = await _client.PostAsync($"/api/v1/suppliers/{created.SupplierProfileId}/activate", null);
        Assert.Equal(HttpStatusCode.BadRequest, activateResponse.StatusCode);
        var payload = await activateResponse.Content.ReadAsStringAsync();
        Assert.Contains("verified bank", payload, StringComparison.OrdinalIgnoreCase);
    }

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

        var createResponse = await _client.PostAsJsonAsync("/api/v1/suppliers", new CreateSupplierProfileRequest(
            1,
            null,
            "LOCAL_VENDOR",
            "EGP",
            "BANK_TRANSFER",
            30,
            5,
            500m,
            "CIB",
            "1122334455667788",
            "CIBEEGCX",
            "Forbidden finance maker attempt"));

        Assert.Equal(HttpStatusCode.Forbidden, createResponse.StatusCode);
    }
}
