import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

import 'package:lanebow/services/auth_service.dart';
import 'package:lanebow/services/api_service.dart';
import 'package:lanebow/models/user_model.dart';
import 'package:lanebow/config/api_config.dart';

@GenerateMocks([ApiService, FlutterSecureStorage])
import 'auth_service_test.mocks.dart';

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  group('AuthService', () {
    late MockApiService mockApiService;
    late MockFlutterSecureStorage mockSecureStorage;
    late AuthService authService;

    setUp(() async {
      mockApiService = MockApiService();
      mockSecureStorage = MockFlutterSecureStorage();
      SharedPreferences.setMockInitialValues({});
      authService = AuthService(apiService: mockApiService, secureStorage: mockSecureStorage);
    });

    test('login 성공 시 토큰/유저 저장 및 isAuthenticated=true', () async {
      // arrange
      final fakeUserJson = {
        'id': 'u1',
        'name': 'Tester',
        'email': 't@example.com',
        'role': 'admin',
        'clubId': 'c1',
      };
      when(mockApiService.post(ApiConfig.login, data: anyNamed('data'))).thenAnswer(
        (_) async => {
          'token': 'fake-token',
          'user': fakeUserJson,
        },
      );

      // act
      final ok = await authService.login('id', 'pw');

      // assert
      expect(ok, true);
      expect(authService.isAuthenticated, true);
      expect(authService.token, 'fake-token');
      verify(mockSecureStorage.write(key: ApiConfig.tokenKey, value: 'fake-token')).called(1);
      verify(mockApiService.setToken('fake-token')).called(1);

      final prefs = await SharedPreferences.getInstance();
      expect(prefs.getString(ApiConfig.userIdKey), 'u1');
      expect(prefs.getString(ApiConfig.userRoleKey), 'admin');
      expect(prefs.getString(ApiConfig.clubIdKey), 'c1');
    });

    test('initialize() 저장된 토큰이 있으면 프로필 조회 및 currentUser 설정', () async {
      // arrange
      when(mockSecureStorage.read(key: ApiConfig.tokenKey)).thenAnswer((_) async => 'saved-token');
      when(mockApiService.get(ApiConfig.profile)).thenAnswer((_) async => {
            'id': 'u1',
            'name': 'Tester',
            'email': 't@example.com',
            'role': 'admin',
            'clubId': 'c1',
          });

      // act
      await authService.initialize();

      // assert
      expect(authService.isInitialized, true);
      expect(authService.token, 'saved-token');
      expect(authService.currentUser, isA<User>());
      verify(mockApiService.setToken('saved-token')).called(1);
    });

    test('logout() 토큰/유저/저장소 초기화', () async {
      // arrange: 로그인된 상태처럼 세팅
      when(mockApiService.post(ApiConfig.login, data: anyNamed('data'))).thenAnswer(
        (_) async => {
          'token': 'fake-token',
          'user': {
            'id': 'u1',
            'name': 'Tester',
            'email': 't@example.com',
            'role': 'admin',
          },
        },
      );
      await authService.login('id', 'pw');

      // act
      await authService.logout();

      // assert
      expect(authService.isAuthenticated, false);
      expect(authService.currentUser, isNull);
      verify(mockSecureStorage.delete(key: ApiConfig.tokenKey)).called(1);
      final prefs = await SharedPreferences.getInstance();
      expect(prefs.getString(ApiConfig.userIdKey), isNull);
      expect(prefs.getString(ApiConfig.userRoleKey), isNull);
      expect(prefs.getString(ApiConfig.clubIdKey), isNull);
    });
  });
}
