import 'package:networks_sdk/networks_sdk.dart';
import 'package:storage_sdk/storage_sdk.dart';

import 'package:im_app/core/services/socket_manager.dart';
import 'package:im_app/domain/entities/user.dart';
import 'package:im_app/domain/repositories/auth_repository.dart';

/// 登录用例
///
/// 封装登录的完整业务流程：
/// - sendOtp：格式校验 → 发短信
/// - verifyAndLogin：格式校验 → 校验验证码 → 登录 → 初始化 WebSocket → 打开本地数据库
///
/// ## 为什么需要 UseCase？
///
/// 登录有明确的多步业务规则，UseCase 把这些规则集中封装，
/// ViewModel 只需一行调用。
///
/// ## 数据流位置
///
/// ```
/// LoginViewModel.sendOtp(countryCode, contact)
///   → ★ LoginUseCase.sendOtp() ★          ← 你在这里（步骤 1）
///     → 格式校验（手机号）
///     → AuthRepository.sendOtp()
///
/// LoginViewModel.verifyAndLogin(code)
///   → ★ LoginUseCase.verifyAndLogin() ★   ← 你在这里（步骤 2+3）
///     → 格式校验（验证码）
///     → AuthRepository.verifyOtp()        → vcode_token
///     → AuthRepository.login()            → User + token
///     → SocketManager.connect(token)
///     → StorageSdkApi.openDatabase(uid)
///   ← User
/// ```
class LoginUseCase {
  final AuthRepository _authRepository;
  final SocketManager _socketManager;
  final ApiConfig _apiConfig;
  final StorageSdkApi _storageApi;

  StorageSdkLifecycle get _storageLifeCycle =>
      _storageApi as StorageSdkLifecycle;

  LoginUseCase({
    required AuthRepository authRepository,
    required SocketManager socketManager,
    required ApiConfig apiConfig,
    required StorageSdkApi storageApi,
  }) : _authRepository = authRepository,
       _socketManager = socketManager,
       _apiConfig = apiConfig,
       _storageApi = storageApi;

  /// 步骤 1：发送手机验证码
  ///
  /// 抛出：
  /// - [FormatException] — 手机号格式不合法
  /// - [ApiError] — 网络/服务端错误
  Future<void> sendOtp({
    required String countryCode,
    required String contact,
  }) async {
    _validatePhone(contact);
    await _authRepository.sendOtp(
      countryCode: countryCode,
      contact: contact,
    );
  }

  /// 步骤 2+3：校验验证码并完成登录，返回 [User]
  ///
  /// 内部串行：verifyOtp → login → connectWebSocket → openDatabase
  ///
  /// 抛出：
  /// - [FormatException] — 验证码格式不合法
  /// - [ApiError] — 网络/服务端错误
  Future<User> verifyAndLogin({
    required String countryCode,
    required String contact,
    required String code,
  }) async {
    _validateCode(code);

    // 校验验证码，换取 vcode_token
    final vcodeToken = await _authRepository.verifyOtp(
      countryCode: countryCode,
      contact: contact,
      code: code,
    );

    // 用 vcode_token 登录（token 写入由 Repository._onTokenUpdate 回调处理）
    final user = await _authRepository.login(
      countryCode: countryCode,
      contact: contact,
      vcodeToken: vcodeToken,
    );

    // 连接 WebSocket（token 已由 Repository 写入 ApiConfig，直接读取）
    final token = _apiConfig.token;
    if (token != null && token.isNotEmpty) {
      await _socketManager.connect(token: token);
    }

    // 按用户 uid 打开本地数据库
    await _storageLifeCycle.openDatabase(user.uid);

    // TODO: 扩展点 — 同步联系人列表、注册推送 token

    return user;
  }

  void _validatePhone(String contact) {
    final trimmed = contact.trim();
    if (trimmed.isEmpty) {
      throw const FormatException('手机号不能为空'); // TODO: 接入国际化
    }
    if (trimmed.length < 7 || trimmed.length > 15) {
      throw const FormatException('手机号长度不正确'); // TODO: 接入国际化
    }
    if (!RegExp(r'^\d+$').hasMatch(trimmed)) {
      throw const FormatException('手机号只能包含数字'); // TODO: 接入国际化
    }
  }

  void _validateCode(String code) {
    final trimmed = code.trim();
    if (trimmed.isEmpty) {
      throw const FormatException('验证码不能为空'); // TODO: 接入国际化
    }
    if (!RegExp(r'^\d+$').hasMatch(trimmed)) {
      throw const FormatException('验证码只能包含数字'); // TODO: l10n
    }
  }
}
