// Author: fruit.com.cn import 'package:fruitshorts/core/data/models/account_device.dart'; import 'package:fruitshorts/core/data/models/account_export.dart'; import 'package:fruitshorts/core/data/models/account_profile.dart'; import 'package:fruitshorts/core/data/repositories/account_repository.dart'; import 'package:fruitshorts/core/data/remote/api_client.dart'; /// 账号中心测试替身;可预置数据与失败文案。 class FakeAccountRepository implements AccountRepository { FakeAccountRepository({ AccountProfile? profile, List devices = const [], AccountExport? export, }) : _profile = profile ?? defaultProfile, _devices = [...devices], _export = export ?? defaultExport; static const defaultProfile = AccountProfile( uid: 'U-K19', nickname: 'Nadia', avatarUrl: '', gender: 'female', countryCode: 'ID', regionCode: 'JK', language: 'id', timezone: 'Asia/Jakarta', currency: 'IDR', status: 'normal', maskedTarget: 'n***@example.com', vipLevel: 0, ); static const defaultExport = AccountExport( profile: defaultProfile, credentials: [ AccountCredential( type: 'EMAIL', masked: 'n***@example.com', verified: true, ), ], consentCount: 1, devices: [], raw: { 'profile': {'uid': 'U-K19', 'nickname': 'Nadia'}, 'credentials': [ {'type': 'EMAIL', 'masked': 'n***@example.com', 'verified': true}, ], 'consents': [ {'scene': 'privacy'}, ], 'devices': [], }, ); AccountProfile _profile; final List _devices; final AccountExport _export; AccountProfileUpdate? lastUpdate; String? lastDeactivateReason; int profileCalls = 0; int deviceCalls = 0; int exportCalls = 0; bool failProfile = false; bool failDevices = false; bool failExport = false; bool failUpdate = false; bool failDeactivate = false; bool failCancel = false; bool throwUnexpected = false; @override Future profile() async { profileCalls++; if (throwUnexpected) throw StateError('offline'); if (failProfile) throw const ApiException(500, '资料加载失败'); return _profile; } @override Future updateProfile(AccountProfileUpdate update) async { lastUpdate = update; if (throwUnexpected) throw StateError('offline'); if (failUpdate) throw const ApiException(400, '昵称不可用'); _profile = AccountProfile( uid: _profile.uid, nickname: update.nickname ?? _profile.nickname, avatarUrl: _profile.avatarUrl, gender: update.gender ?? _profile.gender, countryCode: _profile.countryCode, regionCode: _profile.regionCode, language: _profile.language, timezone: _profile.timezone, currency: _profile.currency, status: _profile.status, maskedTarget: _profile.maskedTarget, vipLevel: _profile.vipLevel, ); return _profile; } @override Future> devices() async { deviceCalls++; if (throwUnexpected) throw StateError('offline'); if (failDevices) throw const ApiException(500, '设备加载失败'); return [..._devices]; } @override Future export() async { exportCalls++; if (throwUnexpected) throw StateError('offline'); if (failExport) throw const ApiException(500, '导出失败'); return _export; } @override Future deactivate(String reason) async { lastDeactivateReason = reason; if (failDeactivate) throw const ApiException(100009, '注销申请已在处理中'); return DateTime(2026, 11, 3, 9, 30); } @override Future cancelDeactivation() async { if (failCancel) { throw const ApiException(100009, '没有待处理的注销申请'); } } }