using Microsoft.EntityFrameworkCore;
using Tiku.Application.Catalog;
using Tiku.Application.Content;

namespace Tiku.Infrastructure.Content;

public sealed partial class DirectContentService
{
    public async Task<CatalogList<OperationContentItem>> GetOperationContentAsync(
        DirectContentActor actor,
        string kind,
        AdminLimitFilter filter,
        CancellationToken cancellationToken = default)
    {
        var items = NormalizeOperationKind(kind) switch
        {
            "banners" => (await dbContext.Banners.AsNoTracking()
                .Where(item => item.TenantId == actor.TenantId)
                .Where(item => !filter.RegionId.HasValue || item.RegionId == filter.RegionId.Value)
                .Where(item => string.Equals(filter.Status, "all", StringComparison.OrdinalIgnoreCase) || item.IsActive)
                .OrderBy(item => item.SortOrder)
                .ThenByDescending(item => item.CreatedAt)
                .Take(ResolveLimit(filter.Limit))
                .ToArrayAsync(cancellationToken)).Select(ToOperationItem).ToArray(),
            "faqs" => (await dbContext.Faqs.AsNoTracking()
                .Where(item => item.TenantId == actor.TenantId)
                .Where(item => !filter.RegionId.HasValue || item.RegionId == filter.RegionId.Value)
                .Where(item => string.Equals(filter.Status, "all", StringComparison.OrdinalIgnoreCase) || item.IsActive)
                .OrderBy(item => item.SortOrder)
                .ThenBy(item => item.CreatedAt)
                .Take(ResolveLimit(filter.Limit))
                .ToArrayAsync(cancellationToken)).Select(ToOperationItem).ToArray(),
            "announcements" => (await dbContext.Announcements.AsNoTracking()
                .Where(item => item.TenantId == actor.TenantId)
                .Where(item => string.Equals(filter.Status, "all", StringComparison.OrdinalIgnoreCase) || item.IsActive)
                .OrderBy(item => item.SortOrder)
                .ThenByDescending(item => item.CreatedAt)
                .Take(ResolveLimit(filter.Limit))
                .ToArrayAsync(cancellationToken)).Select(ToOperationItem).ToArray(),
            "exam-dates" => (await dbContext.ExamDates.AsNoTracking()
                .Where(item => item.TenantId == actor.TenantId)
                .Where(item => !filter.RegionId.HasValue || item.RegionId == filter.RegionId.Value)
                .Where(item => !filter.SchoolId.HasValue || item.SchoolId == filter.SchoolId.Value)
                .Where(item => string.Equals(filter.Status, "all", StringComparison.OrdinalIgnoreCase) || item.IsActive)
                .OrderBy(item => item.ExamAt == null)
                .ThenBy(item => item.ExamAt)
                .ThenBy(item => item.SortOrder)
                .Take(ResolveLimit(filter.Limit))
                .ToArrayAsync(cancellationToken)).Select(ToOperationItem).ToArray(),
            _ => throw new ContentManagementException("Operation content kind is invalid.",
                "operation_content_kind_invalid")
        };

        return new CatalogList<OperationContentItem>(items);
    }

    public async Task<ContentManagementResult<OperationContentItem>> UpsertOperationContentAsync(
        DirectContentActor actor,
        string kind,
        OperationContentCommand command,
        CancellationToken cancellationToken = default)
    {
        var item = NormalizeOperationKind(kind) switch
        {
            "banners" => ToOperationItem(await UpsertBannerAsync(actor, command, cancellationToken)),
            "faqs" => ToOperationItem(await UpsertFaqAsync(actor, command, cancellationToken)),
            "announcements" => ToOperationItem(await UpsertAnnouncementAsync(actor, command, cancellationToken)),
            "exam-dates" => ToOperationItem(await UpsertExamDateAsync(actor, command, cancellationToken)),
            _ => throw new ContentManagementException("Operation content kind is invalid.",
                "operation_content_kind_invalid")
        };

        return new ContentManagementResult<OperationContentItem>(item);
    }
}