using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OutputCaching;
using Microsoft.EntityFrameworkCore;
using Tiku.Application.Assets;
using Tiku.Api.Contracts;
using Tiku.Application.Catalog;
using Tiku.Application.Content;
using Tiku.Application.QuestionBanks;
using Tiku.Application.Security;
using Tiku.Application.StudyContent;
using Tiku.Domain.Tenancy;
using Tiku.Infrastructure.Persistence;

namespace Tiku.Api.Controllers;

[ApiController]
[Tags("学生端-公开目录")]
[AllowAnonymous]
[Produces("application/json")]
[Route("api/catalog")]
[OutputCache(PolicyName = "TenantPublic")]
public sealed class CatalogController(
    ICatalogQueryService catalogQueryService,
    IContentNavigationQueryService contentNavigationQueryService,
    IQuestionBankQueryService questionBankQueryService,
    IStudyContentQueryService studyContentQueryService,
    IAssetQueryService assetQueryService,
    ITenantContext currentTenant,
    TikuDbContext dbContext) : ControllerBase
{
    [HttpGet("regions")]
    [EndpointSummary("查询可用地区")]
    [ProducesResponseType<CatalogList<RegionCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<RegionCatalogItem>>> GetRegions(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetRegionsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("region-modules")]
    [EndpointSummary("查询地区功能模块")]
    [ProducesResponseType<CatalogList<RegionModuleCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<RegionModuleCatalogItem>>> GetRegionModules(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetRegionModulesAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("module-nodes")]
    [EndpointSummary("查询模块导航节点")]
    [ProducesResponseType<CatalogList<ModuleNodeCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<ModuleNodeCatalogItem>>> GetModuleNodes(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetModuleNodesAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("schools")]
    [EndpointSummary("查询院校目录")]
    [ProducesResponseType<CatalogList<SchoolCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<SchoolCatalogItem>>> GetSchools(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetSchoolsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("majors")]
    [EndpointSummary("查询专业目录")]
    [ProducesResponseType<CatalogList<MajorCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<MajorCatalogItem>>> GetMajors(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetMajorsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("subjects")]
    [EndpointSummary("查询科目目录")]
    [ProducesResponseType<CatalogList<SubjectCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<SubjectCatalogItem>>> GetSubjects(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetSubjectsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("categories")]
    [HttpGet("question-categories")]
    [EndpointSummary("查询题目分类")]
    [ProducesResponseType<CatalogList<CategoryCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<CategoryCatalogItem>>> GetCategories(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetCategoriesAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("content-entries")]
    [EndpointSummary("查询内容入口")]
    [ProducesResponseType<CatalogList<ContentEntryCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<ContentEntryCatalogItem>>> GetContentEntries(
        [FromQuery] ContentNavigationQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await contentNavigationQueryService.GetContentEntriesAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("content-nodes")]
    [EndpointSummary("查询内容导航节点")]
    [ProducesResponseType<CatalogList<ContentNodeCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status400BadRequest)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<ContentNodeCatalogItem>>> GetContentNodes(
        [FromQuery] ContentNavigationQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await contentNavigationQueryService.GetContentNodesAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("question-collections")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Practice)]
    [EndpointSummary("查询可用题集")]
    [ProducesResponseType<CatalogList<QuestionCollectionCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<QuestionCollectionCatalogItem>>> GetQuestionCollections(
        [FromQuery] ContentNavigationQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await contentNavigationQueryService.GetQuestionCollectionsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("question-collections/questions")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Practice)]
    [EndpointSummary("查询题集内题目")]
    [ProducesResponseType<CatalogList<CollectionQuestionCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status400BadRequest)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<CollectionQuestionCatalogItem>>> GetCollectionQuestions(
        [FromQuery] ContentNavigationQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await contentNavigationQueryService.GetCollectionQuestionsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("practice-blueprints")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Practice)]
    [EndpointSummary("查询练习蓝图")]
    [ProducesResponseType<CatalogList<PracticeBlueprintCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<PracticeBlueprintCatalogItem>>> GetPracticeBlueprints(
        [FromQuery] ContentNavigationQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await contentNavigationQueryService.GetPracticeBlueprintsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("question-banks")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Practice)]
    [EndpointSummary("查询题库列表")]
    [ProducesResponseType<CatalogList<QuestionBankCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<QuestionBankCatalogItem>>> GetQuestionBanks(
        [FromQuery] QuestionBankQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await questionBankQueryService.GetQuestionBanksAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("questions")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Practice)]
    [EndpointSummary("查询已发布题目")]
    [EndpointDescription("支持按题库、科目、分类、模块节点、内容入口、内容节点、题集或题目 ID 列表筛选。")]
    [ProducesResponseType<CatalogList<QuestionCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<QuestionCatalogItem>>> GetQuestions(
        [FromQuery] QuestionBankQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await questionBankQueryService.GetQuestionsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("questions/{questionId:guid}")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Practice)]
    [EndpointSummary("查询题目详情")]
    [ProducesResponseType<QuestionCatalogItem>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<QuestionCatalogItem>> GetQuestion(
        Guid questionId,
        [FromQuery] QuestionBankQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await questionBankQueryService.GetQuestionAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken), questionId),
            cancellationToken));
    }

    [HttpGet("questions/{questionId:guid}/versions")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Practice)]
    [EndpointSummary("查询题目版本")]
    [ProducesResponseType<CatalogList<QuestionVersionCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<QuestionVersionCatalogItem>>> GetQuestionVersions(
        Guid questionId,
        [FromQuery] QuestionBankQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await questionBankQueryService.GetQuestionVersionsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken), questionId),
            cancellationToken));
    }

    [HttpGet("vocabulary-units")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Vocabulary)]
    [EndpointSummary("查询词汇单元")]
    [ProducesResponseType<CatalogList<VocabularyUnitCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<VocabularyUnitCatalogItem>>> GetVocabularyUnits(
        [FromQuery] StudyContentQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await studyContentQueryService.GetVocabularyUnitsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("vocabulary-words")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Vocabulary)]
    [EndpointSummary("查询词汇单词")]
    [ProducesResponseType<CatalogList<VocabularyWordCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<VocabularyWordCatalogItem>>> GetVocabularyWords(
        [FromQuery] StudyContentQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await studyContentQueryService.GetVocabularyWordsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("handbook-subjects")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Handbook)]
    [EndpointSummary("查询知识手册科目")]
    [ProducesResponseType<CatalogList<HandbookSubjectCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<HandbookSubjectCatalogItem>>> GetHandbookSubjects(
        [FromQuery] StudyContentQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await studyContentQueryService.GetHandbookSubjectsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("handbook-chapters")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Handbook)]
    [EndpointSummary("查询知识手册章节")]
    [ProducesResponseType<CatalogList<HandbookChapterCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<HandbookChapterCatalogItem>>> GetHandbookChapters(
        [FromQuery] StudyContentQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await studyContentQueryService.GetHandbookChaptersAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("handbook-entries")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Handbook)]
    [EndpointSummary("查询知识手册条目")]
    [ProducesResponseType<CatalogList<HandbookEntryCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<HandbookEntryCatalogItem>>> GetHandbookEntries(
        [FromQuery] StudyContentQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await studyContentQueryService.GetHandbookEntriesAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("content-assets")]
    [EndpointSummary("查询内容资源")]
    [ProducesResponseType<CatalogList<ContentAssetCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<ContentAssetCatalogItem>>> GetContentAssets(
        [FromQuery] AssetQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await assetQueryService.GetContentAssetsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("images")]
    [EndpointSummary("查询图片资源")]
    [ProducesResponseType<CatalogList<ImageAssetCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<ImageAssetCatalogItem>>> GetImages(
        [FromQuery] AssetQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await assetQueryService.GetImagesAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("app-assets")]
    [EndpointSummary("查询应用资源")]
    [ProducesResponseType<CatalogList<AppAssetCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<AppAssetCatalogItem>>> GetAppAssets(
        [FromQuery] AssetQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await assetQueryService.GetAppAssetsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("video-explanations")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Video)]
    [EndpointSummary("查询视频讲解")]
    [ProducesResponseType<CatalogList<VideoExplanationCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<VideoExplanationCatalogItem>>> GetVideoExplanations(
        [FromQuery] AssetQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await assetQueryService.GetVideoExplanationsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("question-videos")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.Video)]
    [EndpointSummary("查询题目关联视频")]
    [ProducesResponseType<CatalogList<QuestionVideoCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<QuestionVideoCatalogItem>>> GetQuestionVideos(
        [FromQuery] AssetQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await assetQueryService.GetQuestionVideosAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("banners")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.SiteContent)]
    [EndpointSummary("查询首页横幅")]
    [ProducesResponseType<CatalogList<BannerCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<BannerCatalogItem>>> GetBanners(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetBannersAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("faqs")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.SiteContent)]
    [EndpointSummary("查询常见问题")]
    [ProducesResponseType<CatalogList<FaqCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<FaqCatalogItem>>> GetFaqs(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetFaqsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("announcements")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.SiteContent)]
    [EndpointSummary("查询公告")]
    [ProducesResponseType<CatalogList<AnnouncementCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<AnnouncementCatalogItem>>> GetAnnouncements(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetAnnouncementsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("exam-dates")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.SiteContent)]
    [EndpointSummary("查询考试日期")]
    [ProducesResponseType<CatalogList<ExamDateCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<ExamDateCatalogItem>>> GetExamDates(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetExamDatesAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("products")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.StudentStore)]
    [EndpointSummary("查询可购买产品")]
    [ProducesResponseType<CatalogList<ProductCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<ProductCatalogItem>>> GetProducts(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetProductsAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    [HttpGet("svip-plans")]
    [Tiku.Api.Security.RequireSaasFeature(SaasFeatureCatalog.StudentStore)]
    [EndpointSummary("查询 SVIP 套餐")]
    [ProducesResponseType<CatalogList<SvipPlanCatalogItem>>(StatusCodes.Status200OK)]
    [ProducesResponseType<ProblemDetails>(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CatalogList<SvipPlanCatalogItem>>> GetSvipPlans(
        [FromQuery] CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        return Ok(await catalogQueryService.GetSvipPlansAsync(
            query.ToFilter(await ResolveTenantIdAsync(query, cancellationToken)),
            cancellationToken));
    }

    private async Task<Guid> ResolveTenantIdAsync(
        CatalogQueryDto query,
        CancellationToken cancellationToken)
    {
        if (currentTenant.TenantId.HasValue)
        {
            return currentTenant.TenantId.Value;
        }

        var tenantCode = query.TenantCode ?? Request.Headers["x-tenant-code"].FirstOrDefault();
        if (string.IsNullOrWhiteSpace(tenantCode))
        {
            throw new TenantNotFoundException();
        }

        var tenantId = await dbContext.Tenants
            .Where(tenant =>
                tenant.Slug == tenantCode.Trim() &&
                tenant.Status == TenantStatus.Active)
            .Select(tenant => (Guid?)tenant.Id)
            .SingleOrDefaultAsync(cancellationToken);

        return tenantId ?? throw new TenantNotFoundException();
    }

    private Task<Guid> ResolveTenantIdAsync(
        ContentNavigationQueryDto query,
        CancellationToken cancellationToken)
    {
        return ResolveTenantIdAsync(
            new CatalogQueryDto
            {
                TenantCode = query.TenantCode
            },
            cancellationToken);
    }

    private Task<Guid> ResolveTenantIdAsync(
        QuestionBankQueryDto query,
        CancellationToken cancellationToken)
    {
        return ResolveTenantIdAsync(
            new CatalogQueryDto
            {
                TenantCode = query.TenantCode
            },
            cancellationToken);
    }

    private Task<Guid> ResolveTenantIdAsync(
        StudyContentQueryDto query,
        CancellationToken cancellationToken)
    {
        return ResolveTenantIdAsync(
            new CatalogQueryDto
            {
                TenantCode = query.TenantCode
            },
            cancellationToken);
    }

    private Task<Guid> ResolveTenantIdAsync(
        AssetQueryDto query,
        CancellationToken cancellationToken)
    {
        return ResolveTenantIdAsync(
            new CatalogQueryDto
            {
                TenantCode = query.TenantCode
            },
            cancellationToken);
    }
}

public sealed class TenantNotFoundException : Exception
{
    public TenantNotFoundException()
        : base("Tenant was not found.")
    {
    }
}
