using CMSMicroservice.Domain.Entities;

namespace CMSMicroservice.Application.Common.Interfaces;

/// <summary>
/// اینترفیس ریپازیتوری هفته‌ها با کش در حافظه
/// این سرویس موقع استارت برنامه از دیتابیس لود می‌شود و در حافظه نگهداری می‌شود
/// </summary>
public interface IWeekDefinitionRepository
{
    /// <summary>
    /// گرفتن هفته جاری
    /// </summary>
    WeekDefinition? GetCurrentWeek();
    
    /// <summary>
    /// گرفتن هفته جاری (async برای سازگاری)
    /// </summary>
    Task<WeekDefinition?> GetCurrentWeekAsync(CancellationToken cancellationToken = default);
    
    /// <summary>
    /// گرفتن هفته بعد
    /// </summary>
    WeekDefinition? GetNextWeek();
    
    /// <summary>
    /// گرفتن هفته بعد از هفته مشخص
    /// </summary>
    WeekDefinition? GetNextWeek(WeekDefinition currentWeek);
    
    /// <summary>
    /// گرفتن هفته قبل
    /// </summary>
    WeekDefinition? GetPreviousWeek();
    
    /// <summary>
    /// گرفتن هفته قبل از هفته مشخص
    /// </summary>
    WeekDefinition? GetPreviousWeek(WeekDefinition currentWeek);
    
    /// <summary>
    /// گرفتن هفته بر اساس تاریخ میلادی
    /// </summary>
    WeekDefinition? GetWeekByDate(DateTime date);
    
    /// <summary>
    /// گرفتن هفته بر اساس شماره هفته میلادی (مثال: "2025-W46")
    /// </summary>
    WeekDefinition? GetWeekByGregorianWeekNumber(string gregorianWeekNumber);
    
    /// <summary>
    /// گرفتن هفته بر اساس شماره هفته شمسی (مثال: "1404-W35")
    /// </summary>
    WeekDefinition? GetWeekByPersianWeekNumber(string persianWeekNumber);
    
    /// <summary>
    /// گرفتن هفته بر اساس شماره ترتیبی
    /// </summary>
    WeekDefinition? GetWeekByOrder(int weekOrder);
    
    /// <summary>
    /// گرفتن لیست همه هفته‌ها
    /// </summary>
    IReadOnlyList<WeekDefinition> GetAllWeeks();
    
    /// <summary>
    /// گرفتن هفته‌های یک سال میلادی خاص
    /// </summary>
    IReadOnlyList<WeekDefinition> GetWeeksByGregorianYear(int year);
    
    /// <summary>
    /// گرفتن هفته‌های یک سال شمسی خاص
    /// </summary>
    IReadOnlyList<WeekDefinition> GetWeeksByPersianYear(int year);
    
    /// <summary>
    /// گرفتن شماره هفته میلادی جاری (مثال: "2025-W51")
    /// </summary>
    string GetCurrentGregorianWeekNumber();
    
    /// <summary>
    /// گرفتن شماره هفته شمسی جاری (مثال: "1404-W39")
    /// </summary>
    string GetCurrentPersianWeekNumber();
    
    /// <summary>
    /// گرفتن نام نمایشی هفته جاری (مثال: "هفته ششم")
    /// </summary>
    string GetCurrentWeekDisplayName();
    
    /// <summary>
    /// آیا تاریخ مشخص در هفته جاری است؟
    /// </summary>
    bool IsDateInCurrentWeek(DateTime date);
    
    /// <summary>
    /// محاسبه شماره هفته میلادی برای یک تاریخ (حتی اگر در کش نباشد)
    /// </summary>
    string CalculateGregorianWeekNumber(DateTime date);
    
    /// <summary>
    /// محاسبه شماره هفته شمسی برای یک تاریخ (حتی اگر در کش نباشد)
    /// </summary>
    string CalculatePersianWeekNumber(DateTime date);
    
    /// <summary>
    /// بارگذاری مجدد کش از دیتابیس
    /// </summary>
    Task ReloadCacheAsync(CancellationToken cancellationToken = default);
    
    /// <summary>
    /// گرفتن بازه تاریخی یک هفته بر اساس شماره هفته میلادی
    /// </summary>
    (DateTime startDate, DateTime endDate)? GetWeekDateRange(string gregorianWeekNumber);

    (DateTime startDate, DateTime endDate)? GetWeekDateRange(long WeekDefinitionId);
    
    /// <summary>
    /// گرفتن شماره هفته قبل از هفته مشخص
    /// </summary>
    string? GetPreviousWeekNumber(string gregorianWeekNumber);
    
    /// <summary>
    /// گرفتن شماره هفته بعد از هفته مشخص
    /// </summary>
    string? GetNextWeekNumber(string gregorianWeekNumber);
    
    /// <summary>
    /// گرفتن DisplayName یک هفته بر اساس شماره هفته میلادی (مثل "هفته یکم")
    /// </summary>
    string GetDisplayNameByGregorianWeekNumber(string gregorianWeekNumber);
    
    /// <summary>
    /// جستجوی هفته‌ها بر اساس DisplayName (برای dropdown)
    /// اگر فیلتر خالی باشد همه هفته‌ها برگردانده می‌شود
    /// </summary>
    IEnumerable<WeekDefinition> SearchWeeksByDisplayName(string? filter = null);
    
    /// <summary>
    /// گرفتن WeekDefinitionId از شماره هفته میلادی
    /// </summary>
    /// <param name="gregorianWeekNumber">شماره هفته میلادی (مثال: "2025-W46")</param>
    /// <returns>شناسه WeekDefinition یا null اگر پیدا نشد</returns>
    long? GetWeekDefinitionId(string gregorianWeekNumber);

    WeekDefinition? GetWeekById(long weekDefinitionId);
    /// <summary>
    /// گرفتن شماره هفته میلادی از WeekDefinitionId
    /// </summary>
    /// <param name="weekDefinitionId">شناسه WeekDefinition</param>
    /// <returns>شماره هفته میلادی یا null اگر پیدا نشد</returns>
    string? GetGregorianWeekNumber(long weekDefinitionId);
    
    /// <summary>
    /// آیا کش لود شده؟
    /// </summary>
    bool IsCacheLoaded { get; }
    
    /// <summary>
    /// تعداد هفته‌های موجود در کش
    /// </summary>
    int CachedWeeksCount { get; }
}
