using System.Net;
using System.Text.Json;
using Tiku.Domain.Catalog;
using Tiku.Domain.Common;
using Tiku.Domain.Tenancy;

namespace Tiku.IntegrationTests.Api;

public sealed class ScorelineEndpointTests
{
    [Fact]
    public async Task Public_scoreline_records_support_dynamic_filters()
    {
        await using var factory = new ApiTestFactory();
        var tenantId = Guid.NewGuid();
        var regionId = Guid.NewGuid();
        var schoolId = Guid.NewGuid();
        var majorId = Guid.NewGuid();
        var tenantCode = tenantId.ToString("N");
        await factory.SeedAsync(
            new Tenant
            {
                Id = tenantId,
                Slug = tenantCode,
                Name = "Test Tenant",
                Status = TenantStatus.Active,
                Metadata = JsonDefaults.Object()
            },
            new Region { Id = regionId, TenantId = tenantId, Name = "四川" },
            new School { Id = schoolId, TenantId = tenantId, RegionId = regionId, Name = "美术学院" },
            new Major { Id = majorId, TenantId = tenantId, RegionId = regionId, SchoolId = schoolId, Name = "视觉传达" },
            new ScorelineField
            {
                TenantId = tenantId,
                RegionId = regionId,
                FieldKey = "cultureScore",
                FieldName = "文化分",
                FieldType = "number",
                IsFilter = true,
                IsTrend = true
            },
            new ScorelineRecord
            {
                TenantId = tenantId,
                RegionId = regionId,
                SchoolId = schoolId,
                MajorId = majorId,
                Year = 2026,
                SchoolName = "美术学院",
                MajorName = "视觉传达",
                FieldValues = JsonSerializer.SerializeToElement(new { cultureScore = 420, scoreType = "统考" })
            },
            new ScorelineRecord
            {
                TenantId = tenantId,
                RegionId = regionId,
                SchoolId = schoolId,
                MajorId = majorId,
                Year = 2025,
                SchoolName = "美术学院",
                MajorName = "视觉传达",
                FieldValues = JsonSerializer.SerializeToElement(new { cultureScore = 360, scoreType = "统考" })
            });
        using var client = factory.CreateClient();

        using var response = await client.GetAsync(
            $"/api/public/scoreline/records?tenantCode={tenantCode}&regionId={regionId}&min.cultureScore=400");
        var json = await ReadJsonAsync(response);

        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        Assert.Equal(1, json.RootElement.GetProperty("total").GetInt32());
        var item = json.RootElement.GetProperty("items").EnumerateArray().Single();
        Assert.Equal(2026, item.GetProperty("year").GetInt32());
        Assert.Equal(420, item.GetProperty("fieldValues").GetProperty("cultureScore").GetInt32());

        using var firstCursorResponse = await client.GetAsync(
            $"/api/public/scoreline/records/cursor?tenantCode={tenantCode}&regionId={regionId}&pageSize=1");
        var firstCursorJson = await ReadJsonAsync(firstCursorResponse);
        Assert.Equal(HttpStatusCode.OK, firstCursorResponse.StatusCode);
        Assert.True(firstCursorJson.RootElement.GetProperty("hasMore").GetBoolean());
        var firstCursorItem = firstCursorJson.RootElement.GetProperty("items").EnumerateArray().Single();
        var firstCursorId = firstCursorItem.GetProperty("id").GetGuid();
        var nextCursor = firstCursorJson.RootElement.GetProperty("nextCursor").GetString();
        Assert.False(string.IsNullOrWhiteSpace(nextCursor));

        using var secondCursorResponse = await client.GetAsync(
            $"/api/public/scoreline/records/cursor?tenantCode={tenantCode}&regionId={regionId}&pageSize=1&cursor={Uri.EscapeDataString(nextCursor!)}");
        var secondCursorJson = await ReadJsonAsync(secondCursorResponse);
        Assert.Equal(HttpStatusCode.OK, secondCursorResponse.StatusCode);
        Assert.False(secondCursorJson.RootElement.GetProperty("hasMore").GetBoolean());
        var secondCursorItem = secondCursorJson.RootElement.GetProperty("items").EnumerateArray().Single();
        Assert.NotEqual(firstCursorId, secondCursorItem.GetProperty("id").GetGuid());
        Assert.Equal(2025, secondCursorItem.GetProperty("year").GetInt32());

        using var invalidCursorResponse = await client.GetAsync(
            $"/api/public/scoreline/records/cursor?tenantCode={tenantCode}&regionId={regionId}&cursor=not-a-cursor");
        var invalidCursorJson = await ReadJsonAsync(invalidCursorResponse);
        Assert.Equal(HttpStatusCode.BadRequest, invalidCursorResponse.StatusCode);
        Assert.Equal("scoreline_cursor_invalid", invalidCursorJson.RootElement.GetProperty("code").GetString());
    }

    [Fact]
    public async Task Public_scoreline_without_tenant_returns_not_found()
    {
        await using var factory = new ApiTestFactory();
        using var client = factory.CreateClient();

        using var response = await client.GetAsync("/api/public/scoreline/fields");
        var json = await ReadJsonAsync(response);

        Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
        Assert.Equal("tenant_not_found", json.RootElement.GetProperty("code").GetString());
    }

    private static async Task<JsonDocument> ReadJsonAsync(HttpResponseMessage response)
    {
        var stream = await response.Content.ReadAsStreamAsync();
        return await JsonDocument.ParseAsync(stream);
    }
}