using FrontOffice.Main.Utilities;
using Microsoft.AspNetCore.Components;
using MudBlazor;

namespace FrontOffice.Main.Shared;

public partial class WeekSelector : ComponentBase
{
    [Inject] private CommissionService CommissionService { get; set; } = default!;

    /// <summary>
    /// Selected week definition
    /// </summary>
    [Parameter] public WeekDefinitionDto? Value { get; set; }
    
    /// <summary>
    /// Callback when week selection changes
    /// </summary>
    [Parameter] public EventCallback<WeekDefinitionDto?> ValueChanged { get; set; }

    /// <summary>
    /// Label for the input
    /// </summary>
    [Parameter] public string Label { get; set; } = "انتخاب هفته";
    
    /// <summary>
    /// Placeholder text
    /// </summary>
    [Parameter] public string Placeholder { get; set; } = "هفته را انتخاب کنید...";
    
    /// <summary>
    /// Input variant
    /// </summary>
    [Parameter] public Variant Variant { get; set; } = Variant.Outlined;
    
    /// <summary>
    /// Dense mode
    /// </summary>
    [Parameter] public bool Dense { get; set; } = false;
    
    /// <summary>
    /// Input margin
    /// </summary>
    [Parameter] public Margin Margin { get; set; } = Margin.Normal;
    
    /// <summary>
    /// Allow clearing the selection
    /// </summary>
    [Parameter] public bool Clearable { get; set; } = true;
    
    /// <summary>
    /// CSS class
    /// </summary>
    [Parameter] public string? Class { get; set; }

    /// <summary>
    /// Inline style
    /// </summary>
    [Parameter] public string? Style { get; set; }

    /// <summary>
    /// Persian year filter
    /// </summary>
    [Parameter] public int? PersianYear { get; set; }
    
    /// <summary>
    /// Gregorian year filter
    /// </summary>
    [Parameter] public int? GregorianYear { get; set; }
    
    /// <summary>
    /// Only show active weeks
    /// </summary>
    [Parameter] public bool? OnlyActive { get; set; } = true;

    private WeekDefinitionDto? _selectedWeek
    {
        get => Value;
        set
        {
            if (Value != value)
            {
                Value = value;
                ValueChanged.InvokeAsync(value);
            }
        }
    }
    private List<WeekDefinitionDto> _cachedWeeks = new();
    private bool _isLoading = false;

    protected override async Task OnInitializedAsync()
    {
        // Pre-load weeks
        await LoadWeeksAsync();
    }

    private async Task LoadWeeksAsync()
    {
        try
        {
            _isLoading = true;
            _cachedWeeks = await CommissionService.GetWeekDefinitionsAsync(
                searchText: null,
                gregorianYear: GregorianYear,
                persianYear: PersianYear,
                isActive: OnlyActive,
                pageSize: 100
            );
        }
        catch
        {
            _cachedWeeks = new List<WeekDefinitionDto>();
        }
        finally
        {
            _isLoading = false;
        }
    }

    private async Task<IEnumerable<WeekDefinitionDto>> SearchWeeksAsync(string searchText, CancellationToken cancellationToken)
    {
        // If cached weeks are empty, load them
        if (!_cachedWeeks.Any())
        {
            await LoadWeeksAsync();
        }

        // Filter locally from cache
        if (string.IsNullOrWhiteSpace(searchText))
            return _cachedWeeks;

        return _cachedWeeks.Where(w => 
            w.DisplayName.Contains(searchText, StringComparison.OrdinalIgnoreCase) ||
            w.StartDatePersian.Contains(searchText, StringComparison.OrdinalIgnoreCase) ||
            w.EndDatePersian.Contains(searchText, StringComparison.OrdinalIgnoreCase));
    }

    private async Task OnWeekChanged(WeekDefinitionDto? week)
    {
        _selectedWeek = week;
    }

    /// <summary>
    /// Get current week from cached weeks
    /// </summary>
    public WeekDefinitionDto? GetCurrentWeek()
    {
        return _cachedWeeks.FirstOrDefault(w => w.IsCurrentWeek);
    }

    /// <summary>
    /// Select current week
    /// </summary>
    public async Task SelectCurrentWeekAsync()
    {
        var currentWeek = GetCurrentWeek();
        if (currentWeek != null)
        {
            _selectedWeek = currentWeek;
            StateHasChanged();
        }
        await Task.CompletedTask;
    }

    /// <summary>
    /// Find week by WeekOrder number (e.g., 46 from ?week=46)
    /// </summary>
    public WeekDefinitionDto? FindByWeekOrder(int weekOrder)
    {
        return _cachedWeeks.FirstOrDefault(w => w.WeekOrder == weekOrder);
    }

    /// <summary>
    /// Find week by Id
    /// </summary>
    public WeekDefinitionDto? FindById(long id)
    {
        return _cachedWeeks.FirstOrDefault(w => w.Id == id);
    }

    /// <summary>
    /// Select week by WeekOrder
    /// </summary>
    public async Task SelectByWeekOrderAsync(int weekOrder)
    {
        var week = FindByWeekOrder(weekOrder);
        if (week != null)
        {
            _selectedWeek = week;
            StateHasChanged();
        }
        await Task.CompletedTask;
    }

    /// <summary>
    /// Ensure weeks are loaded (useful for parent components)
    /// </summary>
    public async Task EnsureLoadedAsync()
    {
        if (!_cachedWeeks.Any())
        {
            await LoadWeeksAsync();
        }
    }

    /// <summary>
    /// Get all cached weeks
    /// </summary>
    public IReadOnlyList<WeekDefinitionDto> GetCachedWeeks() => _cachedWeeks.AsReadOnly();
}
