import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../../../core/network/api_exception.dart';
import '../data/auth_providers.dart';
import '../domain/auth_repository.dart';
import '../domain/auth_state.dart';

part 'auth_controller.g.dart';

/// 登录状态控制器。
///
/// 会话级持有（`keepAlive`），负责令牌恢复、登录 / 注册 / 退出，
/// 以及启动期的登录态校验（verify + refresh 重试）。
@Riverpod(keepAlive: true)
class AuthController extends _$AuthController {
  AuthRepository get _repository => ref.read(authRepositoryProvider);

  @override
  FutureOr<AuthState> build() async {
    final repository = ref.watch(authRepositoryProvider);
    await repository.restore();
    final loggedIn =
        repository.accessToken != null && await repository.hasRefreshToken();
    return AuthState(
      loggedIn: loggedIn,
      username: await repository.getUsername(),
    );
  }

  AuthState get _current => state.valueOrNull ?? const AuthState();

  /// 校验本地令牌是否仍然有效（对应启动页流程）。
  ///
  /// 无令牌直接返回 false；`verify` 失败时尝试 `refresh` 后重试一次，
  /// 仍失败则清空令牌。
  Future<bool> checkLoginState() async {
    final repository = _repository;
    await repository.restore();
    if (repository.accessToken == null) {
      if (!await repository.hasRefreshToken()) {
        await _reset();
        return false;
      }
    }

    if (await _verifyQuietly()) {
      state = AsyncData(
        _current.copyWith(
          loggedIn: true,
          username: await repository.getUsername(),
        ),
      );
      return true;
    }

    // access token 失效：用 refreshToken 续期后再校验一次。
    try {
      await repository.refresh();
    } on Object {
      await _reset();
      return false;
    }

    if (await _verifyQuietly()) {
      state = AsyncData(
        _current.copyWith(
          loggedIn: true,
          username: await repository.getUsername(),
        ),
      );
      return true;
    }

    await _reset();
    return false;
  }

  Future<bool> _verifyQuietly() async {
    try {
      await _repository.verify();
      return true;
    } on Object {
      return false;
    }
  }

  Future<void> _reset() async {
    final username = await _repository.getUsername();
    await _repository.clear();
    state = AsyncData(AuthState(username: username));
  }

  /// 登录：成功返回 true，失败返回 false 并写入 [AuthState.error]。
  Future<bool> login(String username, String password) async {
    state = AsyncData(_current.copyWith(submitting: true, error: null));
    try {
      await _repository.login(username, password);
      state = AsyncData(AuthState(loggedIn: true, username: username));
      return true;
    } catch (e) {
      state = AsyncData(
        _current.copyWith(
          submitting: false,
          loggedIn: false,
          error: _describe(e, '登录失败'),
        ),
      );
      return false;
    }
  }

  /// 注册：成功后不自动登录，仅通过 [AuthState.alert] 提示前往登录。
  Future<bool> register(String username, String password) async {
    state = AsyncData(_current.copyWith(submitting: true, error: null));
    try {
      await _repository.register(username, password);
      state = AsyncData(
        _current.copyWith(
          submitting: false,
          error: null,
          alert: '注册成功，请登录',
        ),
      );
      return true;
    } catch (e) {
      state = AsyncData(
        _current.copyWith(
          submitting: false,
          error: _describe(e, '注册失败'),
        ),
      );
      return false;
    }
  }

  /// 退出登录：清空令牌并复位状态（保留用户名用于回显）。
  Future<void> logout() async {
    await _reset();
  }

  /// 展示一次性提示（如从主页因登录失效跳转时携带的文案）。
  void showAlert(String message) {
    state = AsyncData(_current.copyWith(alert: message));
  }

  /// 消费一次性提示，避免重建时重复展示。
  void consumeAlert() {
    if (_current.alert != null) {
      state = AsyncData(_current.copyWith(alert: null));
    }
  }

  /// 清空错误信息。
  void clearError() {
    if (_current.error != null) {
      state = AsyncData(_current.copyWith(error: null));
    }
  }

  /// 优先展示服务端返回的错误码，其余异常回落到通用提示。
  String _describe(Object e, String fallback) {
    if (e is ApiException) return e.code;
    return '$fallback：$e';
  }
}
