using System.Globalization;
using ClaudeDo.Data.Models;
using ClaudeDo.Ui.Localization;
using ClaudeDo.Ui.Services;
using CommunityToolkit.Mvvm.ComponentModel;

namespace ClaudeDo.Ui.ViewModels.Modals.Settings;

public sealed partial class PrimeScheduleRowViewModel : ViewModelBase
{
    private const int Mon = 1, Tue = 2, Wed = 4, Thu = 8, Fri = 16, Sat = 32, Sun = 64;

    public Guid Id { get; }
    public bool IsExisting { get; }

    [ObservableProperty] private bool _enabled;
    [ObservableProperty] private bool _monday;
    [ObservableProperty] private bool _tuesday;
    [ObservableProperty] private bool _wednesday;
    [ObservableProperty] private bool _thursday;
    [ObservableProperty] private bool _friday;
    [ObservableProperty] private bool _saturday;
    [ObservableProperty] private bool _sunday;
    [ObservableProperty] private TimeSpan _timeOfDay;
    [ObservableProperty] private DateTimeOffset? _lastRunAt;
    [ObservableProperty] private string? _promptOverride;
    [ObservableProperty] private PrimeActionKind _kind;

    public string LastRunLabel => LastRunAt is { } v ? v.LocalDateTime.ToString("g") : "—";

    private static readonly string[] TimeFormats = { @"h\:mm", @"hh\:mm" };

    public string TimeText
    {
        get => TimeOfDay.ToString(@"hh\:mm", CultureInfo.InvariantCulture);
        set
        {
            if (TimeSpan.TryParseExact(value, TimeFormats, CultureInfo.InvariantCulture, out var t)
                && t >= TimeSpan.Zero && t < TimeSpan.FromDays(1))
            {
                TimeOfDay = t;
            }
            OnPropertyChanged(nameof(TimeText));
        }
    }

    /// <summary>Per-row group name. A shared GroupName would make every schedule in the
    /// ItemsControl share one selection.</summary>
    public string RadioGroup => $"prime-kind-{Id}";

    // Three booleans rather than an enum-to-bool converter: RadioButton.IsChecked binds
    // TwoWay to a bool, and compiled bindings stay simple.
    public bool IsPing
    {
        get => Kind == PrimeActionKind.Ping;
        set { if (value) Kind = PrimeActionKind.Ping; }
    }

    public bool IsFillMyDay
    {
        get => Kind == PrimeActionKind.FillMyDay;
        set { if (value) Kind = PrimeActionKind.FillMyDay; }
    }

    public bool IsCustom
    {
        get => Kind == PrimeActionKind.Custom;
        set { if (value) Kind = PrimeActionKind.Custom; }
    }

    public bool ShowPrompt => Kind != PrimeActionKind.Ping;

    public string PromptLabel => Kind == PrimeActionKind.Custom
        ? Loc.T("settings.prime.customPromptLabel")
        : Loc.T("settings.prime.promptOverrideLabel");

    public string PromptPlaceholder => Kind == PrimeActionKind.Custom
        ? Loc.T("settings.prime.customPromptPlaceholder")
        : Loc.T("settings.prime.promptOverridePlaceholder");

    partial void OnKindChanged(PrimeActionKind value)
    {
        OnPropertyChanged(nameof(IsPing));
        OnPropertyChanged(nameof(IsFillMyDay));
        OnPropertyChanged(nameof(IsCustom));
        OnPropertyChanged(nameof(ShowPrompt));
        OnPropertyChanged(nameof(PromptLabel));
        OnPropertyChanged(nameof(PromptPlaceholder));
    }

    partial void OnLastRunAtChanged(DateTimeOffset? value) => OnPropertyChanged(nameof(LastRunLabel));

    partial void OnTimeOfDayChanged(TimeSpan value) => OnPropertyChanged(nameof(TimeText));

    public PrimeScheduleRowViewModel(PrimeScheduleDto dto, bool isExisting)
    {
        Id = dto.Id;
        IsExisting = isExisting;
        Enabled = dto.Enabled;
        Monday = (dto.Days & Mon) != 0;
        Tuesday = (dto.Days & Tue) != 0;
        Wednesday = (dto.Days & Wed) != 0;
        Thursday = (dto.Days & Thu) != 0;
        Friday = (dto.Days & Fri) != 0;
        Saturday = (dto.Days & Sat) != 0;
        Sunday = (dto.Days & Sun) != 0;
        TimeOfDay = dto.TimeOfDay;
        LastRunAt = dto.LastRunAt;
        PromptOverride = dto.PromptOverride;
        Kind = dto.Kind;
    }

    public int DaysMask()
    {
        int m = 0;
        if (Monday) m |= Mon;
        if (Tuesday) m |= Tue;
        if (Wednesday) m |= Wed;
        if (Thursday) m |= Thu;
        if (Friday) m |= Fri;
        if (Saturday) m |= Sat;
        if (Sunday) m |= Sun;
        return m;
    }

    public PrimeScheduleDto ToDto() =>
        new(Id, DaysMask(), TimeOfDay, Enabled, LastRunAt,
            string.IsNullOrWhiteSpace(PromptOverride) ? null : PromptOverride, Kind);
}
