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

namespace Tiku.IntegrationTests.Api;

public sealed class AssetEndpointTests
{
    [Fact]
    public async Task Content_assets_return_public_active_assets_by_default()
    {
        var tenantId = Guid.NewGuid();
        var regionId = Guid.NewGuid();
        await using var factory = new ApiTestFactory();
        await factory.SeedAsync(
            Tenant(tenantId, "master"),
            new Region { Id = regionId, TenantId = tenantId, Name = "测试地区" },
            new ContentAsset
            {
                Id = Guid.NewGuid(),
                TenantId = tenantId,
                RegionId = regionId,
                Title = "公开讲义",
                FileName = "handbook.pdf",
                AssetType = ContentAssetType.Pdf,
                StorageProvider = AssetStorageProvider.AliyunOss,
                Bucket = "tiku-assets",
                ObjectKey = $"{tenantId:N}/handbook.pdf",
                MimeType = "application/pdf",
                Visibility = ContentVisibility.Public,
                Status = ContentStatus.Active,
                SortOrder = 2
            },
            new ContentAsset
            {
                Id = Guid.NewGuid(),
                TenantId = tenantId,
                RegionId = regionId,
                Title = "会员讲义",
                Visibility = ContentVisibility.Members,
                Status = ContentStatus.Active,
                SortOrder = 1
            },
            new ContentAsset
            {
                Id = Guid.NewGuid(),
                TenantId = tenantId,
                RegionId = regionId,
                Title = "归档讲义",
                Visibility = ContentVisibility.Public,
                Status = ContentStatus.Archived
            });
        using var client = factory.CreateClient();

        using var response = await client.GetAsync($"/api/catalog/content-assets?tenantCode=master&regionId={regionId}&assetType=pdf");
        var items = await ReadItemsAsync(response);

        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        var item = Assert.Single(items);
        Assert.Equal("公开讲义", item.GetProperty("title").GetString());
        Assert.Equal("AliyunOss", item.GetProperty("storageProvider").GetString());
    }

    [Fact]
    public async Task Content_assets_can_include_locked_catalog_items_when_requested()
    {
        var tenantId = Guid.NewGuid();
        await using var factory = new ApiTestFactory();
        await factory.SeedAsync(
            Tenant(tenantId, "master"),
            new ContentAsset
            {
                Id = Guid.NewGuid(),
                TenantId = tenantId,
                Title = "会员讲义",
                Visibility = ContentVisibility.Members,
                Status = ContentStatus.Active
            });
        using var client = factory.CreateClient();

        using var response = await client.GetAsync("/api/catalog/content-assets?tenantCode=master&includeLocked=true");
        var items = await ReadItemsAsync(response);

        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        Assert.Equal("会员讲义", Assert.Single(items).GetProperty("title").GetString());
    }

    [Fact]
    public async Task Images_filter_private_items_until_include_locked()
    {
        var tenantId = Guid.NewGuid();
        await using var factory = new ApiTestFactory();
        await factory.SeedAsync(
            Tenant(tenantId, "master"),
            new ImageAsset
            {
                Id = Guid.NewGuid(),
                TenantId = tenantId,
                Title = "公开图",
                Category = "banner",
                IsPublic = true
            },
            new ImageAsset
            {
                Id = Guid.NewGuid(),
                TenantId = tenantId,
                Title = "内部图",
                Category = "banner",
                IsPublic = false
            });
        using var client = factory.CreateClient();

        using var publicResponse = await client.GetAsync("/api/catalog/images?tenantCode=master&category=banner");
        using var lockedResponse = await client.GetAsync("/api/catalog/images?tenantCode=master&category=banner&includeLocked=true");

        Assert.Equal(["公开图"], (await ReadItemsAsync(publicResponse)).Select(item => item.GetProperty("title").GetString()!).ToArray());
        var lockedTitles = (await ReadItemsAsync(lockedResponse))
            .Select(item => item.GetProperty("title").GetString()!)
            .ToArray();
        Assert.Equal(2, lockedTitles.Length);
        Assert.Contains("内部图", lockedTitles);
        Assert.Contains("公开图", lockedTitles);
    }

    [Fact]
    public async Task App_assets_support_asset_key_lookup()
    {
        var tenantId = Guid.NewGuid();
        await using var factory = new ApiTestFactory();
        await factory.SeedAsync(
            Tenant(tenantId, "master"),
            new AppAsset
            {
                Id = Guid.NewGuid(),
                TenantId = tenantId,
                AssetKey = "logo",
                FileName = "logo.png"
            },
            new AppAsset
            {
                Id = Guid.NewGuid(),
                TenantId = tenantId,
                AssetKey = "icon",
                FileName = "icon.png"
            });
        using var client = factory.CreateClient();

        using var response = await client.GetAsync("/api/catalog/app-assets?tenantCode=master&assetKey=logo");
        var item = Assert.Single(await ReadItemsAsync(response));

        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        Assert.Equal("logo", item.GetProperty("assetKey").GetString());
    }

    [Fact]
    public async Task Question_videos_include_video_explanation_summary()
    {
        var tenantId = Guid.NewGuid();
        var questionId = Guid.NewGuid();
        var videoId = Guid.NewGuid();
        await using var factory = new ApiTestFactory();
        await factory.SeedAsync(
            Tenant(tenantId, "master"),
            new Question
            {
                Id = questionId,
                TenantId = tenantId,
                Type = "choice",
                Status = QuestionStatus.Published
            },
            new VideoExplanation
            {
                Id = videoId,
                TenantId = tenantId,
                Title = "解题视频",
                IsActive = true,
                SortOrder = 1
            },
            new QuestionVideo
            {
                Id = Guid.NewGuid(),
                TenantId = tenantId,
                QuestionId = questionId,
                VideoId = videoId,
                VideoType = QuestionVideoType.Specific
            });
        using var client = factory.CreateClient();

        using var response = await client.GetAsync($"/api/catalog/question-videos?tenantCode=master&questionId={questionId}");
        var item = Assert.Single(await ReadItemsAsync(response));

        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        Assert.Equal(questionId, item.GetProperty("questionId").GetGuid());
        Assert.Equal("解题视频", item.GetProperty("video").GetProperty("title").GetString());
    }

    private static Tenant Tenant(Guid id, string slug)
    {
        return new Tenant
        {
            Id = id,
            Slug = slug,
            Name = slug,
            Status = TenantStatus.Active,
            Metadata = JsonDefaults.Object()
        };
    }

    private static async Task<JsonElement[]> ReadItemsAsync(HttpResponseMessage response)
    {
        var body = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
        return body.RootElement
            .GetProperty("items")
            .EnumerateArray()
            .Select(item => item.Clone())
            .ToArray();
    }
}
