using System.Net;
using System.Net.Http.Json;
using CashLineERP.Contracts.IslamicFinance;
using CashLineERP.Domain.IslamicFinance.Murabaha;
using CashLineERP.Infrastructure.Persistence;
using Microsoft.Extensions.DependencyInjection;

namespace CashLineERP.Api.Tests;

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

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

    [Fact]
    public async Task Murabaha_Schedule_Endpoints_Generate_And_Return_Summary_And_Installment_Detail()
    {
        await _client.AuthenticateAsInternalAsync();
        var murabahaCaseId = SeedApprovedMurabahaCase();

        var generateResponse = await _client.PostAsJsonAsync(
            $"/api/v1/islamic-finance/murabaha-cases/{murabahaCaseId}/generate-schedule",
            new GenerateIslamicFinanceMurabahaScheduleRequest
            {
                InstallmentCount = 2,
                FirstDueDate = new DateOnly(2026, 5, 1),
                InstallmentIntervalMonths = 1
            });
        Assert.Equal(HttpStatusCode.OK, generateResponse.StatusCode);

        var scheduleResponse = await _client.GetAsync($"/api/v1/islamic-finance/murabaha-cases/{murabahaCaseId}/schedule");
        Assert.Equal(HttpStatusCode.OK, scheduleResponse.StatusCode);

        var schedule = await scheduleResponse.Content.ReadFromJsonAsync<IslamicFinanceMurabahaScheduleResponse>();
        Assert.NotNull(schedule);
        Assert.Equal(2, schedule!.InstallmentCount);
        Assert.Equal("ACTIVE", schedule.StatusCode);

        var installmentResponse = await _client.GetAsync($"/api/v1/islamic-finance/murabaha-cases/{murabahaCaseId}/schedule/installments/1");
        Assert.Equal(HttpStatusCode.OK, installmentResponse.StatusCode);

        var installment = await installmentResponse.Content.ReadFromJsonAsync<IslamicFinanceMurabahaScheduleLineResponse>();
        Assert.NotNull(installment);
        Assert.Equal(1, installment!.InstallmentNumber);
        Assert.Equal(60000m, installment.InstallmentAmount);
    }

    [Fact]
    public async Task Murabaha_Schedule_Endpoints_Return_NotFound_For_Unknown_Case_Or_Installment()
    {
        await _client.AuthenticateAsInternalAsync();
        var murabahaCaseId = SeedApprovedMurabahaCase();

        await _client.PostAsJsonAsync(
            $"/api/v1/islamic-finance/murabaha-cases/{murabahaCaseId}/generate-schedule",
            new GenerateIslamicFinanceMurabahaScheduleRequest
            {
                InstallmentCount = 2,
                FirstDueDate = new DateOnly(2026, 5, 1),
                InstallmentIntervalMonths = 1
            });

        var missingScheduleResponse = await _client.GetAsync("/api/v1/islamic-finance/murabaha-cases/999999/schedule");
        Assert.Equal(HttpStatusCode.NotFound, missingScheduleResponse.StatusCode);

        var missingInstallmentResponse = await _client.GetAsync($"/api/v1/islamic-finance/murabaha-cases/{murabahaCaseId}/schedule/installments/99");
        Assert.Equal(HttpStatusCode.NotFound, missingInstallmentResponse.StatusCode);
    }

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

        using var scope = _factory.Services.CreateScope();
        var dbContext = scope.ServiceProvider.GetRequiredService<CashLineErpDbContext>();

        var murabahaCase = new IslamicFinanceMurabahaCase(
            $"MUR-{Guid.NewGuid():N}"[..12].ToUpperInvariant(),
            301,
            1,
            1,
            supplierPartyId: 2,
            productProfileId: 1,
            contractTemplateId: null,
            transactionCurrencyCode: "EGP",
            purchaseCostAmount: 100000m,
            profitAmount: 20000m);

        dbContext.IslamicFinanceMurabahaCases.Add(murabahaCase);
        dbContext.SaveChanges();

        var response = await _client.PostAsJsonAsync(
            $"/api/v1/islamic-finance/murabaha-cases/{murabahaCase.Id}/generate-schedule",
            new GenerateIslamicFinanceMurabahaScheduleRequest
            {
                InstallmentCount = 2,
                FirstDueDate = new DateOnly(2026, 5, 1),
                InstallmentIntervalMonths = 1
            });

        Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
    }

    private long SeedApprovedMurabahaCase()
    {
        using var scope = _factory.Services.CreateScope();
        var dbContext = scope.ServiceProvider.GetRequiredService<CashLineErpDbContext>();

        var murabahaCase = new IslamicFinanceMurabahaCase(
            $"MUR-{Guid.NewGuid():N}"[..12].ToUpperInvariant(),
            201,
            1,
            1,
            supplierPartyId: 2,
            productProfileId: 1,
            contractTemplateId: null,
            transactionCurrencyCode: "EGP",
            purchaseCostAmount: 100000m,
            profitAmount: 20000m);

        murabahaCase.Submit(3);
        murabahaCase.Approve(4);
        murabahaCase.Activate(4);
        dbContext.IslamicFinanceMurabahaCases.Add(murabahaCase);
        dbContext.SaveChanges();

        return murabahaCase.Id;
    }
}
