// nodes_provider.dart — 节点清单 + 当前选择 + 实测延迟
//
// 从 GET /v1/nodes 拉取真实节点(含 host/port);拉取后后台对各节点做 TCP 握手
// 实测 per-client 延迟并回填。未登录 / 失败返回空列表(不再伪造演示节点)。
import 'dart:async';
import 'dart:convert';

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;

import '../models/node.dart';
import '../services/api_config.dart';
import '../services/latency_probe.dart';
import 'auth_provider.dart';

// ── 节点列表 AsyncNotifier ────────────────────────────────────────

class NodesNotifier extends AsyncNotifier<List<Node>> {
  bool _disposed = false;

  @override
  Future<List<Node>> build() async {
    ref.onDispose(() => _disposed = true);
    final auth = ref.watch(authProvider);
    if (!auth.isLoggedIn) return const [];
    final list = await _fetchNodes(auth.accessToken!);
    unawaited(_measure(list));
    return list;
  }

  Future<void> refresh() async {
    final auth = ref.read(authProvider);
    if (!auth.isLoggedIn) {
      state = const AsyncData([]);
      return;
    }
    state = const AsyncLoading();
    state = await AsyncValue.guard(() async {
      final list = await _fetchNodes(auth.accessToken!);
      unawaited(_measure(list));
      return list;
    });
  }

  /// 后台实测各节点延迟,完成后回填(notifier 未销毁才更新)。
  Future<void> _measure(List<Node> list) async {
    if (list.isEmpty) return;
    final pings = await probeAll(
      [for (final n in list) (uuid: n.uuid, host: n.host, port: n.port)],
    );
    if (_disposed) return;
    final updated = [for (final n in list) n.copyWith(ping: pings[n.uuid] ?? n.ping)];
    state = AsyncData(updated);
  }

  static Future<List<Node>> _fetchNodes(String accessToken) async {
    final uri = Uri.parse('$kApiBaseUrl/v1/nodes');
    final resp = await http.get(uri, headers: {
      'Authorization': 'Bearer $accessToken',
    }).timeout(const Duration(seconds: 10));

    if (resp.statusCode != 200) return const [];

    final body = jsonDecode(resp.body) as Map<String, dynamic>;
    final rawList = body['nodes'] as List<dynamic>? ?? [];
    return rawList.map((e) {
      final m = e as Map<String, dynamic>;
      return Node(
        uuid: m['id'] as String? ?? '',
        code: m['region'] as String? ?? '??',
        nameZh: m['name_zh'] as String? ?? '',
        nameEn: m['name_en'] as String? ?? '',
        tier: m['tier'] as String? ?? 'free',
        host: m['host'] as String? ?? '',
        port: (m['port'] as num?)?.toInt() ?? 0,
        ping: 0, // 由 _measure 实测回填
      );
    }).toList();
  }
}

final nodesProvider =
    AsyncNotifierProvider<NodesNotifier, List<Node>>(NodesNotifier.new);

// ── 当前选中的节点 code；'AUTO' 表示智能选择(默认)─────────────────

final selectedNodeCodeProvider = StateProvider<String>((ref) => kSmartNodeCode);

/// 是否处于智能选择。
final isSmartSelectProvider = Provider<bool>(
  (ref) => ref.watch(selectedNodeCodeProvider) == kSmartNodeCode,
);

/// 实际生效的节点:列表为空时返回占位;智能选择取实测延迟最小者(未测得排后)。
final effectiveNodeProvider = Provider<Node>((ref) {
  final nodes = ref.watch(nodesProvider).valueOrNull ?? const <Node>[];
  if (nodes.isEmpty) return kPlaceholderNode;

  final code = ref.watch(selectedNodeCodeProvider);
  if (code == kSmartNodeCode) {
    return nodes.reduce((a, b) {
      final pa = a.ping > 0 ? a.ping : 1 << 30;
      final pb = b.ping > 0 ? b.ping : 1 << 30;
      return pa <= pb ? a : b;
    });
  }
  return nodes.firstWhere((n) => n.code == code, orElse: () => nodes.first);
});
