using System.Collections.ObjectModel;
using System.ComponentModel;
using AxCopilot.Services.Agent;

namespace AxCopilot.ViewModels;

/// <summary>Phase 18-B: 에이전트 이벤트 타임라인 재생 ViewModel.</summary>
public class ReplayTimelineViewModel : INotifyPropertyChanged
{
    private readonly AgentReplayService _replayService;
    private CancellationTokenSource? _replayCts;

    public ObservableCollection<ReplayEventItem> Events { get; } = new();
    public ObservableCollection<ReplaySessionInfo> Sessions { get; } = new();

    private ReplaySessionInfo? _selectedSession;
    public ReplaySessionInfo? SelectedSession
    {
        get => _selectedSession;
        set { _selectedSession = value; OnPropertyChanged(); OnPropertyChanged(nameof(CanReplay)); }
    }

    private bool _isReplaying;
    public bool IsReplaying
    {
        get => _isReplaying;
        set { _isReplaying = value; OnPropertyChanged(); OnPropertyChanged(nameof(CanReplay)); }
    }

    public bool CanReplay => SelectedSession != null && !IsReplaying;

    private int _replaySpeedMs = 200;
    public int ReplaySpeedMs
    {
        get => _replaySpeedMs;
        set { _replaySpeedMs = Math.Max(0, value); OnPropertyChanged(); }
    }

    private int _progressValue;
    public int ProgressValue
    {
        get => _progressValue;
        set { _progressValue = value; OnPropertyChanged(); }
    }

    private int _progressMax = 100;
    public int ProgressMax
    {
        get => _progressMax;
        set { _progressMax = value; OnPropertyChanged(); }
    }

    public ReplayTimelineViewModel()
    {
        _replayService = new AgentReplayService();
    }

    public void LoadSessions()
    {
        Sessions.Clear();
        foreach (var s in _replayService.GetSessions())
            Sessions.Add(s);
        if (Sessions.Count > 0)
            SelectedSession = Sessions[0];
    }

    public async Task StartReplayAsync()
    {
        if (SelectedSession == null || IsReplaying) return;

        Events.Clear();
        IsReplaying = true;
        ProgressValue = 0;
        _replayCts = new CancellationTokenSource();

        try
        {
            // 전체 이벤트 수 먼저 파악
            var allEvents = await _replayService.LoadAllEventsAsync(
                SelectedSession.SessionId, _replayCts.Token);
            ProgressMax = Math.Max(1, allEvents.Count);

            int i = 0;
            await _replayService.ReplayAsync(
                SelectedSession.SessionId,
                async record =>
                {
                    var item = new ReplayEventItem(record);
                    // Dispatcher needed — raise event for UI thread
                    ReplayEventReceived?.Invoke(item);
                    i++;
                    ProgressValue = i;
                    await Task.CompletedTask;
                },
                ReplaySpeedMs,
                _replayCts.Token);
        }
        catch (OperationCanceledException) { }
        finally
        {
            IsReplaying = false;
            _replayCts?.Dispose();
            _replayCts = null;
        }
    }

    public void StopReplay()
    {
        _replayCts?.Cancel();
    }

    /// <summary>UI 스레드에서 이벤트 항목을 추가하기 위한 이벤트.</summary>
    public event Action<ReplayEventItem>? ReplayEventReceived;

    public event PropertyChangedEventHandler? PropertyChanged;
    protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string? name = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

/// <summary>타임라인에 표시할 단일 이벤트 항목.</summary>
public class ReplayEventItem
{
    public AgentEventRecord Record { get; }
    public string TypeLabel { get; }
    public string Icon { get; }
    public string TimeLabel { get; }

    public ReplayEventItem(AgentEventRecord record)
    {
        Record = record;
        TimeLabel = record.Timestamp.ToString("HH:mm:ss");
        (TypeLabel, Icon) = record.Type switch
        {
            AgentEventLogType.SessionStart       => ("세션 시작",         "\uE768"),
            AgentEventLogType.SessionEnd         => ("세션 종료",         "\uE711"),
            AgentEventLogType.UserMessage        => ("사용자 메시지",     "\uE8BD"),
            AgentEventLogType.AssistantMessage   => ("AI 응답",           "\uE8D4"),
            AgentEventLogType.ToolRequest        => ("도구 요청",         "\uE756"),
            AgentEventLogType.ToolResult         => ("도구 결과",         "\uE73E"),
            AgentEventLogType.HookFired          => ("훅 실행",           "\uE81C"),
            AgentEventLogType.HookResult         => ("훅 결과",           "\uE73E"),
            AgentEventLogType.SkillActivated     => ("스킬 활성화",       "\uE82D"),
            AgentEventLogType.SkillCompleted     => ("스킬 완료",         "\uE930"),
            AgentEventLogType.CompactionTriggered  => ("컨텍스트 압축",   "\uE8EC"),
            AgentEventLogType.CompactionCompleted  => ("압축 완료",       "\uE930"),
            AgentEventLogType.SubagentSpawned    => ("서브에이전트 생성", "\uE718"),
            AgentEventLogType.SubagentCompleted  => ("서브에이전트 완료", "\uE930"),
            AgentEventLogType.ReflexionSaved     => ("반성 저장",         "\uE90F"),
            AgentEventLogType.Error              => ("오류",              "\uE783"),
            _                                    => (record.Type.ToString(), "\uE946")
        };
    }
}
