// connection_provider.dart — 连接状态机(严格三态,禁止乐观显示)
//
// 设计约定(design/CLAUDE.md §2/§5):连接键三态严格对应状态层事件,
// UI 只渲染本通知器的真实状态,绝不在点击时本地乐观翻转。连接握手由
// 状态层(此处为 mock 计时器,后续替换为隧道事件)决定何时进入 on。
import 'dart:async';

import 'package:flutter_riverpod/flutter_riverpod.dart';

/// 连接阶段。严格三态——与 React 原型一致。
enum VpnPhase { off, connecting, on }

/// 连接状态快照。
class ConnectionState {
  const ConnectionState({required this.phase, this.elapsed = Duration.zero});

  final VpnPhase phase;
  final Duration elapsed;

  ConnectionState copyWith({VpnPhase? phase, Duration? elapsed}) =>
      ConnectionState(phase: phase ?? this.phase, elapsed: elapsed ?? this.elapsed);

  @override
  bool operator ==(Object other) =>
      other is ConnectionState && other.phase == phase && other.elapsed == elapsed;

  @override
  int get hashCode => Object.hash(phase, elapsed);
}

/// 连接状态机。握手时长可注入,便于测试确定化。
class ConnectionController extends StateNotifier<ConnectionState> {
  ConnectionController({this.handshake = const Duration(milliseconds: 1500)})
      : super(const ConnectionState(phase: VpnPhase.off));

  final Duration handshake;
  Timer? _handshakeTimer;
  Timer? _tick;

  /// 用户轻点连接键:仅依据真实状态决定动作,握手中点击被忽略(禁乐观)。
  void toggle() {
    switch (state.phase) {
      case VpnPhase.off:
        connect();
      case VpnPhase.on:
        disconnect();
      case VpnPhase.connecting:
        break; // 握手进行中,不响应——避免乐观回退
    }
  }

  void connect() {
    _cancelTimers();
    state = const ConnectionState(phase: VpnPhase.connecting);
    _handshakeTimer = Timer(handshake, _onConnected);
  }

  void disconnect() {
    _cancelTimers();
    state = const ConnectionState(phase: VpnPhase.off);
  }

  /// 切换节点时触发:已连接则重连(短暂回到 connecting)。
  void onNodeChanged() {
    if (state.phase == VpnPhase.on || state.phase == VpnPhase.connecting) {
      connect();
    }
  }

  void _onConnected() {
    state = const ConnectionState(phase: VpnPhase.on);
    _tick = Timer.periodic(const Duration(seconds: 1), (_) {
      state = state.copyWith(elapsed: state.elapsed + const Duration(seconds: 1));
    });
  }

  void _cancelTimers() {
    _handshakeTimer?.cancel();
    _handshakeTimer = null;
    _tick?.cancel();
    _tick = null;
  }

  @override
  void dispose() {
    _cancelTimers();
    super.dispose();
  }
}

final connectionProvider =
    StateNotifierProvider<ConnectionController, ConnectionState>(
  (ref) => ConnectionController(),
);
