import 'package:dio/dio.dart';

import '../config.dart';

/// 公司账号登录接口返回的数据
class AuthResult {
  final String userID;
  final String token;
  final String nickname;

  AuthResult({required this.userID, required this.token, required this.nickname});

  factory AuthResult.fromJson(Map<String, dynamic> json) => AuthResult(
        userID: json['userID']?.toString() ?? '',
        token: json['imToken']?.toString() ?? '',
        nickname: json['nickname']?.toString() ?? '',
      );
}

/// 登录失败，message 直接给用户看（简体中文）
class AuthException implements Exception {
  final String message;
  AuthException(this.message);

  @override
  String toString() => message;
}

/// 公司账号登录 HTTP 客户端。
///
/// 接口契约（account-service，见仓库 account-service/README.md）：
/// - POST {authApiBase}/api/login
///   body: {"staffNo": "工号", "password": "...", "platformID": 1 iOS / 2 Android}
///   响应统一包络 {"code": 0, "msg": "", "data": {...}}，失败也是 HTTP 200 + code != 0
///   成功 data: {"userID", "nickname", "imToken", "expireTimeSeconds"}（userID/imToken 直接用于 OpenIM SDK 登录）
/// - POST {authApiBase}/api/rtc_token（语音通话换 LiveKit 进房 token）
///   请求头: Authorization: Bearer {imToken}
///   body: {"room": "房间号", "identity": "当前用户 userID"}
///   成功 data: {"token": "LiveKit 访问 token"}
class AuthApi {
  final Dio _dio = Dio(BaseOptions(
    baseUrl: authApiBase,
    connectTimeout: const Duration(seconds: 10),
    receiveTimeout: const Duration(seconds: 10),
  ));

  /// 拆统一响应包络：code == 0 返回 data，否则用 msg 抛 [AuthException]
  Map<String, dynamic> _unwrap(dynamic body) {
    if (body is Map<String, dynamic>) {
      if (body['code'] == 0 && body['data'] is Map<String, dynamic>) {
        return Map<String, dynamic>.from(body['data'] as Map);
      }
      final msg = body['msg']?.toString();
      throw AuthException((msg != null && msg.isNotEmpty) ? msg : '服务器返回的数据不对，请联系管理员');
    }
    throw AuthException('服务器返回的数据不对，请联系管理员');
  }

  /// 工号 + 密码登录，成功后返回 OpenIM 登录所需的 userID/imToken
  Future<AuthResult> login({required String staffNo, required String password, required int platformID}) async {
    try {
      final resp = await _dio.post('/api/login', data: {
        'staffNo': staffNo,
        'password': password,
        'platformID': platformID,
      });
      final result = AuthResult.fromJson(_unwrap(resp.data));
      if (result.userID.isNotEmpty && result.token.isNotEmpty) return result;
      throw AuthException('服务器返回的数据不对，请联系管理员');
    } on DioException catch (e) {
      // 401 等 HTTP 层失败也带 {code, msg} 包络
      final data = e.response?.data;
      if (data is Map && data['msg'] != null && data['msg'].toString().isNotEmpty) {
        throw AuthException(data['msg'].toString());
      }
      throw AuthException('连不上服务器，请检查网络');
    } catch (e) {
      if (e is AuthException) rethrow;
      throw AuthException('登录出错了，请稍后再试');
    }
  }

  /// 获取 LiveKit 房间 token（语音通话用）。authToken 即登录返回的 imToken。
  Future<LiveKitCredential> getRtcToken({required String room, required String identity, required String authToken}) async {
    try {
      final resp = await _dio.post(
        '/api/rtc_token',
        data: {'room': room, 'identity': identity},
        options: Options(headers: {'Authorization': 'Bearer $authToken'}),
      );
      final data = _unwrap(resp.data);
      final token = data['token']?.toString();
      if (token != null && token.isNotEmpty) {
        final live = data['liveURL']?.toString();
        return LiveKitCredential(
          token: token,
          liveURL: live != null && live.isNotEmpty ? live : livekitUrl,
        );
      }
      throw AuthException('服务器返回的数据不对，请联系管理员');
    } on DioException catch (e) {
      final data = e.response?.data;
      if (data is Map && data['msg'] != null && data['msg'].toString().isNotEmpty) {
        throw AuthException(data['msg'].toString());
      }
      throw AuthException('连不上服务器，请检查网络');
    } catch (e) {
      if (e is AuthException) rethrow;
      throw AuthException('发起通话失败，请稍后再试');
    }
  }
}

/// LiveKit 进房凭证
class LiveKitCredential {
  final String token;
  final String liveURL;

  LiveKitCredential({required this.token, required this.liveURL});
}
