using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;

namespace AdsServingService.FunctionalTests.Controllers;

/// <summary>
/// EN: Functional tests for ads serving and admin auction endpoints.
/// VI: Functional tests cho endpoint phục vụ quảng cáo và quản trị auction.
/// </summary>
public class AdsServingControllerTests : IClassFixture<CustomWebApplicationFactory>
{
    private readonly HttpClient _client;

    public AdsServingControllerTests(CustomWebApplicationFactory factory)
    {
        _client = factory.CreateClient(new WebApplicationFactoryClientOptions
        {
            AllowAutoRedirect = false,
        });
    }

    [Fact]
    public async Task ServeAd_ShouldReturnServedAdPayload()
    {
        // Arrange
        var request = new
        {
            userId = Guid.NewGuid(),
            placementType = "feed",
            userContext = new Dictionary<string, string>
            {
                ["segment"] = "high-intent",
            },
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/v1/ads/serve", request);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);

        var content = await response.Content.ReadFromJsonAsync<JsonElement>();
        var adId = content.GetProperty("adId").GetGuid();
        var finalPrice = content.GetProperty("finalPrice").GetDecimal();

        adId.Should().NotBe(Guid.Empty);
        finalPrice.Should().BeGreaterThan(0);
    }

    [Fact]
    public async Task GetAuctionStatistics_AfterServe_ShouldReflectPersistedAuctions()
    {
        // Arrange
        var request = new
        {
            userId = Guid.NewGuid(),
            placementType = "story",
            userContext = new Dictionary<string, string>(),
        };

        // Act
        var serveResponse = await _client.PostAsJsonAsync("/api/v1/ads/serve", request);
        var statsResponse = await _client.GetAsync("/api/v1/admin/auctions/statistics");

        // Assert
        serveResponse.StatusCode.Should().Be(HttpStatusCode.OK);
        statsResponse.StatusCode.Should().Be(HttpStatusCode.OK);

        var stats = await statsResponse.Content.ReadFromJsonAsync<JsonElement>();
        stats.GetProperty("totalAuctions").GetInt32().Should().BeGreaterThanOrEqualTo(1);
        stats.GetProperty("totalBidsPlaced").GetInt64().Should().BeGreaterThanOrEqualTo(2);
    }

    [Fact]
    public async Task TrackImpression_ShouldReturnAccepted()
    {
        // Arrange
        var request = new
        {
            adId = Guid.NewGuid(),
            userId = Guid.NewGuid(),
            timestamp = DateTime.UtcNow,
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/v1/ads/events/impression", request);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.Accepted);
    }

    [Fact]
    public async Task HealthCheck_ShouldReturnHealthy()
    {
        // Act
        var response = await _client.GetAsync("/health/live");

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
    }
}
