using System.Net;
using Microsoft.AspNetCore.Mvc.Testing;

namespace CartWise.Web.Tests;

public class PurchaseAccessControlTests : IClassFixture<CartWiseWebApplicationFactory>
{
    private readonly CartWiseWebApplicationFactory _factory;

    public PurchaseAccessControlTests(CartWiseWebApplicationFactory factory)
    {
        _factory = factory;
    }

    [Fact]
    public async Task AnonymousUser_IsRedirectedToLoginWhenRequestingPurchases()
    {
        var client = _factory.CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false });

        var response = await client.GetAsync("/purchases");

        Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
        Assert.Contains("/Account/Login", response.Headers.Location?.ToString());
    }

    [Fact]
    public async Task RecordPurchase_FullFlow_AddsItemAndCompletes()
    {
        var client = _factory.CreateClient();
        await WebTestHelpers.RegisterAsync(client, "purchaseflow1@example.com", "Purchase Flow User");
        await WebTestHelpers.CreateHouseholdAsync(client, "Purchase Flow Household");

        var indexHtml = await client.GetStringAsync("/purchases");
        var startToken = WebTestHelpers.ExtractAntiForgeryToken(indexHtml);
        var startResponse = await client.PostAsync("/purchases/start", new FormUrlEncodedContent(new Dictionary<string, string>
        {
            ["__RequestVerificationToken"] = startToken
        }));
        startResponse.EnsureSuccessStatusCode();
        var purchaseUrl = startResponse.RequestMessage!.RequestUri!.AbsolutePath;

        var detailHtml = await client.GetStringAsync(purchaseUrl);
        HtmlAssert.Contains("In progress", detailHtml);
        var itemToken = WebTestHelpers.ExtractAntiForgeryToken(detailHtml);

        var addItemResponse = await client.PostAsync($"{purchaseUrl}/items", new FormUrlEncodedContent(new Dictionary<string, string>
        {
            ["__RequestVerificationToken"] = itemToken,
            ["NewItem.Description"] = "Milk",
            ["NewItem.Quantity"] = "2",
            ["NewItem.Unit"] = "gal",
            ["NewItem.LinePrice"] = "7.98"
        }));
        addItemResponse.EnsureSuccessStatusCode();

        var afterAddHtml = await addItemResponse.Content.ReadAsStringAsync();
        HtmlAssert.Contains("Milk", afterAddHtml);

        var completeToken = WebTestHelpers.ExtractAntiForgeryToken(afterAddHtml);
        var completeResponse = await client.PostAsync($"{purchaseUrl}/complete", new FormUrlEncodedContent(new Dictionary<string, string>
        {
            ["__RequestVerificationToken"] = completeToken
        }));
        completeResponse.EnsureSuccessStatusCode();

        var finalHtml = await completeResponse.Content.ReadAsStringAsync();
        HtmlAssert.Contains("Completed", finalHtml);
        HtmlAssert.Contains("$7.98", finalHtml);
    }

    [Fact]
    public async Task EachHousehold_OnlySeesItsOwnPurchases()
    {
        var clientA = _factory.CreateClient();
        var clientB = _factory.CreateClient();
        await WebTestHelpers.RegisterAsync(clientA, "purchasealice@example.com", "Purchase Alice");
        await WebTestHelpers.RegisterAsync(clientB, "purchasebob@example.com", "Purchase Bob");
        await WebTestHelpers.CreateHouseholdAsync(clientA, "Purchase Household A");
        await WebTestHelpers.CreateHouseholdAsync(clientB, "Purchase Household B");

        var indexA = await clientA.GetStringAsync("/purchases");
        var tokenA = WebTestHelpers.ExtractAntiForgeryToken(indexA);
        var startResponseA = await clientA.PostAsync("/purchases/start", new FormUrlEncodedContent(new Dictionary<string, string>
        {
            ["__RequestVerificationToken"] = tokenA
        }));
        var purchaseUrlA = startResponseA.RequestMessage!.RequestUri!.AbsolutePath;
        var purchaseIdA = purchaseUrlA.Split('/').Last();

        var response = await clientB.GetAsync($"/purchases/{purchaseIdA}");

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