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

namespace TrackQrApi.Tests;

public class AnalyticsEndpointTests(
    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 WorkspaceAnalytics_ReturnsEmptyForNewWorkspace()
    {
        // Arrange
        var (token, workspaceId) = await SetupAuthAndWorkspaceAsync("analytics-empty@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        // Act
        var response = await _client.GetAsync($"/workspaces/{workspaceId}/analytics");

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        var result = await response.Content.ReadFromJsonAsync<WorkspaceAnalyticsResponse>();
        result.Should().NotBeNull();
        result!.Summary.TotalClicks.Should().Be(0);
        result.Summary.TotalScans.Should().Be(0);
        result.Summary.UniqueVisitors.Should().Be(0);
    }

    [Fact]
    public async Task WorkspaceAnalytics_ReturnsValidResponse()
    {
        // Arrange
        var (token, workspaceId) = await SetupAuthAndWorkspaceAsync("analytics-clicks@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var link = await CreateLinkAsync(workspaceId, "https://example.com", "analytics-clicks-link");

        // Generate some clicks (event tracking is async/fire-and-forget)
        await _noRedirectClient.GetAsync($"/{link.Slug}");

        // Act - Verify endpoint returns valid response structure
        var response = await _client.GetAsync($"/workspaces/{workspaceId}/analytics");

        // Assert - Focus on response structure, not click counts (tested separately)
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        var result = await response.Content.ReadFromJsonAsync<WorkspaceAnalyticsResponse>();
        result.Should().NotBeNull();
        result!.Summary.Should().NotBeNull();
        result.TimeSeries.Should().NotBeNull();
        result.TopLinks.Should().NotBeNull();
        result.DeviceBreakdown.Should().NotBeNull();
        result.ReferrerBreakdown.Should().NotBeNull();
    }

    [Fact]
    public async Task WorkspaceAnalytics_WithPeriodFilter_FiltersEvents()
    {
        // Arrange
        var (token, workspaceId) = await SetupAuthAndWorkspaceAsync("analytics-period@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        // Act
        var response = await _client.GetAsync($"/workspaces/{workspaceId}/analytics?period=24h");

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

    [Fact]
    public async Task WorkspaceAnalytics_Unauthorized_Returns401()
    {
        // Arrange
        var (_, workspaceId) = await SetupAuthAndWorkspaceAsync("analytics-unauth@example.com");
        _client.DefaultRequestHeaders.Authorization = null;

        // Act
        var response = await _client.GetAsync($"/workspaces/{workspaceId}/analytics");

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

    [Fact]
    public async Task WorkspaceAnalytics_OtherUsersWorkspace_Returns404()
    {
        // Arrange
        var (token1, workspaceId1) = await SetupAuthAndWorkspaceAsync("analytics-user1@example.com");
        var (token2, _) = await SetupAuthAndWorkspaceAsync("analytics-user2@example.com");

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

        // Act
        var response = await _client.GetAsync($"/workspaces/{workspaceId1}/analytics");

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

    [Fact]
    public async Task LinkAnalytics_ReturnsEmptyForNewLink()
    {
        // Arrange
        var (token, workspaceId) = await SetupAuthAndWorkspaceAsync("link-analytics-empty@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var link = await CreateLinkAsync(workspaceId, "https://example.com", "link-analytics-empty");

        // Act
        var response = await _client.GetAsync($"/workspaces/{workspaceId}/links/{link.Id}/analytics");

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        var result = await response.Content.ReadFromJsonAsync<LinkAnalyticsResponse>();
        result.Should().NotBeNull();
        result!.LinkId.Should().Be(link.Id);
        result.Slug.Should().Be(link.Slug);
        result.Summary.TotalClicks.Should().Be(0);
    }

    [Fact]
    public async Task LinkAnalytics_ReturnsValidResponse()
    {
        // Arrange
        var (token, workspaceId) = await SetupAuthAndWorkspaceAsync("link-analytics-clicks@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var link = await CreateLinkAsync(workspaceId, "https://example.com", "link-analytics-clicks");

        // Act
        var response = await _client.GetAsync($"/workspaces/{workspaceId}/links/{link.Id}/analytics");

        // Assert - Focus on response structure
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        var result = await response.Content.ReadFromJsonAsync<LinkAnalyticsResponse>();
        result.Should().NotBeNull();
        result!.LinkId.Should().Be(link.Id);
        result.Slug.Should().Be(link.Slug);
        result.Summary.Should().NotBeNull();
        result.TimeSeries.Should().NotBeNull();
        result.DeviceBreakdown.Should().NotBeNull();
        result.ReferrerBreakdown.Should().NotBeNull();
    }

    [Fact]
    public async Task LinkAnalytics_InvalidLink_Returns404()
    {
        // Arrange
        var (token, workspaceId) = await SetupAuthAndWorkspaceAsync("link-analytics-invalid@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        // Act
        var response = await _client.GetAsync($"/workspaces/{workspaceId}/links/{Guid.NewGuid()}/analytics");

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

    [Fact]
    public async Task LinkAnalytics_OtherUsersLink_Returns404()
    {
        // Arrange
        var (token1, workspaceId1) = await SetupAuthAndWorkspaceAsync("link-analytics-user1@example.com");
        var link = await CreateLinkAsync(workspaceId1, "https://example.com", "link-analytics-user1");

        var (token2, _) = await SetupAuthAndWorkspaceAsync("link-analytics-user2@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token2);

        // Act
        var response = await _client.GetAsync($"/workspaces/{workspaceId1}/links/{link.Id}/analytics");

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