import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../data/datasources/remote/auth_remote_datasource.dart';
import '../../data/models/capability_model.dart';
import '../../core/di/injection.dart';
import '../../core/telemetry/telemetry_service.dart';

class UserState {
  final String? accountSequence;
  final String? nickname;
  final String? phone;
  final String? kycStatus;
  final String? source;
  final String? status;
  final String? realName;
  final DateTime? createdAt;
  final DateTime? lastLoginAt;
  final String? accessToken;
  final String? refreshToken;
  final int avatarIndex;
  final bool isLoggedIn;
  final bool isLoading;
  final String? error;

  UserState({
    this.accountSequence,
    this.nickname,
    this.phone,
    this.kycStatus,
    this.source,
    this.status,
    this.realName,
    this.createdAt,
    this.lastLoginAt,
    this.accessToken,
    this.refreshToken,
    this.avatarIndex = 0,
    this.isLoggedIn = false,
    this.isLoading = false,
    this.error,
  });

  bool get isKycVerified => kycStatus == 'VERIFIED';

  UserState copyWith({
    String? accountSequence,
    String? nickname,
    String? phone,
    String? kycStatus,
    String? source,
    String? status,
    String? realName,
    DateTime? createdAt,
    DateTime? lastLoginAt,
    String? accessToken,
    String? refreshToken,
    int? avatarIndex,
    bool? isLoggedIn,
    bool? isLoading,
    String? error,
  }) {
    return UserState(
      accountSequence: accountSequence ?? this.accountSequence,
      nickname: nickname ?? this.nickname,
      phone: phone ?? this.phone,
      kycStatus: kycStatus ?? this.kycStatus,
      source: source ?? this.source,
      status: status ?? this.status,
      realName: realName ?? this.realName,
      createdAt: createdAt ?? this.createdAt,
      lastLoginAt: lastLoginAt ?? this.lastLoginAt,
      accessToken: accessToken ?? this.accessToken,
      refreshToken: refreshToken ?? this.refreshToken,
      avatarIndex: avatarIndex ?? this.avatarIndex,
      isLoggedIn: isLoggedIn ?? this.isLoggedIn,
      isLoading: isLoading ?? this.isLoading,
      error: error,
    );
  }
}

class UserNotifier extends StateNotifier<UserState> {
  final AuthRemoteDataSource _authDataSource;

  UserNotifier(this._authDataSource) : super(UserState()) {
    _loadFromStorage();
  }

  Future<void> _loadFromStorage() async {
    final prefs = await SharedPreferences.getInstance();
    final accessToken = prefs.getString('access_token');
    final refreshToken = prefs.getString('refresh_token');
    final accountSequence = prefs.getString('account_sequence');
    final phone = prefs.getString('phone');
    final avatarIndex = prefs.getInt('avatar_index') ?? 0;
    final nickname = prefs.getString('nickname');

    if (accessToken != null && refreshToken != null && accountSequence != null) {
      state = state.copyWith(
        accessToken: accessToken,
        refreshToken: refreshToken,
        accountSequence: accountSequence,
        phone: phone,
        avatarIndex: avatarIndex,
        nickname: nickname,
        isLoggedIn: true,
      );
      // 登录后自动获取用户详情
      await fetchProfile();
    }
  }

  Future<void> _saveToStorage(AuthResult result) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString('access_token', result.accessToken);
    await prefs.setString('refresh_token', result.refreshToken);
    await prefs.setString('account_sequence', result.user.accountSequence);
    await prefs.setString('phone', result.user.phone);
  }

  Future<void> _clearStorage() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove('access_token');
    await prefs.remove('refresh_token');
    await prefs.remove('account_sequence');
    await prefs.remove('phone');
    await prefs.remove('avatar_index');
    await prefs.remove('nickname');
  }

  Future<void> sendSmsCode(String phone, String type) async {
    state = state.copyWith(isLoading: true, error: null);
    try {
      await _authDataSource.sendSmsCode(phone, type);
      state = state.copyWith(isLoading: false);
    } catch (e) {
      state = state.copyWith(isLoading: false, error: e.toString());
      rethrow;
    }
  }

  Future<void> register(String phone, String password, String smsCode) async {
    state = state.copyWith(isLoading: true, error: null);
    try {
      final result = await _authDataSource.register(phone, password, smsCode);
      await _saveToStorage(result);
      state = state.copyWith(
        accessToken: result.accessToken,
        refreshToken: result.refreshToken,
        accountSequence: result.user.accountSequence,
        phone: result.user.phone,
        kycStatus: result.user.kycStatus,
        source: result.user.source,
        isLoggedIn: true,
        isLoading: false,
      );
    } catch (e) {
      state = state.copyWith(isLoading: false, error: e.toString());
      rethrow;
    }
  }

  Future<void> loginWithPassword(String phone, String password) async {
    state = state.copyWith(isLoading: true, error: null);
    try {
      final result = await _authDataSource.loginWithPassword(phone, password);
      await _saveToStorage(result);
      state = state.copyWith(
        accessToken: result.accessToken,
        refreshToken: result.refreshToken,
        accountSequence: result.user.accountSequence,
        phone: result.user.phone,
        kycStatus: result.user.kycStatus,
        source: result.user.source,
        isLoggedIn: true,
        isLoading: false,
      );
      TelemetryService().setUserId(result.user.accountSequence);
      TelemetryService().setAccessToken(result.accessToken);
      TelemetryService().resumeAfterLogin();
      TelemetryService().logUserAction('login_success', properties: {'method': 'password'});
      // 登录后获取详细信息
      await fetchProfile();
    } catch (e) {
      TelemetryService().logUserAction('login_failed', properties: {'method': 'password', 'error': e.toString()});
      state = state.copyWith(isLoading: false, error: e.toString());
      rethrow;
    }
  }

  Future<void> loginWithSms(String phone, String smsCode) async {
    state = state.copyWith(isLoading: true, error: null);
    try {
      final result = await _authDataSource.loginWithSms(phone, smsCode);
      await _saveToStorage(result);
      state = state.copyWith(
        accessToken: result.accessToken,
        refreshToken: result.refreshToken,
        accountSequence: result.user.accountSequence,
        phone: result.user.phone,
        kycStatus: result.user.kycStatus,
        source: result.user.source,
        isLoggedIn: true,
        isLoading: false,
      );
      TelemetryService().setUserId(result.user.accountSequence);
      TelemetryService().setAccessToken(result.accessToken);
      TelemetryService().resumeAfterLogin();
      TelemetryService().logUserAction('login_success', properties: {'method': 'sms'});
      // 登录后获取详细信息
      await fetchProfile();
    } catch (e) {
      TelemetryService().logUserAction('login_failed', properties: {'method': 'sms', 'error': e.toString()});
      state = state.copyWith(isLoading: false, error: e.toString());
      rethrow;
    }
  }

  Future<void> logout() async {
    if (state.refreshToken != null) {
      try {
        await _authDataSource.logout(state.refreshToken!);
      } catch (_) {}
    }
    TelemetryService().logUserAction('logout');
    await TelemetryService().pauseForLogout();
    TelemetryService().setAccessToken(null);
    await _clearStorage();
    state = UserState();
  }

  Future<void> refreshTokenIfNeeded() async {
    if (state.refreshToken == null) {
      throw Exception('No refresh token available');
    }
    try {
      final newAccessToken = await _authDataSource.refreshToken(state.refreshToken!);
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString('access_token', newAccessToken);
      state = state.copyWith(accessToken: newAccessToken);
      TelemetryService().setAccessToken(newAccessToken);
    } catch (e) {
      // 清除本地存储，不调用远程logout API（可能网络不可用）
      await _clearStorage();
      state = UserState();
      rethrow;
    }
  }

  Future<void> resetPassword(String phone, String smsCode, String newPassword) async {
    state = state.copyWith(isLoading: true, error: null);
    try {
      await _authDataSource.resetPassword(phone, smsCode, newPassword);
      state = state.copyWith(isLoading: false);
    } catch (e) {
      state = state.copyWith(isLoading: false, error: e.toString());
      rethrow;
    }
  }

  Future<void> changePassword(String oldPassword, String newPassword) async {
    state = state.copyWith(isLoading: true, error: null);
    try {
      await _authDataSource.changePassword(oldPassword, newPassword);
      state = state.copyWith(isLoading: false);
    } catch (e) {
      state = state.copyWith(isLoading: false, error: e.toString());
      rethrow;
    }
  }

  /// 获取用户详细信息
  Future<void> fetchProfile() async {
    if (!state.isLoggedIn) return;
    try {
      final profile = await _authDataSource.getProfile();
      state = state.copyWith(
        phone: profile.phone,
        kycStatus: profile.kycStatus,
        source: profile.source,
        status: profile.status,
        realName: profile.realName,
        createdAt: profile.createdAt,
        lastLoginAt: profile.lastLoginAt,
      );
    } catch (e) {
      // 静默失败，不影响用户体验
    }
  }

  /// 更新头像索引（本地存储）
  Future<void> updateAvatar(int avatarIndex) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setInt('avatar_index', avatarIndex);
    state = state.copyWith(avatarIndex: avatarIndex);
  }

  /// 更新昵称（本地存储）
  Future<void> updateNickname(String nickname) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString('nickname', nickname);
    state = state.copyWith(nickname: nickname);
  }

  /// 获取支付密码状态
  Future<bool> getTradePasswordStatus() async {
    try {
      return await _authDataSource.getTradePasswordStatus();
    } catch (e) {
      return false;
    }
  }

  /// 设置支付密码
  Future<void> setTradePassword(String loginPassword, String tradePassword) async {
    state = state.copyWith(isLoading: true, error: null);
    try {
      await _authDataSource.setTradePassword(loginPassword, tradePassword);
      state = state.copyWith(isLoading: false);
    } catch (e) {
      state = state.copyWith(isLoading: false, error: e.toString());
      rethrow;
    }
  }

  /// 修改支付密码
  Future<void> changeTradePassword(String oldTradePassword, String newTradePassword) async {
    state = state.copyWith(isLoading: true, error: null);
    try {
      await _authDataSource.changeTradePassword(oldTradePassword, newTradePassword);
      state = state.copyWith(isLoading: false);
    } catch (e) {
      state = state.copyWith(isLoading: false, error: e.toString());
      rethrow;
    }
  }

  /// 验证支付密码
  Future<bool> verifyTradePassword(String tradePassword) async {
    try {
      return await _authDataSource.verifyTradePassword(tradePassword);
    } catch (e) {
      return false;
    }
  }
}

final userNotifierProvider = StateNotifierProvider<UserNotifier, UserState>(
  (ref) => UserNotifier(getIt<AuthRemoteDataSource>()),
);

final currentAccountSequenceProvider = Provider<String?>((ref) {
  return ref.watch(userNotifierProvider).accountSequence;
});

final isLoggedInProvider = Provider<bool>((ref) {
  return ref.watch(userNotifierProvider).isLoggedIn;
});

final accessTokenProvider = Provider<String?>((ref) {
  return ref.watch(userNotifierProvider).accessToken;
});

/// 支付密码状态 Provider
final tradePasswordStatusProvider = FutureProvider<bool>((ref) async {
  final userNotifier = ref.read(userNotifierProvider.notifier);
  return userNotifier.getTradePasswordStatus();
});

/// 用户能力权限 Provider
/// 登录后获取，用于 UI 层判断功能是否可用
final capabilitiesProvider = FutureProvider<CapabilityMap>((ref) async {
  final isLoggedIn = ref.watch(isLoggedInProvider);
  if (!isLoggedIn) return CapabilityMap.defaultAll();

  try {
    final authDataSource = getIt<AuthRemoteDataSource>();
    return await authDataSource.getCapabilities();
  } catch (_) {
    // fail-open: 获取失败时默认全部开启
    return CapabilityMap.defaultAll();
  }
});
