import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:flashlink/app/constants/api_domains.dart';
import 'package:flashlink/app/constants/keys.dart';
import 'package:flashlink/app/dialog/all_dialog.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:uuid/uuid.dart';

import '../../config/translations/strings_enum.dart';
import 'base_core_api.dart';
import '../../utils/boost_report_manager.dart';
import '../../utils/haptic_feedback_manager.dart';
import '../../utils/log/logger.dart';
import '../../utils/network_helper.dart';
import '../components/ix_snackbar.dart';
import '../constants/enums.dart';
import '../constants/errors.dart';
import '../data/models/api_exception.dart';
import '../data/models/failure.dart';
import '../data/models/vpn_message.dart';
import '../data/sp/ix_sp.dart';
import '../constants/sp_keys.dart';
import '../dialog/error_dialog.dart';
import 'api_controller.dart';

class CoreController extends GetxService {
  final TAG = 'CoreController';
  final _apiController = Get.find<ApiController>();
  final _state = ConnectionState.disconnected.obs;
  ConnectionState get state => _state.value;
  set state(ConnectionState value) => _state.value = value;

  // 公开状态流供外部监听
  Rx<ConnectionState> get stateStream => _state;

  final _timer = "00:00:00".obs;
  String get timer => _timer.value;
  set timer(String value) => _timer.value = value;

  // VPN 事件流订阅
  StreamSubscription<String>? _eventSubscription;

  CancelToken? _cancelToken;

  //全局uuid
  final _globalUuid = Uuid().v4();

  String locationSelectionType = 'auto';

  // 标记 VPN 逻辑是否已开启（调用了 BaseCoreApi().connect()）
  bool _isVpnStarted = false;

  // 标记是否有待处理的断开请求
  bool _pendingDisconnect = false;

  // 用于等待断开完成的 Completer
  Completer<void>? _disconnectCompleter;

  @override
  void onInit() {
    super.onInit();
    _initCheckConnect();
    _startListeningToEvents();
  }

  @override
  void onClose() {
    super.onClose();
    // 取消事件流订阅
    _eventSubscription?.cancel();
    _eventSubscription = null;
  }

  void _initCheckConnect() {
    BaseCoreApi().isConnected().then((value) {
      if (value == true) {
        state = ConnectionState.connected;
        _isVpnStarted = true;
      } else {
        state = ConnectionState.disconnected;
        _isVpnStarted = false;
      }
    });
  }

  void handleConnection() async {
    // 如果正在断开中，忽略操作
    if (state == ConnectionState.disconnecting) {
      log(TAG, '正在断开中，忽略操作');
      return;
    }

    if (state == ConnectionState.disconnected) {
      // 开始连接 - 轻微震动
      state = ConnectionState.connectingVirtual;
      _isVpnStarted = false;
      _pendingDisconnect = false;
      HapticFeedbackManager.connectionStart();
      getDispatchInfo();
    } else if (state == ConnectionState.connectingVirtual) {
      // 虚拟连接中点击断开
      if (_isVpnStarted) {
        // VPN 逻辑已开启，标记待断开，等待 _onVpnConnecting 返回后执行断开
        log(TAG, 'VPN 已启动，标记待断开');
        _pendingDisconnect = true;
      } else {
        // VPN 逻辑还没开启，取消请求并初始化状态
        log(TAG, 'VPN 未启动，取消请求并初始化状态');
        _cancelToken?.cancel('用户取消连接');
        _cancelToken = null;
        _uninitState();
      }
    } else if (state == ConnectionState.connecting) {
      // 真实连接中点击断开 - 执行断开逻辑
      log(TAG, '真实连接中，执行断开逻辑');
      await _performDisconnect();
    } else if (state == ConnectionState.connected) {
      // 已连接状态，执行断开逻辑
      await _performDisconnect();
    }
  }

  /// 执行断开逻辑，等待断开完成
  Future<void> _performDisconnect() async {
    // 如果已经在断开中，等待断开完成（带超时）
    if (_disconnectCompleter != null) {
      log(TAG, '已经在断开中，等待完成');
      try {
        await _disconnectCompleter!.future.timeout(
          const Duration(seconds: 10),
          onTimeout: () {
            log(TAG, '等待断开超时，强制清理');
            _forceCleanupDisconnect();
          },
        );
      } catch (e) {
        log(TAG, '等待断开异常: $e');
        _forceCleanupDisconnect();
      }
      return;
    }

    log(TAG, '开始执行断开逻辑, _isVpnStarted=$_isVpnStarted');

    // 如果 VPN 根本没启动，直接清理状态即可
    if (!_isVpnStarted) {
      log(TAG, 'VPN 未启动，直接清理状态');
      _uninitState();
      return;
    }

    state = ConnectionState.disconnecting;
    _disconnectCompleter = Completer<void>();

    try {
      BaseCoreApi().disconnect();
    } catch (e) {
      log(TAG, 'disconnect 调用异常: $e');
      _forceCleanupDisconnect();
      return;
    }

    // 等待断开完成（带超时）
    try {
      await _disconnectCompleter!.future.timeout(
        const Duration(seconds: 10),
        onTimeout: () {
          log(TAG, '断开超时，强制清理');
          _forceCleanupDisconnect();
        },
      );
    } catch (e) {
      log(TAG, '断开等待异常: $e');
      _forceCleanupDisconnect();
    }
  }

  /// 强制清理断开状态
  void _forceCleanupDisconnect() {
    if (_disconnectCompleter != null && !_disconnectCompleter!.isCompleted) {
      _disconnectCompleter!.complete();
    }
    _disconnectCompleter = null;
    _isVpnStarted = false;
    _pendingDisconnect = false;
    _uninitState();
  }

  void selectLocationConnect() async {
    if (state == ConnectionState.disconnecting) {
      log(TAG, '正在断开中，等待断开完成');
      if (_disconnectCompleter != null) {
        await _disconnectCompleter!.future;
      }
    }

    if (state != ConnectionState.disconnected) {
      await _performDisconnect();
      // 延迟300ms
      await Future.delayed(const Duration(milliseconds: 300));
      log(TAG, 'selectLocationConnect disconnected = $state');
      state = ConnectionState.connectingVirtual;
      _isVpnStarted = false;
      _pendingDisconnect = false;
      getDispatchInfo();
    } else {
      handleConnection();
    }
  }

  Future<void> getDispatchInfo() async {
    // 如果正在请求中，取消当前请求
    if (_cancelToken != null) {
      log(TAG, '取消当前请求，重新发起新请求');
      _cancelToken?.cancel('取消旧请求，发起新请求');
    }

    // 创建新的 CancelToken
    final currentToken = CancelToken();
    _cancelToken = currentToken;
    // 创建一条加速日志
    await createBoostLog();
    try {
      final locationId = IXSP.getSelectedLocation()?['id'];
      final locationCode = IXSP.getSelectedLocation()?['code'];
      final launch = await _apiController.getDispatchInfo(
        locationId,
        locationCode,
        cancelToken: currentToken,
      );

      // 只有当前 token 没有被替换时才清空
      if (_cancelToken == currentToken) {
        _cancelToken = null;
      }
      final remainTime = launch.userConfig?.remainTime ?? 0;

      if (remainTime <= 0) {
        _onVpnError(Errors.ERROR_REMAIN_TIME, Strings.remainTimeEnded.tr);
        return;
      }

      if (state == ConnectionState.connectingVirtual) {
        // 标记 VPN 逻辑已开启
        _isVpnStarted = true;

        final sessionId = Uuid().v4();
        final socksPort = launch.nodesConfig!.socketPort!;
        final tunnelConfig = launch.nodesConfig!.tunnelConfig!;
        final configJson = jsonEncode(launch.nodesConfig!);

        // 根据分流隧道设置获取 allowVpnApps 和 disallowVpnApps
        final splitTunnelingApps = _getSplitTunnelingApps();
        final allowVpnApps = splitTunnelingApps['allowVpnApps']!;
        final disallowVpnApps = splitTunnelingApps['disallowVpnApps']!;
        final accessToken = launch.userConfig?.accessToken ?? '';
        final peekTimeInterval = launch.appConfig?.peekTimeInterval ?? 600;
        final aesKey = Keys.aesKey;
        final aesIv = Keys.aesIv;
        final baseUrls = ApiDomains.instance.getAllLogUrls();
        final params = jsonEncode(_apiController.fp);
        BaseCoreApi().connect(
          sessionId,
          socksPort,
          tunnelConfig,
          configJson,
          remainTime,
          false,
          allowVpnApps,
          disallowVpnApps,
          accessToken,
          aesKey,
          aesIv,
          locationId,
          locationCode,
          baseUrls,
          params,
          peekTimeInterval,
        );
      }
    } on DioException catch (e, s) {
      // 只有当前 token 没有被替换时才清空
      if (_cancelToken == currentToken) {
        _cancelToken = null;
      }

      // 如果是取消错误，不处理
      if (e.type == DioExceptionType.cancel) {
        log(TAG, '请求已取消');
        return;
      }

      if (state == ConnectionState.connectingVirtual) {
        state = ConnectionState.disconnected;
      }
      handleErrorDialog(e, s);
      log(TAG, 'getDispatchInfo error: $e');
    } catch (e, s) {
      // 只有当前 token 没有被替换时才清空
      if (_cancelToken == currentToken) {
        _cancelToken = null;
      }

      if (state == ConnectionState.connectingVirtual) {
        state = ConnectionState.disconnected;
      }
      handleErrorDialog(e, s);
      log(TAG, 'getDispatchInfo error: $e');
    }
  }

  /// 根据分流隧道设置获取 allowVpnApps 和 disallowVpnApps
  /// 直接从 IXSP 读取，参考 SplittunnelingController 的逻辑
  Map<String, List<String>> _getSplitTunnelingApps() {
    List<String> allowVpnApps = [];
    List<String> disallowVpnApps = [];

    try {
      // 读取选中的模式
      final modeString = IXSP.getString(SPKeys.splittunnelingSelectedMode);
      if (modeString == null) {
        log(TAG, '分流隧道未设置模式');
        return {
          'allowVpnApps': allowVpnApps,
          'disallowVpnApps': disallowVpnApps,
        };
      }

      // 判断模式类型
      final isExcludeMode = modeString.contains('exclude');
      final isIncludeMode = modeString.contains('include');

      if (!isExcludeMode && !isIncludeMode) {
        log(TAG, '分流隧道模式为 none');
        return {
          'allowVpnApps': allowVpnApps,
          'disallowVpnApps': disallowVpnApps,
        };
      }

      // 根据模式获取对应的应用列表
      final key = isExcludeMode
          ? SPKeys.splittunnelingExcludeSelectedApps
          : SPKeys.splittunnelingIncludeSelectedApps;

      final selectedAppsJson = IXSP.getString(key);
      if (selectedAppsJson != null) {
        final selectedPackageNames =
            (jsonDecode(selectedAppsJson) as List<dynamic>).cast<String>();

        if (isIncludeMode) {
          // include 模式：只有选中的应用走 VPN
          allowVpnApps = selectedPackageNames;
          log(TAG, '分流隧道 include 模式，允许的应用: $allowVpnApps');
        } else {
          // exclude 模式：选中的应用不走 VPN
          disallowVpnApps = selectedPackageNames;
          log(TAG, '分流隧道 exclude 模式，排除的应用: $disallowVpnApps');
        }
      }
    } catch (e) {
      log(TAG, '获取分流隧道设置失败: $e');
    }

    return {'allowVpnApps': allowVpnApps, 'disallowVpnApps': disallowVpnApps};
  }

  /// 开始监听来自 Android 的事件
  void _startListeningToEvents() {
    _eventSubscription = onEventChange().listen(
      _handleEventChange,
      onError: (error) {
        log(TAG, '事件流错误: $error');
      },
    );
  }

  // 处理从原生端接收到的消息
  void _handleEventChange(String message) {
    try {
      final Map<String, dynamic> json = jsonDecode(message);
      final String type = json['type'] ?? '';

      switch (type) {
        case 'vpn_status':
          _handleVpnStatus(VpnStatusMessage.fromJson(json));
          break;
        case 'timer_update':
          _handleTimerUpdate(TimerUpdateMessage.fromJson(json));
          break;
        case 'boost_result':
          _handleBoostResult(BoostResultMessage.fromJson(json));
          break;
        default:
          log(TAG, '未知消息类型: $type');
      }
    } catch (e) {
      log(TAG, '解析消息失败: $e');
    }
  }

  void _handleVpnStatus(VpnStatusMessage message) {
    final vpnError = VpnStatus.fromValue(message.status);
    log(
      TAG,
      'VPN状态变化: ${vpnError.label}, status=${message.status}, code=${message.code}, message=${message.message}',
    );
    // 根据状态码处理不同的VPN状态
    switch (vpnError) {
      case VpnStatus.idle:
        // disconnected
        _onVpnDisconnected();
        break;
      case VpnStatus.connecting:
        // connecting
        _onVpnConnecting();
        break;
      case VpnStatus.connected:
        // connected
        _onVpnConnected();
        break;
      case VpnStatus.error:
        // error
        _onVpnError(message.code, message.message);
        break;
    }
  }

  void _handleTimerUpdate(TimerUpdateMessage message) {
    //log(TAG, '计时更新: time=${message.currentTime}, mode=${message.mode}');
    timer = _formatTime(message.currentTime);
  }

  void _handleBoostResult(BoostResultMessage message) async {
    log(
      TAG,
      '加速结果: locationCode=${message.locationCode}, nodeId=${message.nodeId}, success=${message.success}',
    );
    if (message.success) {
      try {
        await _apiController.connected({
          'locationCode': message.locationCode,
          'instanceId': message.nodeId,
        });
      } catch (e) {
        log('handleRouterConnected error: $e');
      }
    }

    try {
      final json = jsonDecode(message.param);
      await _apiController.uploadLogs(json);
    } catch (e) {
      log('handleBoostResult error: $e');
    }
  }

  // VPN状态处理方法
  void _onVpnDisconnected() {
    log(TAG, 'VPN已断开连接');

    // 完成断开 Completer
    if (_disconnectCompleter != null && !_disconnectCompleter!.isCompleted) {
      _disconnectCompleter!.complete();
    }
    _disconnectCompleter = null;

    // 重置标志位
    _isVpnStarted = false;
    _pendingDisconnect = false;

    // 更新UI状态
    _uninitState();

    // 上传 Boost 日志（不阻塞）
    _apiController.uploadBoostLog();

    // FeedbackBottomSheet.show();
  }

  void _onVpnConnecting() {
    log(TAG, 'VPN正在连接');

    // 检查是否有待处理的断开请求
    if (_pendingDisconnect) {
      log(TAG, '检测到待处理的断开请求，执行断开');
      _pendingDisconnect = false;
      _performDisconnect();
      return;
    }

    // 显示连接中状态
    state = ConnectionState.connecting;
  }

  void _onVpnConnected() {
    log(TAG, 'VPN已连接');
    // 显示已连接状态
    state = ConnectionState.connected;
    HapticFeedbackManager.connectionSuccess();
  }

  void _onVpnError(int code, String message) {
    log(TAG, 'VPN连接错误: code=$code, message=$message');

    // 完成断开 Completer（如果有）
    if (_disconnectCompleter != null && !_disconnectCompleter!.isCompleted) {
      _disconnectCompleter!.complete();
    }
    _disconnectCompleter = null;

    // 重置标志位
    _isVpnStarted = false;
    _pendingDisconnect = false;

    // 显示错误信息
    _uninitState();
    showErrorDialog(code, message);

    // 上传 Boost 日志（不阻塞）
    _apiController.uploadBoostLog();
  }

  void showErrorDialog(int code, String message) {
    var errorMessage = message;
    switch (code) {
      case Errors.ERROR_NODE_TIMEOUT:
        errorMessage = Strings.vpnConnectionTimeoutError.tr;
        break;
      case Errors.ERROR_NO_NODE:
        errorMessage = Strings.vpnNoNodeError.tr;
        break;
      case Errors.ERROR_INIT:
        errorMessage = Strings.vpnInitError.tr;
        break;
      case Errors.ERROR_KILL:
        errorMessage = Strings.vpnKillError.tr;
        break;
      case Errors.ERROR_REVOKE:
        errorMessage = Strings.vpnRevokeError.tr;
        break;
      case Errors.ERROR_SERVICE_EMPTY:
        errorMessage = Strings.vpnServiceEmptyError.tr;
        break;
      case Errors.ERROR_ROUTER:
        errorMessage = Strings.vpnRouterError.tr;
        break;
      case Errors.ERROR_PERMISSION_DENIED:
        errorMessage = Strings.vpnPermissionDeniedError.tr;
        break;
      case Errors.ERROR_REMAIN_TIME:
        errorMessage = Strings.remainTimeEnded.tr;
        break;
      // 桌面版本错误
      case Errors.ERROR_RPC_CALL_FAILED:
        errorMessage = Strings.vpnRPCCallFailed.tr;
        break;
      case Errors.ERROR_RPC_RETURN_FALSE:
        errorMessage = Strings.vpnRPCReturnFalse.tr;
        break;
    }
    if (code == Errors.ERROR_REMAIN_TIME) {
      AllDialog.showMembershipExpired();
      return;
    }
    if (errorMessage.isNotEmpty) {
      ErrorDialog.show(message: errorMessage);
    }
  }

  void _uninitState() {
    if (state != ConnectionState.disconnected) {
      state = ConnectionState.disconnected;
      timer = "00:00:00";
      HapticFeedbackManager.connectionDisconnected();
    }
  }

  // 格式化时间显示
  String _formatTime(int timeMs) {
    final totalSeconds = (timeMs / 1000).abs().round();
    final hours = totalSeconds ~/ 3600;
    final minutes = (totalSeconds % 3600) ~/ 60;
    final seconds = totalSeconds % 60;

    return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
  }

  void handleSnackBarError(dynamic error, StackTrace stackTrace) {
    if (error is ApiException) {
      IXSnackBar.showIXErrorSnackBar(
        title: Strings.error.tr,
        message: error.message,
      );
    } else if (error is Failure) {
      IXSnackBar.showIXErrorSnackBar(
        title: Strings.error.tr,
        message: error.message ?? Strings.unknownError.tr,
      );
    } else if (error is DioException) {
      switch (error.type) {
        case DioExceptionType.connectionError:
        case DioExceptionType.connectionTimeout:
        case DioExceptionType.receiveTimeout:
        case DioExceptionType.sendTimeout:
          IXSnackBar.showIXErrorSnackBar(
            title: Strings.error.tr,
            message: Strings.unableToConnectNetwork.tr,
          );
          break;
        default:
          IXSnackBar.showIXErrorSnackBar(
            title: Strings.error.tr,
            message: Strings.unableToConnectServer.tr,
          );
      }
    } else {
      IXSnackBar.showIXErrorSnackBar(
        title: Strings.error.tr,
        message: error.toString(),
      );
    }
  }

  void handleErrorDialog(dynamic error, StackTrace stackTrace) {
    if (error is ApiException) {
      ErrorDialog.show(title: Strings.error.tr, message: error.message);
    } else if (error is Failure) {
      ErrorDialog.show(
        title: Strings.error.tr,
        message: error.message ?? Strings.unknownError.tr,
      );
    } else if (error is DioException) {
      switch (error.type) {
        case DioExceptionType.connectionError:
        case DioExceptionType.connectionTimeout:
        case DioExceptionType.receiveTimeout:
        case DioExceptionType.sendTimeout:
          ErrorDialog.show(
            title: Strings.error.tr,
            message: Strings.unableToConnectNetwork.tr,
          );
          break;
        default:
          ErrorDialog.show(
            title: Strings.error.tr,
            message: Strings.unableToConnectServer.tr,
          );
      }
    } else {
      ErrorDialog.show(title: Strings.error.tr, message: error.toString());
    }
  }

  // 创建一条加速日志
  Future<void> createBoostLog() async {
    await initLog();
    await setSessionInfoLog();
    await setTargetInfoLog();
  }

  // 初始化日志
  Future<void> initLog() async {
    await BoostReportManager().init();
  }

  // 读取历史日志
  Future<void> readHistoryLog() async {
    await BoostReportManager().readHistoryLog();
  }

  // 初始化会话日志
  Future<void> setSessionInfoLog() async {
    final deviceInfoPlugin = DeviceInfoPlugin();
    final appVersion = await PackageInfo.fromPlatform().then(
      (value) => value.version,
    );
    final networkType = await NetworkHelper.instance.getNetworkType();
    Map<String, String> deviceInfo = {};
    if (Platform.isIOS) {
      final iosOsInfo = await deviceInfoPlugin.iosInfo;
      deviceInfo = {
        'deviceModel': iosOsInfo.model,
        'osVersion': iosOsInfo.systemVersion,
        'appVersion': appVersion,
        'networkType': networkType,
        'deviceBrand': iosOsInfo.utsname.machine,
      };
    } else if (Platform.isAndroid) {
      final androidOsInfo = await deviceInfoPlugin.androidInfo;
      deviceInfo = {
        'deviceModel': androidOsInfo.model,
        'osVersion': androidOsInfo.version.release,
        'appVersion': appVersion,
        'networkType': networkType,
        'deviceBrand': androidOsInfo.brand,
      };
    }
    final boostSessionId = Uuid().v4();
    await BoostReportManager().initSessionInfo(
      appSessionId: _globalUuid,
      boostSessionId: boostSessionId,
      deviceInfo: deviceInfo,
    );
  }

  // 初始化目标信息
  Future<void> setTargetInfoLog() async {
    await BoostReportManager().addTargetInfo(
      locationSelectionType: locationSelectionType,
      location: IXSP.getSelectedLocation(),
    );
  }
}
