using System.Net;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using FluentAssertions;
using TrackQrApi.Features.Auth.Common;
using TrackQrApi.Features.Workspaces.Common;

namespace TrackQrApi.Tests;

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

    private async Task<(string Token, Guid WorkspaceId)> GetAuthAndWorkspaceAsync(string email,
        bool upgradeToPro = false)
    {
        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 result = await response.Content.ReadFromJsonAsync<AuthResponse>();
        var token = result!.Token;

        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        var workspacesResponse = await _client.GetAsync("/workspaces");
        var workspaces = await workspacesResponse.Content.ReadFromJsonAsync<WorkspaceListResponse>();
        var workspaceId = workspaces!.Workspaces.First().Id;

        if (upgradeToPro) await factory.UpgradeWorkspaceToPro(workspaceId);

        return (token, workspaceId);
    }

    private async Task<string> GetAuthTokenAsync(string email = "workspace-test@example.com")
    {
        var (token, _) = await GetAuthAndWorkspaceAsync(email);
        return token;
    }

    [Fact]
    public async Task ListWorkspaces_WithValidToken_ReturnsWorkspaces()
    {
        // Arrange
        var token = await GetAuthTokenAsync("list-ws@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        // Act
        var response = await _client.GetAsync("/workspaces");

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        var result = await response.Content.ReadFromJsonAsync<WorkspaceListResponse>();
        result.Should().NotBeNull();
        result!.Workspaces.Should().HaveCountGreaterThanOrEqualTo(1); // Default workspace created on registration
    }

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

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

    [Fact]
    public async Task CreateWorkspace_WithValidData_ReturnsCreated()
    {
        // Arrange - upgrade to Pro to allow creating additional workspaces
        var (token, _) = await GetAuthAndWorkspaceAsync("create-ws@example.com", true);
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        // Act
        var response = await _client.PostAsJsonAsync("/workspaces", new { Name = "Test Workspace" });

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.Created);
        var result = await response.Content.ReadFromJsonAsync<WorkspaceResponse>();
        result.Should().NotBeNull();
        result!.Name.Should().Be("Test Workspace");
        result.Plan.Should().Be("Free");
        result.Id.Should().NotBeEmpty();
    }

    [Fact]
    public async Task CreateWorkspace_WithEmptyName_ReturnsBadRequest()
    {
        // Arrange
        var token = await GetAuthTokenAsync("create-ws-invalid@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        // Act
        var response = await _client.PostAsJsonAsync("/workspaces", new { Name = "" });

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

    [Fact]
    public async Task GetWorkspace_WithValidId_ReturnsWorkspace()
    {
        // Arrange - use the default workspace (created on registration)
        var (token, workspaceId) = await GetAuthAndWorkspaceAsync("get-ws@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

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

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        var result = await response.Content.ReadFromJsonAsync<WorkspaceResponse>();
        result!.Id.Should().Be(workspaceId);
        result.Name.Should().NotBeNullOrEmpty();
    }

    [Fact]
    public async Task GetWorkspace_WithInvalidId_ReturnsNotFound()
    {
        // Arrange
        var token = await GetAuthTokenAsync("get-ws-invalid@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

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

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

    [Fact]
    public async Task UpdateWorkspace_WithValidData_ReturnsUpdated()
    {
        // Arrange - use the default workspace (created on registration)
        var (token, workspaceId) = await GetAuthAndWorkspaceAsync("update-ws@example.com");
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        // Act
        var response = await _client.PutAsJsonAsync($"/workspaces/{workspaceId}", new { Name = "Updated Name" });

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        var result = await response.Content.ReadFromJsonAsync<WorkspaceResponse>();
        result!.Name.Should().Be("Updated Name");
    }

    [Fact]
    public async Task DeleteWorkspace_WithValidId_ReturnsSuccess()
    {
        // Arrange - upgrade to Pro to allow creating additional workspaces
        var (token, _) = await GetAuthAndWorkspaceAsync("delete-ws@example.com", true);
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

        var createResponse = await _client.PostAsJsonAsync("/workspaces", new { Name = "To Delete" });
        var created = await createResponse.Content.ReadFromJsonAsync<WorkspaceResponse>();

        // Act
        var response = await _client.DeleteAsync($"/workspaces/{created!.Id}");

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

        // Verify it's deleted
        var getResponse = await _client.GetAsync($"/workspaces/{created.Id}");
        getResponse.StatusCode.Should().Be(HttpStatusCode.NotFound);
    }

    [Fact]
    public async Task Workspace_CannotAccessOtherUsersWorkspace()
    {
        // Arrange - Create two users
        var token1 = await GetAuthTokenAsync("user1-ws@example.com");
        var token2 = await GetAuthTokenAsync("user2-ws@example.com");

        // Create workspace as user1
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token1);
        var createResponse = await _client.PostAsJsonAsync("/workspaces", new { Name = "User1 Workspace" });
        var created = await createResponse.Content.ReadFromJsonAsync<WorkspaceResponse>();

        // Try to access as user2
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token2);

        // Act
        var getResponse = await _client.GetAsync($"/workspaces/{created!.Id}");
        var updateResponse = await _client.PutAsJsonAsync($"/workspaces/{created.Id}", new { Name = "Hacked" });
        var deleteResponse = await _client.DeleteAsync($"/workspaces/{created.Id}");

        // Assert - All should return NotFound (not exposing existence)
        getResponse.StatusCode.Should().Be(HttpStatusCode.NotFound);
        updateResponse.StatusCode.Should().Be(HttpStatusCode.NotFound);
        deleteResponse.StatusCode.Should().Be(HttpStatusCode.NotFound);
    }
}