import 'dart:async';

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

import '../../core/foundation/api_paths.dart';
import '../../core/foundation/config.dart';
import '../../core/foundation/constants.dart';
import '../../core/services/network_monitor.dart';
import '../../core/services/socket_manager.dart';

// ── 网络状态监听 ──────────────────────────────────────────────────────────────

/// 网络状态监听 Provider（全局单例）
///
/// 基于 connectivity_plus 监听平台网络变化，
/// 作为公共服务供多个模块使用：
/// - SocketManager：网络变化时自动断连/重连 WebSocket
/// - HTTP 层：请求前检查网络可用性
/// - UI 层：显示网络状态提示
///
/// ## 使用
///
/// ```dart
/// // 查询当前状态
/// final isConnected = ref.read(networkMonitorProvider).isConnected;
///
/// // 监听状态变化
/// ref.listen(networkMonitorProvider, (prev, monitor) {
///   monitor.onStatusChanged.listen((isAvailable) {
///     // 处理网络变化
///   });
/// });
/// ```
final networkMonitorProvider = Provider<NetworkMonitor>((ref) {
  final monitor = NetworkMonitor(
    onLog: (message, {tag}) {
      // ignore: avoid_print
      print('[${tag ?? 'Network'}] $message');
    },
  );

  ref.onDispose(() {
    monitor.dispose();
  });

  return monitor;
});

// ── HTTP 基础设施 ─────────────────────────────────────────────────────────────

/// API 配置 Provider（全局单例）
///
/// 从 [AppConfig.apiBaseUrl]（config.json → --dart-define-from-file）读取 baseURL，
/// 注入到 Network SDK 作为所有 HTTP 请求的基础 URL。
///
/// [onCheckNetworkAvailable] 由 [networkMonitorProvider]（公共服务）注入，
/// 请求前先判断网络状态，无网络时直接抛 [ApiError.noNetworkConnection]。
final apiConfigProvider = Provider<ApiConfig>((ref) {
  final networkMonitor = ref.read(networkMonitorProvider);

  return ApiConfig(
    baseURL: AppConfig.apiBaseUrl,
    platformHeaders: {
      'Platform': 'Android', // TODO: 运行时从平台 API 获取
      'client-version': '1.0.0', // TODO: 运行时从 package_info 获取
    },
    tokenExpiredCodes: {30002, 30003, 30124},
    forceLogoutCodes: {30125},
    onForceLogout: () {
      // TODO: 清除登录态，跳转登录页
    },
    onTokenRefresh: () async {
      // TODO: App 层刷新 token 逻辑
      return null;
    },
    onCheckNetworkAvailable: () async => networkMonitor.isConnected,
    maxRetries: AppConstants.maxRetries,
    retryBaseDelay: AppConstants.retryBaseDelay,
    onLog: (message, {tag}) {
      // ignore: avoid_print
      print('[${tag ?? 'Network'}] $message');
    },
  );
});

/// API 客户端 Provider（全局单例）
///
/// 含拦截器（Auth / Retry / Logging）、超时配置。
final networkSdkApiProvider = Provider<NetworksSdkApi>((ref) {
  final config = ref.read(apiConfigProvider);
  return NetworksSdkApi()..initialize(config);
});

// ── WebSocket 基础设施 ────────────────────────────────────────────────────────

/// SocketConfig Provider（全局单例）
///
/// 与 apiConfigProvider 对称，通过回调注入 App 层能力，
/// SDK 内部不调用其他 SDK。
final socketConfigProvider = Provider<SocketConfig>((ref) {
  final networkMonitor = ref.read(networkMonitorProvider);

  return SocketConfig(
    maxReconnectAttempts: AppConstants.maxRetries,
    maxReconnectDelay: AppConstants.maxReconnectDelay,
    onLog: (message, {tag}) {
      // ignore: avoid_print
      print('[${tag ?? 'Socket'}] $message');
    },
    onCheckNetworkAvailable: () async {
      return networkMonitor.isConnected;
    },
  );
});

/// SocketClient Provider（全局单例）
///
/// 与 apiClientProvider 对称。
final socketClientProvider = Provider<NetworksMessagingApi>((ref)
{
  final config = ref.read(socketConfigProvider);
  return NetworksMessagingApi()..initialize(config);
});

/// SocketManager Provider
///
/// 封装连接生命周期、网络/前后台事件响应、操作前置检查、消息预处理。
/// 业务模块通过此 Provider 访问 WebSocket 能力。
///
/// ## 前置检查
///
/// connect / send 前先检查网络可用性 + 后台状态，
/// 无效操作直接跳过，避免无意义的网络请求。
/// 与 HTTP 层 [ApiClient.executeRequest] 的网络前置检查对称。
///
/// ## 事件驱动
///
/// 网络状态变化由 [networkMonitorProvider]（公共服务）驱动，
/// 自动触发断连/重连。
///
/// onMessageTransform 参考 HTTP 层 onTokenRefresh 的回调模式：
/// 后续接入加解密 SDK 时，在此注入解密回调，
/// SDK 内部不调用其他 SDK。
final socketManagerProvider = Provider<SocketManager>((ref) {
  final client = ref.read(socketClientProvider);
  final networkMonitor = ref.read(networkMonitorProvider);

  final manager = SocketManager(
    client: client,
    wsUrl: _buildWsUrl(AppConfig.apiBaseUrl),
    onMessageTransform: null, // TODO: 接入加解密 SDK 后注入解密回调
    onCheckNetworkAvailable: () async => networkMonitor.isConnected,
    onLog: (message, {tag}) {
      // ignore: avoid_print
      print('[${tag ?? 'SocketManager'}] $message');
    },
  );

  // 监听网络状态变化 → 驱动 SocketManager 断连/重连
  final subscription = networkMonitor.onStatusChanged.listen((isAvailable) {
    manager.handleNetworkStatusChanged(isAvailable: isAvailable);
  });

  ref.onDispose(() {
    subscription.cancel();
    unawaited(manager.dispose());
  });

  return manager;
});

// ── 辅助 ──────────────────────────────────────────────────────────────────────

/// HTTP baseURL → WebSocket URL 转换
///
/// https://api.example.com → wss://api.example.com/ws
/// http://api.example.com  → ws://api.example.com/ws
String _buildWsUrl(String httpBaseUrl) {
  String base = httpBaseUrl;
  if (base.startsWith('https://')) {
    base = base.replaceFirst('https://', 'wss://');
  } else if (base.startsWith('http://')) {
    base = base.replaceFirst('http://', 'ws://');
  }
  return '$base${ApiPaths.wsConnect}';
}

// ══════════════════════════════════════════════════════════════════════════════
//  本文件的职责
// ══════════════════════════════════════════════════════════════════════════════
//
//  提供所有网络基础设施 Provider：网络监听 + HTTP + WebSocket。
//  业务模块的 DI 链路（Repository → UseCase 按需）
//  内聚在 features/{模块}/di/{模块}_providers.dart 中。
//
//  di/ 目录只放「需要手动装配的 Provider」（构造注入、回调组合等）。
//  ViewModel Provider 由 @riverpod 注解自动生成，不在 di/ 中。
//
//  ┌──────────────────────────────────────────────────────────────────────────┐
//  │                         DI 架构                                         │
//  ├──────────────────────────────────────────────────────────────────────────┤
//  │  app/di/                         ← 手动装配：SDK 基础设施               │
//  │  ├── app_providers.dart     → 主题 + 启动初始化                         │
//  │  └── network_provider.dart  → 网络监听 + HTTP + WebSocket              │
//  │                                                                         │
//  │  features/{模块}/di/             ← 手动装配：业务模块 DI 链路           │
//  │  └── auth_providers.dart    → Repository → UseCase（按需）              │
//  │      chat_providers.dart       每个模块 DI 链路内聚在一个文件           │
//  │                                                                         │
//  │  features/{模块}/presentation/   ← @riverpod 自动生成：ViewModel        │
//  │  └── login_view_model.dart  → loginViewModelProvider（代码生成）        │
//  └──────────────────────────────────────────────────────────────────────────┘
//
//  Provider 链路：
//
//    networkMonitorProvider（公共服务，HTTP + WS 共用）
//      ├── apiConfigProvider → apiClientProvider         ← HTTP 层
//      └── socketConfigProvider → socketClientProvider   ← WS 层
//            → socketManagerProvider
//
//  网络事件驱动链路：
//
//    connectivity_plus（平台网络事件）
//      → NetworkMonitor.onStatusChanged（true / false）
//        → SocketManager.handleNetworkStatusChanged()
//          → 断网: disconnect()
//          → 恢复: connect(token: lastToken)
//
//  前后台事件驱动链路：
//
//    WidgetsBindingObserver（App 层 app.dart）
//      → SocketManager.onEnterBackground() → disconnect
//      → SocketManager.onEnterForeground() → reconnect
//
//  Repository 直接注入 ApiClient，通过回调注入其他 SDK 能力：
//
//    onTokenUpdate: (token) {
//      apiConfig.updateToken(token);       // 内存（network_sdk）
//      secureStorage.saveToken(token);     // 持久化（crypto_sdk）
//    }
//
//  这样 network_sdk 和 crypto_sdk 互不依赖，App 层是唯一知道两者的地方。
//
// ══════════════════════════════════════════════════════════════════════════════
//  新增接口的完整流程（以登录为例）
// ══════════════════════════════════════════════════════════════════════════════
//
//  「一个接口 = 一个 Request 文件」，严格按层调用，禁止跳层。
//
//  ┌──────────────────────────────────────────────────────────────────────────┐
//  │                         文件 & 职责总览                                  │
//  ├──────────────────────────────────────────────────────────────────────────┤
//  │  login_request.dart        Request + Response DTO（一个端点一个文件）     │
//  │  auth_repository_impl.dart executeRequest → DTO → Entity + 回调写 Token│
//  │  login_usecase.dart        格式校验 → 调 Repository（按需，非必须）      │
//  │  auth_providers.dart       DI 装配（Repository → UseCase 按需）          │
//  │  login_view_model.dart     ref.read(authRepositoryProvider).login()     │
//  │                            或 ref.read(loginUseCaseProvider).execute()  │
//  │  login_page.dart           ref.watch(loginViewModelProvider)            │
//  └──────────────────────────────────────────────────────────────────────────┘
//
// ─────────────────────────────────────────────────────────────────────────
// Step 1: 定义 Request（data/remote/login_request.dart）
// ─────────────────────────────────────────────────────────────────────────
//
//   一个文件包含两部分：Response DTO + Request 类。
//
//   @JsonSerializable()
//   class LoginData {                               // Response DTO
//     final String token;
//     final String userId;
//     factory LoginData.fromJson(Map<String, dynamic> json) => _$LoginDataFromJson(json);
//     User toEntity() => User(id: userId, ...);     // DTO → Domain Entity
//   }
//
//   @ApiRequest(path: ApiPaths.authLogin, method: HttpMethod.post,
//       responseType: LoginData, requestType: ApiRequestType.login)
//   @JsonSerializable()
//   class LoginRequest extends ApiRequestable<LoginData> with _$LoginRequestApi {
//     final String email;
//     final String password;
//     LoginRequest({required this.email, required this.password});
//     @override Map<String, dynamic> toJson() => _$LoginRequestToJson(this);
//   }
//
//   build_runner 生成 _$LoginRequestApi mixin → 自动提供 path / method / fromJson 注册。
//
// ─────────────────────────────────────────────────────────────────────────
// Step 2: Repository（data/repositories/auth_repository_impl.dart）
// ─────────────────────────────────────────────────────────────────────────
//
//   class AuthRepositoryImpl implements AuthRepository {
//     final ApiClient _client;                        // ← 直接注入 ApiClient
//     final void Function(String?) _onTokenUpdate;    // ← 回调，由 Provider 层组合
//
//     Future<User> login({required String email, required String password}) async {
//       final dto = await _client.executeRequest(
//         LoginRequest(email: email, password: password),
//       );
//       _onTokenUpdate(dto!.token);                   // 回调写入 Token
//       return dto.toEntity();                        // DTO → Domain Entity
//     }
//   }
//
// ─────────────────────────────────────────────────────────────────────────
// Step 3: Provider 装配 + ViewModel
// ─────────────────────────────────────────────────────────────────────────
//
//   // --- Provider 装配（features/auth/di/auth_providers.dart） ---
//
//   // Repository（直接注入 ApiClient + 回调组合多个 SDK 能力）
//   final authRepositoryProvider = Provider((ref) {
//     final apiConfig = ref.read(apiConfigProvider);
//     return AuthRepositoryImpl(
//       client: ref.read(apiClientProvider),       // 直接注入
//       onTokenUpdate: (token) {
//         apiConfig.updateToken(token);             // 内存（network_sdk）
//         // secureStorage.saveToken(token);        // 持久化（crypto_sdk）
//       },
//     );
//   });
//
//   // UseCase（按需 — 登录有多步编排，所以需要）
//   final loginUseCaseProvider = Provider((ref) {
//     return LoginUseCase(authRepository: ref.read(authRepositoryProvider));
//   });
//
//   // --- ViewModel（features/auth/presentation/login_view_model.dart） ---
//
//   // 常规写法：ViewModel 直接调 Repository
//   @riverpod
//   class LoginViewModel extends _$LoginViewModel {
//     Future<void> login(String email, String password) async {
//       state = state.copyWith(isLoading: true);
//       try {
//         final user = await ref.read(authRepositoryProvider).login(
//           email: email, password: password,
//         );
//         state = state.copyWith(user: user, isLoading: false);
//       } on ApiError catch (e) {
//         state = state.copyWith(error: e.displayMessage, isLoading: false);
//       }
//     }
//   }
//
//   // 进阶写法：有 UseCase 时（格式校验 + 多步编排）
//   // final user = await ref.read(loginUseCaseProvider).execute(
//   //   email: email, password: password,
//   // );
//
// ═════════════════════════════════════════════════════════════════════════
//  内部执行链路（点击登录按钮后发生了什么）
// ═════════════════════════════════════════════════════════════════════════
//
//   View: vm.login(email, password)
//     → ViewModel: ref.read(authRepositoryProvider).login(...)    ← 常规路径
//     → ViewModel: ref.read(loginUseCaseProvider).execute(...)    ← 进阶路径（有 UseCase 时）
//       → UseCase: 格式校验（邮箱 + 密码）
//       → UseCase/ViewModel: authRepository.login(...)
//         → Repository: _client.executeRequest(LoginRequest(...))
//           → ApiClient.executeRequest(request)
//               1. 拼 URL: baseURL + "/auth/login"
//               2. request.parameters 触发 fromJson 自动注册
//               3. AuthInterceptor: 注入 token + platform headers
//               4. Dio.request(url, data: {email, password})
//               5. RetryInterceptor: token 过期 → 刷新 → 自动重试
//               6. LoggingInterceptor: 打印请求/响应日志
//             → request.decodeResponse(response)
//               1. ApiResponseWrapper.fromJson: 拆 { code, message, data }
//               2. 检查 code != 0 → 抛 ApiError
//               3. fromJsonRegistry[LoginData] → LoginData.fromJson(data)
//             → 返回 LoginData（DTO）
//         → _onTokenUpdate(token)  回调写入 Token（Provider 层组合：内存 + 持久化）
//         → LoginData.toEntity() → User（Domain Entity）
//     → state.copyWith(user: user)  更新状态
//   View: ref.watch → 自动 rebuild UI
//
// ═════════════════════════════════════════════════════════════════════════
//  各 HTTP 方法速查 — 新增接口时参照
// ═════════════════════════════════════════════════════════════════════════
//
//  GET（参数走 URL query string）
//    @ApiRequest(path: ..., method: HttpMethod.get, responseType: ProfileData)
//    class GetProfileRequest extends ApiRequestable<ProfileData> with _$... { }
//
//  POST（参数走 JSON body）
//    见上方 LoginRequest 示例。
//
//  DELETE / PUT / PATCH（与 POST 相同，只改 method）
//    @ApiRequest(path: ..., method: HttpMethod.delete, responseType: ...)
//
//  POST 无响应数据（如 logout）
//    class LogoutRequest extends ApiRequestable<void> { ... }
//    // → 返回 null
//
//  Upload A: FormData 上传到自有后端
//    @override Object? get uploadData => FormData.fromMap({ 'file': ... });
//
//  Upload B: 二进制上传到 S3 presigned URL
//    @override String get path => presignedURL;    // 完整 URL，不拼 baseURL
//    @override Object? get uploadData => bytes;    // Uint8List
//    @override decodeResponse(response) { ... }    // S3 不走标准信封
//
