using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using ClaudeDo.Data.Models;
using ClaudeDo.Ui.Services;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace ClaudeDo.Ui.ViewModels.Modals.Settings;

public sealed partial class PrimeClaudeTabViewModel : ViewModelBase
{
    private readonly IPrimeScheduleApi _api;
    private readonly HashSet<Guid> _initialIds = new();

    [ObservableProperty] private int _dailyPrepMaxTasks = 5;
    [ObservableProperty] private bool _anyFillMyDay;

    public ObservableCollection<PrimeScheduleRowViewModel> Rows { get; } = new();

    public PrimeClaudeTabViewModel(IPrimeScheduleApi api)
    {
        _api = api;
        Rows.CollectionChanged += OnRowsChanged;
    }

    private void OnRowsChanged(object? sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.OldItems is not null)
            foreach (PrimeScheduleRowViewModel r in e.OldItems) r.PropertyChanged -= OnRowChanged;
        if (e.NewItems is not null)
            foreach (PrimeScheduleRowViewModel r in e.NewItems) r.PropertyChanged += OnRowChanged;
        UpdateAnyFillMyDay();
    }

    private void OnRowChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(PrimeScheduleRowViewModel.Kind)) UpdateAnyFillMyDay();
    }

    private void UpdateAnyFillMyDay() =>
        AnyFillMyDay = Rows.Any(r => r.Kind == PrimeActionKind.FillMyDay);

    public async Task LoadAsync()
    {
        foreach (var r in Rows) r.PropertyChanged -= OnRowChanged;
        Rows.Clear();
        _initialIds.Clear();
        var list = await _api.ListAsync();
        foreach (var dto in list)
        {
            Rows.Add(new PrimeScheduleRowViewModel(dto, isExisting: true));
            _initialIds.Add(dto.Id);
        }
    }

    public string? Validate()
    {
        foreach (var r in Rows)
        {
            if (r.DaysMask() == 0)
                return $"Schedule {r.TimeOfDay:hh\\:mm}: select at least one day.";
            if (r.TimeOfDay < TimeSpan.Zero || r.TimeOfDay >= TimeSpan.FromDays(1))
                return "Time must be between 00:00 and 23:59.";
            if (r.Kind == PrimeActionKind.Custom && string.IsNullOrWhiteSpace(r.PromptOverride))
                return $"Schedule {r.TimeOfDay:hh\\:mm}: a custom action needs a prompt.";
        }
        return null;
    }

    public async Task SaveAsync()
    {
        var keepIds = Rows.Select(r => r.Id).ToHashSet();
        foreach (var removed in _initialIds.Where(id => !keepIds.Contains(id)).ToList())
            await _api.DeleteAsync(removed);
        foreach (var r in Rows)
            await _api.UpsertAsync(r.ToDto());
        _initialIds.Clear();
        foreach (var id in keepIds) _initialIds.Add(id);
    }

    [RelayCommand]
    private void AddSchedule()
    {
        var dto = new PrimeScheduleDto(
            Id: Guid.NewGuid(),
            Days: 31, // Mon–Fri
            TimeOfDay: new TimeSpan(7, 0, 0),
            Enabled: true,
            LastRunAt: null,
            PromptOverride: null,
            Kind: PrimeActionKind.Ping);
        Rows.Add(new PrimeScheduleRowViewModel(dto, isExisting: false));
    }

    [RelayCommand]
    private void RemoveSchedule(PrimeScheduleRowViewModel? row)
    {
        if (row is null) return;
        Rows.Remove(row);
    }

}
