using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace AxCopilot.Services;

public enum PomodoroMode { Idle, Focus, Break }

/// <summary>
/// Phase L3-9: 뽀모도로 타이머 서비스.
/// 집중(기본 25분) / 휴식(기본 5분) 모드를 관리하며 AppData에 상태를 저장합니다.
/// </summary>
internal sealed class PomodoroService
{
    public static readonly PomodoroService Instance = new();

    private static readonly string StateFile = Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
        "AxCopilot", "pomodoro.json");

    // ─── 설정 ────────────────────────────────────────────────────────────────

    public int FocusMinutes { get; set; } = 25;
    public int BreakMinutes { get; set; } = 5;

    // ─── 상태 ────────────────────────────────────────────────────────────────

    public PomodoroMode Mode      { get; private set; } = PomodoroMode.Idle;
    public bool         IsRunning { get; private set; }
    public TimeSpan     Remaining { get; private set; }

    public event EventHandler? StateChanged;

    // ─── 내부 ────────────────────────────────────────────────────────────────

    private System.Threading.Timer? _ticker;

    private PomodoroService()
    {
        LoadState();
        // 앱 재시작 후 진행 중이던 타이머가 있으면 재개
        if (IsRunning && Remaining > TimeSpan.Zero)
            StartTicker();
        else
            IsRunning = false;
    }

    // ─── 공개 API ────────────────────────────────────────────────────────────

    public void StartFocus()  => StartMode(PomodoroMode.Focus);
    public void StartBreak()  => StartMode(PomodoroMode.Break);

    public void Stop()
    {
        StopTicker();
        IsRunning = false;
        SaveState();
        StateChanged?.Invoke(this, EventArgs.Empty);
    }

    public void Reset()
    {
        StopTicker();
        Mode      = PomodoroMode.Idle;
        IsRunning = false;
        Remaining = TimeSpan.FromMinutes(FocusMinutes);
        SaveState();
        StateChanged?.Invoke(this, EventArgs.Empty);
    }

    public void Toggle()
    {
        if (IsRunning)         Stop();
        else if (Mode == PomodoroMode.Break) StartBreak();
        else                   StartFocus();
    }

    // ─── 내부 ────────────────────────────────────────────────────────────────

    private void StartMode(PomodoroMode mode)
    {
        StopTicker();
        Mode      = mode;
        IsRunning = true;
        if (Remaining <= TimeSpan.Zero || Mode != mode)
            Remaining = TimeSpan.FromMinutes(mode == PomodoroMode.Focus ? FocusMinutes : BreakMinutes);
        StartTicker();
        SaveState();
        StateChanged?.Invoke(this, EventArgs.Empty);
    }

    private void StartTicker()
    {
        _ticker = new System.Threading.Timer(_ => Tick(), null, 1000, 1000);
    }

    private void StopTicker()
    {
        _ticker?.Dispose();
        _ticker = null;
    }

    private void Tick()
    {
        if (Remaining <= TimeSpan.Zero)
        {
            // 타이머 종료
            Stop();
            var modeLabel = Mode == PomodoroMode.Focus ? "집중" : "휴식";
            NotificationCenterService.Show("뽀모도로 타이머", $"{modeLabel} 시간이 종료되었습니다.", NotificationType.Info);
            return;
        }

        Remaining -= TimeSpan.FromSeconds(1);
        StateChanged?.Invoke(this, EventArgs.Empty);
    }

    // ─── 영속성 ──────────────────────────────────────────────────────────────

    private void SaveState()
    {
        try
        {
            Directory.CreateDirectory(Path.GetDirectoryName(StateFile)!);
            var dto = new PomodoroStateDto
            {
                Mode              = Mode.ToString(),
                IsRunning         = IsRunning,
                RemainingSeconds  = (int)Remaining.TotalSeconds,
                FocusMinutes      = FocusMinutes,
                BreakMinutes      = BreakMinutes,
                SavedAt           = DateTime.Now,
            };
            File.WriteAllText(StateFile, JsonSerializer.Serialize(dto));
        }
        catch { /* 무시 */ }
    }

    private void LoadState()
    {
        try
        {
            if (!File.Exists(StateFile)) goto defaults;
            var json = File.ReadAllText(StateFile);
            var dto  = JsonSerializer.Deserialize<PomodoroStateDto>(json);
            if (dto == null) goto defaults;

            FocusMinutes = dto.FocusMinutes > 0 ? dto.FocusMinutes : 25;
            BreakMinutes = dto.BreakMinutes > 0 ? dto.BreakMinutes : 5;
            Mode         = Enum.TryParse<PomodoroMode>(dto.Mode, out var m) ? m : PomodoroMode.Idle;
            IsRunning    = dto.IsRunning;

            // 앱이 꺼진 동안 경과 시간 보정
            var elapsed  = DateTime.Now - dto.SavedAt;
            var saved    = TimeSpan.FromSeconds(dto.RemainingSeconds);
            Remaining    = saved - elapsed;
            if (Remaining < TimeSpan.Zero) { Remaining = TimeSpan.Zero; IsRunning = false; }
            return;
        }
        catch { /* fall through */ }

    defaults:
        FocusMinutes = 25;
        BreakMinutes = 5;
        Mode         = PomodoroMode.Idle;
        IsRunning    = false;
        Remaining    = TimeSpan.FromMinutes(FocusMinutes);
    }

    private class PomodoroStateDto
    {
        [JsonPropertyName("mode")]             public string   Mode             { get; set; } = "Idle";
        [JsonPropertyName("isRunning")]        public bool     IsRunning        { get; set; }
        [JsonPropertyName("remainingSeconds")] public int      RemainingSeconds { get; set; }
        [JsonPropertyName("focusMinutes")]     public int      FocusMinutes     { get; set; } = 25;
        [JsonPropertyName("breakMinutes")]     public int      BreakMinutes     { get; set; } = 5;
        [JsonPropertyName("savedAt")]          public DateTime SavedAt          { get; set; } = DateTime.Now;
    }
}
