using FruitBank.Common.Entities;
using LinqToDB;
using Mango.Nop.Data.Repositories;
using Nop.Core.Caching;
using Nop.Core.Configuration;
using Nop.Core.Events;
using Nop.Data;

namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;

public class EkaerHistoryDbTable : MgDbTableBase<EkaerHistory>
{
    public EkaerHistoryDbTable(IEventPublisher eventPublisher, INopDataProvider dataProvider, IShortTermCacheManager shortTermCacheManager, IStaticCacheManager staticCacheManager, AppSettings appSettings)
        : base(eventPublisher, dataProvider, shortTermCacheManager, staticCacheManager, appSettings)
    {
    }

    // History tábla: legújabb elöl.
    public override IOrderedQueryable<EkaerHistory> GetAll() => base.GetAll().OrderByDescending(p => p.Id);

    // loadRelations → a deklarációt lefedő forrás-mapping sorok (Mappings) is töltődnek (a kliensnek kellenek).
    public IQueryable<EkaerHistory> GetAll(bool loadRelations)
        => loadRelations ? GetAll().LoadWith(eh => eh.Mappings) : GetAll();

    // FirstOrDefaultAsync kétértelmű (System.Linq.Async + LinqToDB) az IQueryable-ön (a GetAll(loadRelations) LoadWith
    // miatt már nem IOrderedQueryable) → explicit a LinqToDB-é, ugyanúgy mint a CountByFilterAsync-nél.
    public Task<EkaerHistory> GetByIdAsync(int id, bool loadRelations) => LinqToDB.AsyncExtensions.FirstOrDefaultAsync(GetAll(loadRelations), p => p.Id == id);

    // A NAV-nál lévő partíciók fix StatusId-k; minden más (a jövőbeni új státuszok is) „beküldésre váró".
    private static readonly int[] ToSubmitStatusIds = [.. Enum.GetValues<EkaerStatus>().Select(s => (int)s).Except([(int)EkaerStatus.Sent, (int)EkaerStatus.SentWithMissingData])];

    /// <summary>Flag-alapú szűrés a tabokhoz/count-hoz. <see cref="EkaerHistoryFilter.All"/> (= 0) → minden;
    /// egyébként a beállított flag-ek diszjunkt StatusId-partícióinak UNIÓJA (IN). A státusz-helperek (IsSent stb.)
    /// nem fordulnak SQL-re, ezért közvetlen StatusId-halmazzal szűrünk.</summary>
    public IQueryable<EkaerHistory> GetByFilter(EkaerHistoryFilter filter, bool loadRelations)
    {
        // HasFlag(All) mindig true (0 bit), ezért előbb az All-ágat zárjuk rövidre.
        if (filter == EkaerHistoryFilter.All) return GetAll(loadRelations);

        var statusIds = new List<int>();
        if (filter.HasFlag(EkaerHistoryFilter.ToSubmit)) statusIds.AddRange(ToSubmitStatusIds);
        if (filter.HasFlag(EkaerHistoryFilter.Sent)) statusIds.Add((int)EkaerStatus.Sent);
        if (filter.HasFlag(EkaerHistoryFilter.NeedsCompletion)) statusIds.Add((int)EkaerStatus.SentWithMissingData);

        return GetAll(loadRelations).Where(eh => statusIds.Contains(eh.StatusId));
    }

    // A CountAsync kétértelmű (a System.Linq.Async ÉS a LinqToDB is hozza ugyanazt a nevet, no-arg hívásnál mindkettő illik)
    // → explicit a LinqToDB-é. (A ToListAsync nem ütközik, azt a hívó közvetlenül használhatja.)
    public Task<int> CountByFilterAsync(EkaerHistoryFilter filter) => LinqToDB.AsyncExtensions.CountAsync(GetByFilter(filter, false));
}
