import 'dart:convert';

import 'dart:async';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/common/app_config.dart';

import 'package:kaer_with_panels/app/model/enum/kr_request_type.dart';
import 'package:kaer_with_panels/app/modules/kr_main/controllers/kr_main_controller.dart';
import 'package:kaer_with_panels/app/services/kr_socket_service.dart';
import 'package:kaer_with_panels/app/utils/kr_secure_storage.dart';
import 'package:kaer_with_panels/app/utils/kr_device_util.dart';

import 'package:kaer_with_panels/app/utils/kr_log_util.dart';

import '../services/api_service/kr_api.user.dart';
import '../utils/kr_event_bus.dart';

class KRAppRunData {
  static final KRAppRunData _instance = KRAppRunData._internal();

  static const String _keyUserInfo = 'USER_INFO';

  /// 登录token
  String? kr_token;

  /// 用户账号
  String? kr_account;

  /// 用户ID
  String? kr_userId;

  /// 登录类型
  KRLoginType? kr_loginType;

  /// 区号
  String? kr_areaCode;

  // 需要被监听的属性，用 obs 包装
  final kr_isLogin = false.obs;

  KRAppRunData._internal();

  factory KRAppRunData() => _instance;

  static KRAppRunData getInstance() {
    return _instance;
  }

  /// 保存用户信息
  Future<void> kr_saveUserInfo(
      String token, String account, KRLoginType loginType, String? areaCode) async {
    KRLogUtil.kr_i('开始保存用户信息', tag: 'AppRunData');
    
    try {
      // 更新内存中的数据
      kr_token = token;
      kr_account = account;
      kr_loginType = loginType;
      kr_areaCode = areaCode;
      
      final Map<String, dynamic> userInfo = {
        'token': token,
        'account': account,
        'loginType': loginType.value,
        'areaCode': areaCode ?? "",
      };
      
      KRLogUtil.kr_i('准备保存用户信息到存储', tag: 'AppRunData');
      
      await KRSecureStorage().kr_saveData(
        key: _keyUserInfo,
        value: jsonEncode(userInfo),
      );

      // 验证保存是否成功
      final savedData = await KRSecureStorage().kr_readData(key: _keyUserInfo);
      if (savedData == null || savedData.isEmpty) {
        KRLogUtil.kr_e('数据保存后无法读取，保存失败', tag: 'AppRunData');
        kr_isLogin.value = false;
        return;
      }

      KRLogUtil.kr_i('用户信息保存成功，设置登录状态为true', tag: 'AppRunData');
      
      // 只有在保存成功后才设置登录状态
      kr_isLogin.value = true;

      // 异步获取用户信息并建立 Socket 连接，不等待结果
      _iniUserInfo().catchError((error) {
        KRLogUtil.kr_e('获取用户信息失败: $error', tag: 'AppRunData');
        // 即使获取用户信息失败，也保持登录状态
      });
      
    } catch (e) {
      KRLogUtil.kr_e('保存用户信息失败: $e', tag: 'AppRunData');
      // 如果出错，重置登录状态
      kr_isLogin.value = false;
      rethrow; // 重新抛出异常，让调用者知道保存失败
    }
  }

  /// 退出登录
  Future<void> kr_loginOut() async {
    // 先将登录状态设置为 false，防止重连
    kr_isLogin.value = false;
    
    // 断开 Socket 连接
    await _kr_disconnectSocket();
    
    // 清理用户信息
    kr_token = null;
    kr_account = null;
    kr_userId = null;
    kr_loginType = null;
    kr_areaCode = null;

    // 删除存储的用户信息
    await KRSecureStorage().kr_deleteData(key: _keyUserInfo);

    // 重置主页面
    Get.find<KRMainController>().kr_setPage(0);
  }

  /// 初始化用户信息
  Future<void> kr_initializeUserInfo() async {
    KRLogUtil.kr_i('开始初始化用户信息', tag: 'AppRunData');
    
    try {
      final String? userInfoString =
          await KRSecureStorage().kr_readData(key: _keyUserInfo);

      if (userInfoString != null && userInfoString.isNotEmpty) {
        KRLogUtil.kr_i('找到存储的用户信息，开始解析', tag: 'AppRunData');
        
        try {
          final Map<String, dynamic> userInfo = jsonDecode(userInfoString);
          kr_token = userInfo['token'];
          kr_account = userInfo['account'];
          final loginTypeValue = userInfo['loginType'];
          kr_loginType = KRLoginType.values.firstWhere(
            (e) => e.value == loginTypeValue,
            orElse: () => KRLoginType.kr_telephone,
          );
          kr_areaCode = userInfo['areaCode'] ?? "";

          KRLogUtil.kr_i('解析用户信息成功: token=${kr_token != null}, account=$kr_account', tag: 'AppRunData');

          // 验证token有效性
          if (kr_token != null && kr_token!.isNotEmpty) {
            KRLogUtil.kr_i('设置登录状态为true', tag: 'AppRunData');
            kr_isLogin.value = true;
            
            // 异步获取用户信息，但不等待结果
            _iniUserInfo().catchError((error) {
              KRLogUtil.kr_e('获取用户信息失败: $error', tag: 'AppRunData');
              // 如果获取用户信息失败，不重置登录状态，让用户重试
            });
          } else {
            KRLogUtil.kr_w('Token为空，设置为未登录状态', tag: 'AppRunData');
            kr_isLogin.value = false;
          }
        } catch (e) {
          KRLogUtil.kr_e('解析用户信息失败: $e', tag: 'AppRunData');
          await kr_loginOut();
        }
      } else {
        KRLogUtil.kr_i('未找到存储的用户信息，设置为未登录状态', tag: 'AppRunData');
        kr_isLogin.value = false;
      }
    } catch (e) {
      KRLogUtil.kr_e('初始化用户信息过程出错: $e', tag: 'AppRunData');
      kr_isLogin.value = false;
    }
    
    KRLogUtil.kr_i('用户信息初始化完成，登录状态: ${kr_isLogin.value}', tag: 'AppRunData');
  }

  /// 初始化用户信息并建立 Socket 连接
  Future<void> _iniUserInfo() async {
    final either0 = await KRUserApi().kr_getUserInfo();
    either0.fold(
      (error) {
        KRLogUtil.kr_e(error.msg, tag: 'AppRunData');
      },
      (userInfo) async {
        kr_userId = userInfo.id.toString();
         _kr_connectSocket(kr_userId!);
      },
    );
  }

  /// 建立 Socket 连接
  Future<void> _kr_connectSocket(String userId) async {
    // 如果已存在连接，先断开
    await _kr_disconnectSocket();
    
    final deviceId = await KRDeviceUtil().kr_getDeviceId();
    KRLogUtil.kr_i('设备ID: $deviceId', tag: 'AppRunData');
    KrSocketService.instance.kr_init(
      baseUrl: AppConfig.getInstance().wsBaseUrl,
      userId: userId,
      deviceNumber: deviceId,
      token: kr_token ?? "",
    );

    // 设置消息处理回调
    KrSocketService.instance.setOnMessageCallback(_kr_handleMessage);
    // 设置连接状态回调
    KrSocketService.instance.setOnConnectionStateCallback(_kr_handleConnectionState);
    
    // 建立连接
    KrSocketService.instance.connect();
  }

  /// 处理接收到的消息
  void _kr_handleMessage(Map<String, dynamic> message) {
    try {
      final String method = message['method'] as String;
      switch (method) {
        case 'kicked_device':
          KRLogUtil.kr_i('超出登录设备限制', tag: 'AppRunData');
          kr_loginOut();
          break;
        case 'kicked_admin':
          KRLogUtil.kr_i('强制退出', tag: 'AppRunData');
          kr_loginOut();
          break;
        case 'subscribe_update':
          KRLogUtil.kr_i('订阅信息已更新', tag: 'AppRunData');
          // 发送订阅更新事件
          KREventBus().kr_sendMessage(KRMessageType.kr_subscribe_update);
          break;
        default:
          KRLogUtil.kr_w('收到未知类型的消息: $message', tag: 'AppRunData');
      }
    } catch (e) {
      KRLogUtil.kr_e('处理消息失败: $e', tag: 'AppRunData');
    }
  }

  /// 处理连接状态变化
  void _kr_handleConnectionState(bool isConnected) {
    KRLogUtil.kr_i('WebSocket 连接状态: ${isConnected ? "已连接" : "已断开"}', tag: 'AppRunData');
  }

  /// 断开 Socket 连接
  Future<void> _kr_disconnectSocket() async {
    await KrSocketService.instance.disconnect();
  }
}
