using System.Net;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
using TrackQrApi.Features.Auth.Common;
using TrackQrApi.Features.Links.Common;
using TrackQrApi.Features.Workspaces.Common;

namespace TrackQrApi.Tests;

public class EventTrackingTests(
    ApiWebApplicationFactory factory)
    : IClassFixture<ApiWebApplicationFactory>
{
    private readonly HttpClient _client = factory.CreateClient();

    private readonly HttpClient _noRedirectClient = factory.CreateClient(new WebApplicationFactoryClientOptions
    {
        AllowAutoRedirect = false
    });

    private async Task<(string Token, Guid WorkspaceId)> SetupAuthAndWorkspaceAsync(string email)
    {
        var response = await _client.PostAsJsonAsync("/auth/register", new { Email = email, Password = "password123" });
        if (response.StatusCode == HttpStatusCode.Conflict)
            response = await _client.PostAsJsonAsync("/auth/login", new { Email = email, Password = "password123" });
        var authResult = await response.Content.ReadFromJsonAsync<AuthResponse>();
        var token = authResult!.Token;

        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var wsResponse = await _client.GetAsync("/workspaces");
        var wsResult = await wsResponse.Content.ReadFromJsonAsync<WorkspaceListResponse>();
        var workspaceId = wsResult!.Workspaces.First().Id;

        return (token, workspaceId);
    }

    private async Task<LinkResponse> CreateLinkAsync(Guid workspaceId, string destinationUrl, string slug)
    {
        var createResponse = await _client.PostAsJsonAsync($"/workspaces/{workspaceId}/links", new
        {
            DestinationUrl = destinationUrl,
            Slug = slug
        });
        return (await createResponse.Content.ReadFromJsonAsync<LinkResponse>())!;
    }

    [Fact]
    public async Task Redirect_TracksClickEvent()
    {
        // Arrange
        var (_, workspaceId) = await SetupAuthAndWorkspaceAsync("event-track@example.com");
        var link = await CreateLinkAsync(workspaceId, "https://example.com", "event-track-link");

        // Act - Click the link multiple times
        await _noRedirectClient.GetAsync($"/{link.Slug}");

        // Give time for async event tracking
        await Task.Delay(500);

        // We can't directly query the events without an analytics endpoint,
        // but we can verify the redirect still works and the endpoint doesn't crash
        var response = await _noRedirectClient.GetAsync($"/{link.Slug}");

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

    [Fact]
    public async Task Redirect_DeduplicatesEvents_WithinWindow()
    {
        // Arrange
        var (_, workspaceId) = await SetupAuthAndWorkspaceAsync("event-dedupe@example.com");
        var link = await CreateLinkAsync(workspaceId, "https://example.com", "event-dedupe-link");

        // Act - Click the same link multiple times rapidly
        var responses = new List<HttpResponseMessage>();
        for (var i = 0; i < 5; i++) responses.Add(await _noRedirectClient.GetAsync($"/{link.Slug}"));

        // Assert - All should redirect successfully (deduplication happens silently)
        responses.Should().OnlyContain(r => r.StatusCode == HttpStatusCode.Redirect);
    }

    [Fact]
    public async Task PasswordRedirect_TracksClickEvent()
    {
        // Arrange
        var (_, workspaceId) = await SetupAuthAndWorkspaceAsync("event-pass@example.com");
        var link = await CreateLinkAsync(workspaceId, "https://example.com", "event-pass-link");
        await _client.PutAsJsonAsync($"/workspaces/{workspaceId}/links/{link.Id}", new { Password = "secret" });

        // Act
        var response = await _noRedirectClient.PostAsJsonAsync($"/{link.Slug}", new { Password = "secret" });

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

    [Fact]
    public async Task Redirect_CapturesUserAgent()
    {
        // Arrange
        var (_, workspaceId) = await SetupAuthAndWorkspaceAsync("event-ua@example.com");
        var link = await CreateLinkAsync(workspaceId, "https://example.com", "event-ua-link");

        // Set a custom user agent
        _noRedirectClient.DefaultRequestHeaders.UserAgent.ParseAdd(
            "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)");

        // Act
        var response = await _noRedirectClient.GetAsync($"/{link.Slug}");

        // Assert - Redirect should work (event captures user agent in background)
        response.StatusCode.Should().Be(HttpStatusCode.Redirect);
    }

    [Fact]
    public async Task Redirect_CapturesReferrer()
    {
        // Arrange
        var (_, workspaceId) = await SetupAuthAndWorkspaceAsync("event-ref@example.com");
        var link = await CreateLinkAsync(workspaceId, "https://example.com", "event-ref-link");

        // Set a referrer
        _noRedirectClient.DefaultRequestHeaders.Referrer = new Uri("https://twitter.com/somepost");

        // Act
        var response = await _noRedirectClient.GetAsync($"/{link.Slug}");

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