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

namespace CashLineERP.Api.Tests;

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

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

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

        var partyResponse = await _client.PostAsJsonAsync("/api/v1/parties", new CreateBusinessPartyRequest(
            $"CUS-HTTP-{Guid.NewGuid():N}"[..17].ToUpperInvariant(),
            "HTTP Customer",
            "CUSTOMER",
            "EG",
            null,
            "HTTP-CUS-TAX-001",
            "001",
            "customer-http@example.com",
            "+201000000223",
            "Maadi",
            25000m,
            45,
            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",
                "customer-register.pdf",
                "managed://customer/register.pdf",
                "application/pdf",
                2048));
        Assert.Equal(HttpStatusCode.OK, complianceResponse.StatusCode);

        var createResponse = await _client.PostAsJsonAsync("/api/v1/customers", new CreateCustomerProfileRequest(
            party.PartyId,
            null,
            "INSTITUTIONAL",
            "ENTERPRISE",
            "EGP",
            "DIRECT_SALES",
            "STANDARD",
            "EMAIL",
            "Strategic enterprise customer"));

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

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

        await _client.AuthenticateAsFinanceCheckerAsync();

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

        var activateResponse = await _client.PostAsync($"/api/v1/customers/{created.CustomerProfileId}/activate", null);
        Assert.Equal(HttpStatusCode.OK, activateResponse.StatusCode);
        var activated = await activateResponse.Content.ReadFromJsonAsync<CustomerProfileResponse>();
        Assert.NotNull(activated);
        Assert.True(activated!.IsActive);
        Assert.Equal("APPROVED", activated.TaxProfileStatusCode);

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

        var listResponse = await _client.GetAsync($"/api/v1/customers?activeOnly=true&classificationCode=INSTITUTIONAL");
        Assert.Equal(HttpStatusCode.OK, listResponse.StatusCode);
        var list = await listResponse.Content.ReadFromJsonAsync<CustomerProfileResponse[]>();
        Assert.NotNull(list);
        Assert.Single(list!);
    }

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

        var partyResponse = await _client.PostAsJsonAsync("/api/v1/parties", new CreateBusinessPartyRequest(
            $"CUS-HTTP-{Guid.NewGuid():N}"[..17].ToUpperInvariant(),
            "Incomplete Customer",
            "CUSTOMER",
            "EG",
            null,
            "HTTP-CUS-TAX-002",
            "001",
            "customer-incomplete@example.com",
            "+201000000224",
            "Dokki",
            5000m,
            30,
            false,
            null));

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

        var createResponse = await _client.PostAsJsonAsync("/api/v1/customers", new CreateCustomerProfileRequest(
            party!.PartyId,
            null,
            "COMPANY",
            "MID_MARKET",
            "USD",
            "KEY_ACCOUNT",
            "PREFERRED",
            "PORTAL",
            null));

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

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

        await _client.AuthenticateAsFinanceCheckerAsync();

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

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

        var createResponse = await _client.PostAsJsonAsync("/api/v1/customers", new CreateCustomerProfileRequest(
            2,
            null,
            "COMPANY",
            "MID_MARKET",
            "USD",
            "KEY_ACCOUNT",
            "PREFERRED",
            "PORTAL",
            "Forbidden finance maker attempt"));

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