using ClaudeDo.Ui.Localization;
using ClaudeDo.Ui.Services;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace ClaudeDo.Ui.ViewModels.Modals;

public sealed partial class WeeklyReportModalViewModel : ViewModelBase
{
    private readonly IWorkerClient _worker;

    public WeeklyReportModalViewModel(IWorkerClient worker)
    {
        _worker = worker;
        // OperationStatus is a nested ObservableObject — [NotifyCanExecuteChangedFor] can't see
        // into it, so IsRunning changes are relayed by hand.
        GenerateOperation.PropertyChanged += (_, e) =>
        {
            if (e.PropertyName != nameof(OperationStatus.IsRunning)) return;
            GenerateCommand.NotifyCanExecuteChanged();
            OnPropertyChanged(nameof(EmptyStateVisible));
        };
    }

    public OperationStatus GenerateOperation { get; } = new();

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(HasReport))]
    [NotifyPropertyChangedFor(nameof(EmptyStateVisible))]
    private string? _reportMarkdown;

    [ObservableProperty] private DateTime? _startDate;
    [ObservableProperty] private DateTime? _endDate;
    [ObservableProperty] private string _statusMessage = "";

    public bool HasReport => !string.IsNullOrWhiteSpace(ReportMarkdown);
    public bool EmptyStateVisible => !HasReport && !GenerateOperation.IsRunning;

    public Action? CloseAction { get; set; }
    [RelayCommand] private void Close() => CloseAction?.Invoke();

    public static (DateOnly Start, DateOnly End) DefaultRange(DayOfWeek standup, DateOnly today)
    {
        int diff = ((int)today.DayOfWeek - (int)standup + 7) % 7;
        if (diff == 0) diff = 7;
        return (today.AddDays(-diff), today);
    }

    public async Task InitializeAsync()
    {
        var standup = DayOfWeek.Wednesday;
        var settings = await _worker.GetAppSettingsAsync();
        if (settings is not null && settings.StandupWeekday is >= 0 and <= 6)
            standup = (DayOfWeek)settings.StandupWeekday;

        var (start, end) = DefaultRange(standup, DateOnly.FromDateTime(DateTime.Today));
        StartDate = start.ToDateTime(TimeOnly.MinValue);
        EndDate = end.ToDateTime(TimeOnly.MinValue);
        await LoadStoredAsync();
    }

    partial void OnStartDateChanged(DateTime? value) => _ = LoadStoredAsync();
    partial void OnEndDateChanged(DateTime? value) => _ = LoadStoredAsync();

    private bool RangeValid => StartDate is not null && EndDate is not null && StartDate <= EndDate;

    private async Task LoadStoredAsync()
    {
        if (!RangeValid) return;
        StatusMessage = "";
        try
        {
            ReportMarkdown = await _worker.GetWeekReportAsync(
                DateOnly.FromDateTime(StartDate!.Value), DateOnly.FromDateTime(EndDate!.Value));
        }
        catch (Exception ex) { StatusMessage = ex.Message; }
    }

    private bool CanGenerate() => !GenerateOperation.IsRunning;

    [RelayCommand(CanExecute = nameof(CanGenerate))]
    private async Task Generate()
    {
        if (!RangeValid) { StatusMessage = Loc.T("vm.weeklyReport.invalidRange"); return; }
        using var op = GenerateOperation.Begin(Loc.T("ops.reports.generatingWeekly"));
        StatusMessage = "";
        try
        {
            ReportMarkdown = await _worker.GenerateWeekReportAsync(
                DateOnly.FromDateTime(StartDate!.Value), DateOnly.FromDateTime(EndDate!.Value));
        }
        catch (Exception ex) { StatusMessage = Loc.T("vm.weeklyReport.error", ex.Message); }
    }
}
