import 'dart:io';

import 'package:dio/dio.dart';

import '../../../core/network/api_response.dart';
import '../../../core/utils/device_fingerprint_service.dart';

/// 注册前 `/uc/check-account` 的语义结果（与 Web checkAccountForRegister 一致）：
/// 业务成功 code=0 表示可申请注册；占用由非 0 与异常文案体现；掩码「用户名或密码错误」放行可继续注册。
enum CheckAccountForRegisterResult {
  /// 账号已占用（如接口返回「已注册」等文案）
  alreadyRegistered,
  /// 可申请注册（成功或掩码「用户名或密码错误」）
  available,
}

/// 登录响应数据
class LoginResult {
  final String token;
  final String? uid;
  final String? email;

  const LoginResult({required this.token, this.uid, this.email});

  factory LoginResult.fromJson(Map<String, dynamic> json) {
    return LoginResult(
      token: json['token'] as String? ?? '',
      uid: json['id']?.toString(),
      email: json['email'] as String?,
    );
  }
}

/// 认证 API 服务（无状态，只封装 HTTP 调用）
///
/// 所有接口使用 form-urlencoded 格式提交
class AuthService {
  const AuthService(this._dio);

  final Dio _dio;

  /// form-urlencoded 请求选项
  static final _formOptions = Options(
    contentType: 'application/x-www-form-urlencoded',
  );

  /// 设备类型：1=iOS，2=Android，5=PC/其他
  static int get _deviceType {
    if (Platform.isIOS) return 1;
    if (Platform.isAndroid) return 2;
    return 5;
  }

  /// 与 Web 一致的掩码文案：账号不存在时接口不落真实原因
  static bool isRegisterAvailabilityMaskMessage(String message) {
    return message.contains('用户名或密码错误');
  }

  /// 与 Web `checkAccountForRegister` 一致：接口用业务异常文案表示「已占用」
  static bool isAccountAlreadyRegisteredHint(String message) {
    if (message.contains('已注册')) {
      return true;
    }
    if (message.contains('已存在')) {
      return true;
    }
    if (message.contains('已被使用')) {
      return true;
    }
    return RegExp(
      r'already\s+(exists|registered)',
      caseSensitive: false,
    ).hasMatch(message);
  }

  // ── 登录发码前校验密码（与 Web `/uc/check-password` 一致）────────

  Future<void> checkLoginPassword({
    required String username,
    required String password,
  }) async {
    await _dio.post<dynamic>(
      'uc/check-password',
      data: {'username': username.trim(), 'password': password},
      options: _formOptions,
    );
  }

  // ── 注册发码前校验账号是否已存在（与 Web `/uc/check-account` 一致）──

  Future<CheckAccountForRegisterResult> checkAccountForRegister(
    String username,
  ) async {
    try {
      await _dio.post<dynamic>(
        'uc/check-account',
        data: {'username': username.trim()},
        options: _formOptions,
      );
      return CheckAccountForRegisterResult.available;
    } on DioException catch (e) {
      final err = e.error;
      if (err is ApiException) {
        final msg = err.message;
        if (isAccountAlreadyRegisteredHint(msg)) {
          return CheckAccountForRegisterResult.alreadyRegistered;
        }
        if (isRegisterAvailabilityMaskMessage(msg)) {
          return CheckAccountForRegisterResult.available;
        }
      }
      rethrow;
    }
  }

  // ── 发送登录验证码 ──────────────────────────────────────

  Future<void> sendLoginEmailCode(String email) async {
    await _dio.post<dynamic>(
      'uc/login/email/code',
      data: {'username': email, 'email': email},
      options: _formOptions,
    );
  }

  // ── 密码+验证码登录 ──────────────────────────────────────

  /// [vtype] 验证类型：2=邮箱验证码，3=谷歌验证码
  Future<LoginResult> loginWithPassword({
    required String email,
    required String password,
    required String code,
    String vtype = '2',
  }) async {
    final deviceInfo = await DeviceFingerprintService.getDeviceInfo();
    final response = await _dio.post<Map<String, dynamic>>(
      'uc/login',
      data: {
        'username': email,
        'password': password,
        'country': '',
        'vtype': vtype,
        'vcode': code,
        'deviceType': _deviceType,
        'deviceFingerprint': deviceInfo.fingerprint,
        'deviceModel': deviceInfo.model,
        'osVersion': deviceInfo.osVersion,
      },
      options: _formOptions,
    );
    final data = (response.data?['data'] as Map<String, dynamic>?) ?? {};
    return LoginResult.fromJson(data);
  }

  // ── 发送注册验证码 ──────────────────────────────────────

  Future<void> sendRegisterEmailCode(String email) async {
    await _dio.post<dynamic>(
      'uc/reg/email/code',
      data: {'username': email, 'email': email},
      options: _formOptions,
    );
  }

  // ── 邮箱注册 ────────────────────────────────────────────

  Future<void> registerWithEmail({
    required String email,
    required String password,
    required String code,
    String? inviteCode,
    String country = '不丹',
  }) async {
    await _dio.post<Map<String, dynamic>>(
      'uc/register/email',
      data: {
        'email': email,
        'username': email,
        'password': password,
        'code': code,
        'country': country,
        'promotion': inviteCode ?? '',
        'deviceType': _deviceType,
      },
      options: _formOptions,
    );
  }

  // ── 发送重置密码验证码 ──────────────────────────────────

  Future<void> sendResetEmailCode(String email) async {
    await _dio.post<dynamic>(
      'uc/reset/email/code',
      data: {'username': email, 'account': email},
      options: _formOptions,
    );
  }

  // ── 重置密码 ────────────────────────────────────────────

  Future<void> resetPassword({
    required String email,
    required String password,
    required String code,
  }) async {
    await _dio.post<dynamic>(
      'uc/reset/login/password',
      data: {'email': email, 'password': password, 'code': code, 'account': email, 'mode': 1},
      options: _formOptions,
    );
  }

  // ── 退出登录 ────────────────────────────────────────────

  Future<void> logout() async {
    await _dio.post<dynamic>('uc/loginout');
  }

  // ── 获取用户信息 ────────────────────────────────────────

  Future<Map<String, dynamic>> getMyInfo() async {
    final response =
        await _dio.post<Map<String, dynamic>>('uc/member/my-info');
    return (response.data?['data'] as Map<String, dynamic>?) ?? {};
  }

  // ── 谷歌验证器绑定流程 ──────────────────────────────────

  /// 获取谷歌验证器秘钥
  /// 返回 { link: "otpauth://...", secret: "P12EB42NCCSE8VTX" }
  Future<Map<String, dynamic>> getGoogleSecret() async {
    final response = await _dio.get<Map<String, dynamic>>(
      'uc/google/sendgoogle',
    );
    return (response.data?['data'] as Map<String, dynamic>?) ?? {};
  }

  /// 发送谷歌验证器绑定的邮箱验证码
  Future<void> sendGoogleAuthEmailCode() async {
    await _dio.post<dynamic>(
      'uc/googleAuth/email/code',
      options: _formOptions,
    );
  }

  /// 绑定谷歌验证器
  /// [codes] Google Authenticator 6位动态码
  /// [vcode] 邮箱收到的6位验证码
  /// [secret] 第一步获取的密钥
  /// [vtype] 验证方式 "2"=邮箱
  Future<void> bindGoogleAuth({
    required String codes,
    required String vcode,
    required String secret,
    String vtype = '2',
  }) async {
    await _dio.post<dynamic>(
      'uc/google/googleAuthWithSms',
      data: {
        'codes': codes,
        'vtype': vtype,
        'vcode': vcode,
        'secret': secret,
      },
      options: _formOptions,
    );
  }

  // ── 资金密码 ──────────────────────────────────────────────

  /// 首次设置资金密码
  Future<void> setFundPassword(String password) async {
    await _dio.post<dynamic>(
      'uc/approve/transaction/password',
      data: {'jyPassword': password},
      options: _formOptions,
    );
  }

  /// 发送资金密码重置邮箱验证码
  Future<void> sendFundPasswordEmailCode() async {
    await _dio.post<dynamic>(
      'uc/transaction/email/code',
      options: _formOptions,
    );
  }

  /// 重置资金密码
  /// 发送修改登录密码邮箱验证码 — POST uc/updatePassword/email/code
  Future<void> sendChangePasswordEmailCode() async {
    await _dio.post<dynamic>(
      'uc/updatePassword/email/code',
      options: _formOptions,
    );
  }

  /// 修改登录密码 — POST uc/approve/update/password
  Future<void> changeLoginPassword({
    required String oldPassword,
    required String newPassword,
    required String vcode,
  }) async {
    await _dio.post<dynamic>(
      'uc/approve/update/password',
      data: {
        'oldPassword': oldPassword,
        'newPassword': newPassword,
        'vtype': '2',
        'vcode': vcode,
      },
      options: _formOptions,
    );
  }

  Future<void> resetFundPassword({
    required String newPassword,
    required String vcode,
    String vtype = '2',
  }) async {
    await _dio.post<dynamic>(
      'uc/approve/reset/transaction/password',
      data: {
        'newPassword': newPassword,
        'vtype': vtype,
        'vcode': vcode,
      },
      options: _formOptions,
    );
  }
}
