import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:dio/dio.dart';
import '../core/api_client.dart';
import '../core/local_database.dart';

/// 用户简要信息
class UserInfo {
  final String id;
  final String phone;
  final String? name;
  final String? avatarUrl;

  UserInfo({required this.id, required this.phone, this.name, this.avatarUrl});
}

/// 认证状态
class AuthState {
  final UserInfo? user;
  final bool isLoggedIn;
  final bool isLoading;

  const AuthState({this.user, this.isLoggedIn = false, this.isLoading = true});
}

/// 认证 Provider
final authProvider = NotifierProvider<AuthNotifier, AuthState>(AuthNotifier.new);

final localDbProvider = Provider<LocalDatabase>((ref) => LocalDatabase.instance);

final apiClientProvider = Provider<ApiClient>((ref) {
  return ApiClient(db: ref.watch(localDbProvider));
});

class AuthNotifier extends Notifier<AuthState> {
  @override
  AuthState build() {
    _checkAuth();
    return const AuthState(isLoading: true);
  }

  Future<void> _checkAuth() async {
    final db = ref.read(localDbProvider);
    final refresh = await db.read('refresh_token');
    if (refresh == null) {
      state = const AuthState(isLoggedIn: false, isLoading: false);
      return;
    }

    try {
      final response = await Dio(BaseOptions(baseUrl: baseUrl))
          .post('/api/auth/refresh', data: {'refreshToken': refresh});
      final data = response.data['data'];
      if (data != null) {
        await db.write('access_token', data['accessToken']);
        await db.write('refresh_token', data['refreshToken']);
        state = AuthState(
          isLoggedIn: true,
          isLoading: false,
          user: UserInfo(id: '', phone: '', name: data['user']?['name']),
        );
        _loadProfile();
      } else {
        state = const AuthState(isLoggedIn: false, isLoading: false);
      }
    } catch (_) {
      state = const AuthState(isLoggedIn: false, isLoading: false);
    }
  }

  Future<void> _loadProfile() async {
    try {
      final api = ref.read(apiClientProvider);
      final response = await api.get('/api/user/profile');
      final user = response.data['data'];
      if (user != null) {
        state = AuthState(
          isLoggedIn: true,
          isLoading: false,
          user: UserInfo(
            id: user['id'] ?? '',
            phone: user['phone'] ?? '',
            name: user['name'],
            avatarUrl: user['avatarUrl'],
          ),
        );
      }
    } catch (_) {}
  }

  /// 发送验证码，返回 (error, devCode)
  Future<({String? error, String? devCode})> sendSms(String phone) async {
    try {
      final api = ref.read(apiClientProvider);
      final response = await api.post('/api/auth/send-sms', data: {'phone': phone});
      final devCode = response.data['data']?['devCode'] as String?;
      return (error: null, devCode: devCode);
    } catch (e) {
      return (error: '发送失败: $e', devCode: null);
    }
  }

  /// 验证码登录
  Future<String?> login(String phone, String code) async {
    try {
      final api = ref.read(apiClientProvider);
      final response = await api.post('/api/auth/login', data: {'phone': phone, 'smsCode': code});
      final data = response.data['data'];
      if (data == null) return response.data['message'] ?? '登录失败';

      await api.saveTokens(data['accessToken'], data['refreshToken']);
      final user = data['user'];
      state = AuthState(
        isLoggedIn: true,
        isLoading: false,
        user: UserInfo(
          id: user['id'] ?? '',
          phone: user['phone'] ?? '',
          name: user['name'],
          avatarUrl: user['avatarUrl'],
        ),
      );
      return null;
    } catch (e) {
      return '登录失败: $e';
    }
  }

  /// 登出
  Future<void> logout() async {
    final api = ref.read(apiClientProvider);
    final db = ref.read(localDbProvider);
    final refresh = await db.read('refresh_token');
    if (refresh != null) {
      try { await api.post('/api/auth/logout', data: {'refreshToken': refresh}); } catch (_) {}
    }
    await api.clearTokens();
    state = const AuthState(isLoggedIn: false, isLoading: false);
  }
}
