using System.Collections.Generic;
using CommunityToolkit.Mvvm.ComponentModel;
using ClaudeDo.Data.Models;
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;

namespace ClaudeDo.Ui.ViewModels.Islands;

public sealed partial class TaskRowViewModel : ViewModelBase
{
    public required string Id { get; init; }
    [ObservableProperty] private string _title = "";
    [ObservableProperty] private string _listName = "";
    [ObservableProperty] private bool _done;
    [ObservableProperty] private bool _isStarred;
    [ObservableProperty] private bool _isMyDay;
    [ObservableProperty] private bool _isSelected;
    [ObservableProperty] private TaskStatus _status;
    [ObservableProperty] private string? _branch;
    [ObservableProperty] private string? _diffStat;
    [ObservableProperty] private string? _liveTail;
    [ObservableProperty] private DateTime? _scheduledFor;
    [ObservableProperty] private int _diffAdditions;
    [ObservableProperty] private int _diffDeletions;
    [ObservableProperty] private bool _dropHintAbove;
    [ObservableProperty] private bool _dropHintBelow;

    public DateTime CreatedAt { get; init; }
    public string CreatedAtFormatted => CreatedAt == default ? "—" : $"Created {CreatedAt:MMM d}";

    public IReadOnlyList<string> Tags { get; init; } = Array.Empty<string>();
    public int StepsCount { get; init; }
    public int StepsCompleted { get; init; }

    public bool HasBranch   => !string.IsNullOrWhiteSpace(Branch);
    public bool HasDiff     => DiffAdditions > 0 || DiffDeletions > 0;
    public bool HasTags     => Tags.Count > 0;
    public bool HasSteps    => StepsCount > 0;
    public bool IsOverdue   => ScheduledFor is { } d && d.Date < DateTime.Today && !Done;
    public bool IsRunning   => Status == TaskStatus.Running;
    public bool IsQueued    => Status == TaskStatus.Queued;
    public bool HasSchedule => ScheduledFor.HasValue;
    public bool HasLiveTail => IsRunning && !string.IsNullOrEmpty(LiveTail);

    public string DiffAdditionsText => $"+{DiffAdditions}";
    public string DiffDeletionsText => $"−{DiffDeletions}";
    public string StepsText         => $"{StepsCompleted}/{StepsCount} steps";

    public string StatusChipClass => Status switch
    {
        TaskStatus.Running => "running",
        TaskStatus.Failed  => "error",
        TaskStatus.Done    => "review",
        TaskStatus.Queued  => "queued",
        _                  => "idle",
    };

    partial void OnStatusChanged(TaskStatus value)
    {
        OnPropertyChanged(nameof(StatusChipClass));
        OnPropertyChanged(nameof(IsRunning));
        OnPropertyChanged(nameof(IsQueued));
        OnPropertyChanged(nameof(HasLiveTail));
    }

    partial void OnBranchChanged(string? value)    => OnPropertyChanged(nameof(HasBranch));
    partial void OnLiveTailChanged(string? value)  => OnPropertyChanged(nameof(HasLiveTail));
    partial void OnDoneChanged(bool value)         => OnPropertyChanged(nameof(IsOverdue));
    partial void OnScheduledForChanged(DateTime? value)
    {
        OnPropertyChanged(nameof(IsOverdue));
        OnPropertyChanged(nameof(HasSchedule));
    }
    partial void OnDiffAdditionsChanged(int value) { OnPropertyChanged(nameof(HasDiff)); OnPropertyChanged(nameof(DiffAdditionsText)); }
    partial void OnDiffDeletionsChanged(int value) { OnPropertyChanged(nameof(HasDiff)); OnPropertyChanged(nameof(DiffDeletionsText)); }

    public static TaskRowViewModel FromEntity(TaskEntity t)
    {
        var (add, del) = ParseDiffStat(t.Worktree?.DiffStat);
        return new TaskRowViewModel
        {
            Id            = t.Id,
            Title         = t.Title,
            ListName      = t.List?.Name ?? "",
            Done          = t.Status == TaskStatus.Done,
            IsStarred     = t.IsStarred,
            IsMyDay       = t.IsMyDay,
            Status        = t.Status,
            Branch        = t.Worktree?.BranchName,
            DiffStat      = t.Worktree?.DiffStat,
            ScheduledFor  = t.ScheduledFor,
            DiffAdditions = add,
            DiffDeletions = del,
            CreatedAt     = t.CreatedAt,
        };
    }

    // Best-effort parse of diff stat strings like "+12 -3" or "12 additions, 3 deletions".
    private static (int add, int del) ParseDiffStat(string? s)
    {
        if (string.IsNullOrWhiteSpace(s)) return (0, 0);
        int add = 0, del = 0;
        var parts = s.Split(new[] { ' ', ',', '\t' }, StringSplitOptions.RemoveEmptyEntries);
        foreach (var p in parts)
        {
            if (p.Length > 1 && p[0] == '+' && int.TryParse(p.AsSpan(1), out var a)) add = a;
            else if (p.Length > 1 && (p[0] == '-' || p[0] == '\u2212') && int.TryParse(p.AsSpan(1), out var d)) del = d;
        }
        return (add, del);
    }
}
