import 'package:flutter/foundation.dart';

import '../../../core/network/interceptors/auth_interceptor.dart';
import '../../../core/services/token_storage.dart';
import '../domain/entities/auth_session.dart';
import '../domain/entities/authenticated_user.dart';
import '../domain/entities/login_request.dart';
import '../domain/repositories/auth_repository.dart';

/// 인증 세션을 관리하고 토큰을 보관하는 서비스.
class AuthService extends ChangeNotifier {
  AuthService({
    required AuthRepository repository,
    required TokenStorage tokenStorage,
  }) : _repository = repository,
       _tokenStorage = tokenStorage;

  final AuthRepository _repository;
  final TokenStorage _tokenStorage;

  AuthSession? _session;
  bool _rememberMe = false;

  /// 현재 로그인된 세션 (없으면 null)
  AuthSession? get session => _session;

  /// 사용자가 마지막으로 선택한 자동 로그인 여부
  bool get rememberMe => _rememberMe;

  /// 로그인 후 세션을 저장하고 토큰을 보관한다.
  Future<AuthSession> login(LoginRequest request) async {
    final session = await _repository.login(request);
    _rememberMe = request.rememberMe;
    await _persistSession(session);
    return session;
  }

  /// 저장된 리프레시 토큰으로 세션을 갱신한다.
  Future<AuthSession?> refreshSession() async {
    final refreshToken = await _tokenStorage.readRefreshToken();
    if (refreshToken == null || refreshToken.isEmpty) {
      return null;
    }
    final session = await _repository.refresh(refreshToken);
    await _persistSession(session);
    return session;
  }

  /// 앱 내에서 명시적으로 로그아웃할 때 호출한다.
  Future<void> clearSession() async {
    _session = null;
    _rememberMe = false;
    await _tokenStorage.clear();
    notifyListeners();
  }

  /// 인터셉터에서 사용할 토큰 쌍을 반환한다.
  Future<TokenPair?> refreshForInterceptor() async {
    try {
      final session = await refreshSession();
      if (session == null) {
        return null;
      }
      return TokenPair(
        accessToken: session.accessToken,
        refreshToken: session.refreshToken,
      );
    } catch (_) {
      return null;
    }
  }

  /// 현재 세션의 사용자 정보를 갱신한다.
  void updateSessionUser(AuthenticatedUser user) {
    final current = _session;
    if (current == null) {
      return;
    }
    _session = AuthSession(
      accessToken: current.accessToken,
      refreshToken: current.refreshToken,
      expiresAt: current.expiresAt,
      user: user,
      permissions: current.permissions,
    );
    notifyListeners();
  }

  Future<void> _persistSession(AuthSession session) async {
    _session = session;
    await _tokenStorage.writeAccessToken(session.accessToken);
    if (session.hasRefreshToken) {
      await _tokenStorage.writeRefreshToken(session.refreshToken);
    } else {
      await _tokenStorage.writeRefreshToken(null);
    }
    notifyListeners();
  }
}
