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

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

/// 登录用例
///
/// 封装登录的完整业务流程：
/// 格式校验 → 调 Repository 登录 → 初始化 WebSocket → 打开本地数据库 → 返回 User
///
/// ## 为什么需要 UseCase？
///
/// ViewModel 直接调 Repository 也能跑通，但登录有明确的多步业务规则：
/// - 格式校验（不发无效请求，省流量、减少服务端压力）
/// - 登录后初始化 WebSocket 连接
/// - 登录后按 user id 打开对应的本地数据库
///
/// 把这些规则封装在 UseCase 里，ViewModel 只需一行调用。
///
/// ## 数据流位置
///
/// ```
/// LoginViewModel.login(email, password)
///   → ★ LoginUseCase.execute() ★            ← 你在这里
///     → 格式校验（邮箱 + 密码）
///     → AuthRepository.login()
///       → AuthRepositoryImpl.login()
///         → _client.executeRequest(LoginRequest)
///       ← LoginData（DTO）
///       → _onTokenUpdate(token)               ← 回调写入 Token（内存 + 持久化，由 Provider 层组合）
///       ← LoginData.toEntity() → User
///     → SocketManager.connect(token)           ← 登录后连接 WebSocket
///     → StorageSdkApi.openDatabase(user.id)    ← 按用户 id 打开本地库
///   ← 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]
  /// 2. 调 Repository 登录 → 拿到 User（token 写入由 Repository 处理）
  /// 3. 用已存入 ApiConfig 的 token 连接 WebSocket
  /// 4. 按 user id 打开本地数据库
  ///
  /// 抛出：
  /// - [FormatException] — 邮箱或密码格式不合法
  /// - [ApiError] — 网络/服务端错误（由 Repository 透传）
  Future<User> execute({
    required String email,
    required String password,
  }) async {
    // ── 1. 格式校验 ──
    _validateEmail(email);
    _validatePassword(password);

    // ── 2. 登录 ──
    final user = await _authRepository.login(
      email: email,
      password: password,
    );

    // ── 3. 连接 WebSocket ──
    // token 在 Repository 的 _onTokenUpdate 回调中已写入 ApiConfig，
    // 此处直接读取，避免改动现有接口。
    final token = _apiConfig.token;
    if (token != null && token.isNotEmpty) {
      await _socketManager.connect(token: token);
    }

    // ── 4. 打开数据库 ──
    // TODO: 当服务端返回整型 uid 时，换成 user.uid；目前用 hashCode 作为临时标识。
    await _storageLifeCycle.openDatabase(user.hashCode);

    // TODO: 后续扩展点
    // - 同步联系人列表
    // - 注册推送 token

    return user;
  }

  void _validateEmail(String email) {
    if (email.trim().isEmpty) {
      throw const FormatException('邮箱不能为空'); // TODO: 接入国际化
    }
    final emailRegex = RegExp(r'^[^@\s]+@[^@\s]+\.[^@\s]+$');
    if (!emailRegex.hasMatch(email.trim())) {
      throw const FormatException('邮箱格式不正确'); // TODO: 接入国际化
    }
  }

  void _validatePassword(String password) {
    if (password.isEmpty) {
      throw const FormatException('密码不能为空'); // TODO: 接入国际化
    }
    if (password.length < 6) {
      throw const FormatException('密码长度不能少于 6 位'); // TODO: 接入国际化
    }
  }
}
