using Microsoft.EntityFrameworkCore;
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Infrastructure.App.Persistence;

namespace TakeoutSaaS.Infrastructure.App.Repositories;

/// <summary>
/// EF 租户公告仓储。
/// </summary>
public sealed class EfTenantAnnouncementRepository(TakeoutAppDbContext context) : ITenantAnnouncementRepository
{
    /// <inheritdoc />
    public Task<IReadOnlyList<TenantAnnouncement>> SearchAsync(
        long tenantId,
        TenantAnnouncementType? type,
        bool? isActive,
        DateTime? effectiveAt,
        CancellationToken cancellationToken = default)
    {
        var query = context.TenantAnnouncements.AsNoTracking()
            .Where(x => x.TenantId == tenantId);

        if (type.HasValue)
        {
            query = query.Where(x => x.AnnouncementType == type.Value);
        }

        if (isActive.HasValue)
        {
            query = query.Where(x => x.IsActive == isActive.Value);
        }

        if (effectiveAt.HasValue)
        {
            var at = effectiveAt.Value;
            query = query.Where(x => x.EffectiveFrom <= at && (x.EffectiveTo == null || x.EffectiveTo >= at));
        }

        return query
            .OrderByDescending(x => x.Priority)
            .ThenByDescending(x => x.CreatedAt)
            .ToListAsync(cancellationToken)
            .ContinueWith(t => (IReadOnlyList<TenantAnnouncement>)t.Result, cancellationToken);
    }

    /// <inheritdoc />
    public Task<TenantAnnouncement?> FindByIdAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default)
    {
        return context.TenantAnnouncements.AsNoTracking()
            .FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == announcementId, cancellationToken);
    }

    /// <inheritdoc />
    public Task AddAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default)
    {
        return context.TenantAnnouncements.AddAsync(announcement, cancellationToken).AsTask();
    }

    /// <inheritdoc />
    public Task UpdateAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default)
    {
        context.TenantAnnouncements.Update(announcement);
        return Task.CompletedTask;
    }

    /// <inheritdoc />
    public async Task DeleteAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default)
    {
        var entity = await context.TenantAnnouncements.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == announcementId, cancellationToken);
        if (entity != null)
        {
            context.TenantAnnouncements.Remove(entity);
        }
    }

    /// <inheritdoc />
    public Task SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        return context.SaveChangesAsync(cancellationToken);
    }
}
