using System.Net;
using System.Net.Http.Json;
using Baya.Application.Contracts.Identity;
using Microsoft.Extensions.DependencyInjection;

namespace Baya.Test.Api;

/// <summary>
/// HTTP-pipeline coverage for the b15 partner-center console. The load-bearing assertion is that the settlement
/// IBAN is returned <b>masked</b> (last 4), never plaintext, on both the create response and the detail read.
/// Also covers the admin RBAC gate.
/// </summary>
public class PartnerCentersApiTests(BayaApiFactory factory) : IClassFixture<BayaApiFactory>
{
    private const string FullIban = "IR062960000000100324200001";

    private static async Task<int> UserIdAsync(BayaApiFactory factory, string phone)
    {
        using var scope = factory.Services.CreateScope();
        var users = scope.ServiceProvider.GetRequiredService<IAppUserManager>();
        return (await users.GetUserByPhoneNumber(phone))!.Id;
    }

    [Fact]
    public async Task List_Unauthenticated_Returns401()
    {
        var anon = factory.CreateClient();
        var response = await anon.GetAsync("/api/v1/admin/partner-centers");
        Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
    }

    [Fact]
    public async Task NonAdmin_IsForbidden()
    {
        var customer = factory.CreateClient();
        var login = await AuthTestClient.LoginAsync(factory, customer, "09120040001");
        AuthTestClient.UseBearer(customer, login.GetProperty("accessToken").GetString()!);

        var response = await customer.GetAsync("/api/v1/admin/partner-centers");
        Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
    }

    [Fact]
    public async Task CreateMerchantOfRecord_MasksSettlementIban()
    {
        var admin = factory.CreateClient();
        await AdminTestClient.AuthenticateAsync(factory, admin, "09120040009");

        var create = await admin.PostAsJsonAsync("/api/v1/admin/partner-centers", new
        {
            name = "Asanism Center",
            legalEntityType = "llc",
            mohEstablishmentPermitNo = "MOH-12345",
            enamadCode = "EN-999",
            settlementIban = FullIban,
            isMerchantOfRecord = true,
            commissionRate = 0.05m,
            adminUserId = await UserIdAsync(factory, "09120040009")
        });
        Assert.Equal(HttpStatusCode.OK, create.StatusCode);

        var created = await AuthTestClient.ReadDataAsync(create);
        var centerId = created.GetProperty("id").GetInt64();
        var masked = created.GetProperty("settlementIbanMasked").GetString();

        Assert.NotNull(masked);
        Assert.DoesNotContain("0032420", masked); // no interior digits
        Assert.EndsWith("0001", masked);
        Assert.NotEqual(FullIban, masked);

        // The detail read masks it too — the plaintext IBAN is never serialized.
        var detail = await AuthTestClient.ReadDataAsync(await admin.GetAsync($"/api/v1/admin/partner-centers/{centerId}"));
        Assert.EndsWith("0001", detail.GetProperty("settlementIbanMasked").GetString());
        Assert.False(detail.GetProperty("isActive").GetBoolean()); // created inactive until verified
    }

    [Fact]
    public async Task Verify_ActivatesTheCenter()
    {
        var admin = factory.CreateClient();
        await AdminTestClient.AuthenticateAsync(factory, admin, "09120050009");

        var created = await AuthTestClient.ReadDataAsync(await admin.PostAsJsonAsync("/api/v1/admin/partner-centers", new
        {
            name = "Center B",
            mohEstablishmentPermitNo = "MOH-55555",
            isMerchantOfRecord = false,
            adminUserId = await UserIdAsync(factory, "09120050009")
        }));
        var centerId = created.GetProperty("id").GetInt64();

        var verify = await admin.PostAsync($"/api/v1/admin/partner-centers/{centerId}/verify", null);
        Assert.Equal(HttpStatusCode.OK, verify.StatusCode);

        var detail = await AuthTestClient.ReadDataAsync(verify);
        Assert.True(detail.GetProperty("isActive").GetBoolean());
        Assert.True(detail.GetProperty("verifiedAt").ValueKind is System.Text.Json.JsonValueKind.String);
    }
}
