import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get_it/get_it.dart';
import 'package:go_router/go_router.dart';
import 'package:mocktail/mocktail.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import 'package:superport_v2/core/common/models/paginated_result.dart';
import 'package:superport_v2/core/config/environment.dart';
import 'package:superport_v2/core/constants/app_sections.dart';
import 'package:superport_v2/core/permissions/permission_manager.dart';
import 'package:superport_v2/core/theme/superport_shad_theme.dart';
import 'package:superport_v2/core/services/token_storage.dart';
import 'package:superport_v2/features/auth/application/auth_service.dart';
import 'package:superport_v2/features/auth/domain/entities/auth_session.dart';
import 'package:superport_v2/features/auth/domain/entities/authenticated_user.dart';
import 'package:superport_v2/features/auth/domain/entities/login_request.dart';
import 'package:superport_v2/features/auth/domain/repositories/auth_repository.dart';
import 'package:superport_v2/features/login/presentation/pages/login_page.dart';
import 'package:superport_v2/features/masters/group/domain/entities/group.dart';
import 'package:superport_v2/features/masters/group/domain/repositories/group_repository.dart';
import 'package:superport_v2/features/masters/group_permission/domain/entities/group_permission.dart';
import 'package:superport_v2/features/masters/group_permission/domain/repositories/group_permission_repository.dart';

GoRouter _createTestRouter() {
  return GoRouter(
    initialLocation: loginRoutePath,
    routes: [
      GoRoute(
        path: loginRoutePath,
        builder: (context, state) => const LoginPage(),
      ),
      GoRoute(
        path: dashboardRoutePath,
        builder: (context, state) => const _TestDashboardPage(),
      ),
      GoRoute(
        path: '/inventory/inbound',
        builder: (context, state) => const _PlaceholderPage(title: '입고 화면'),
      ),
      GoRoute(
        path: '/inventory/outbound',
        builder: (context, state) => const _PlaceholderPage(title: '출고 화면'),
      ),
      GoRoute(
        path: '/inventory/rental',
        builder: (context, state) => const _PlaceholderPage(title: '대여 화면'),
      ),
    ],
  );
}

class _TestApp extends StatelessWidget {
  const _TestApp({required this.router});

  final GoRouter router;

  @override
  Widget build(BuildContext context) {
    return PermissionScope(
      manager: PermissionManager(),
      child: ShadApp.router(
        routerConfig: router,
        debugShowCheckedModeBanner: false,
        theme: SuperportShadTheme.light(),
        darkTheme: SuperportShadTheme.dark(),
      ),
    );
  }
}

class _TestDashboardPage extends StatelessWidget {
  const _TestDashboardPage();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('테스트 대시보드'),
        actions: [
          IconButton(
            tooltip: '로그아웃',
            icon: const Icon(Icons.logout),
            onPressed: () => context.go(loginRoutePath),
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            TextButton(
              onPressed: () => context.go('/inventory/inbound'),
              child: const Text('입고로 이동'),
            ),
            TextButton(
              onPressed: () => context.go('/inventory/outbound'),
              child: const Text('출고로 이동'),
            ),
            TextButton(
              onPressed: () => context.go('/inventory/rental'),
              child: const Text('대여로 이동'),
            ),
          ],
        ),
      ),
    );
  }
}

class _PlaceholderPage extends StatelessWidget {
  const _PlaceholderPage({required this.title});

  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(
        child: TextButton(
          onPressed: () => context.go(dashboardRoutePath),
          child: const Text('대시보드로 돌아가기'),
        ),
      ),
    );
  }
}

class _StubGroupRepository implements GroupRepository {
  @override
  Future<Group> create(GroupInput input) {
    throw UnimplementedError();
  }

  @override
  Future<void> delete(int id) {
    throw UnimplementedError();
  }

  @override
  Future<PaginatedResult<Group>> list({
    int page = 1,
    int pageSize = 20,
    String? query,
    bool? isDefault,
    bool? isActive,
    bool includePermissions = false,
    bool includeEmployees = false,
  }) async {
    return PaginatedResult<Group>(
      items: [
        Group(
          id: 1,
          groupName: '기본 그룹',
          description: '테스트',
          isDefault: true,
          isActive: true,
        ),
      ],
      page: 1,
      pageSize: 1,
      total: 1,
    );
  }

  @override
  Future<Group> restore(int id) {
    throw UnimplementedError();
  }

  @override
  Future<Group> update(int id, GroupInput input) {
    throw UnimplementedError();
  }
}

class _StubGroupPermissionRepository implements GroupPermissionRepository {
  @override
  Future<GroupPermission> create(GroupPermissionInput input) {
    throw UnimplementedError();
  }

  @override
  Future<void> delete(int id) {
    throw UnimplementedError();
  }

  @override
  Future<PaginatedResult<GroupPermission>> list({
    int page = 1,
    int pageSize = 20,
    int? groupId,
    int? menuId,
    bool? isActive,
    bool includeDeleted = false,
  }) async {
    return PaginatedResult<GroupPermission>(
      items: [
        GroupPermission(
          id: 1,
          group: GroupPermissionGroup(id: groupId ?? 1, groupName: '기본 그룹'),
          menu: GroupPermissionMenu(
            id: 10,
            menuCode: 'DASHBOARD',
            menuName: '대시보드',
            path: dashboardRoutePath,
          ),
          canCreate: true,
          canRead: true,
          canUpdate: true,
          canDelete: true,
        ),
      ],
      page: 1,
      pageSize: 1,
      total: 1,
    );
  }

  @override
  Future<GroupPermission> restore(int id) {
    throw UnimplementedError();
  }

  @override
  Future<GroupPermission> update(int id, GroupPermissionInput input) {
    throw UnimplementedError();
  }
}

class _MockAuthRepository extends Mock implements AuthRepository {}

class _FakeTokenStorage implements TokenStorage {
  String? _accessToken;
  String? _refreshToken;

  @override
  Future<void> clear() async {
    _accessToken = null;
    _refreshToken = null;
  }

  @override
  Future<String?> readAccessToken() async => _accessToken;

  @override
  Future<String?> readRefreshToken() async => _refreshToken;

  @override
  Future<void> writeAccessToken(String? token) async {
    _accessToken = token;
  }

  @override
  Future<void> writeRefreshToken(String? token) async {
    _refreshToken = token;
  }
}

AuthSession _buildSampleSession() {
  return const AuthSession(
    accessToken: 'access-token',
    refreshToken: 'refresh-token',
    expiresAt: null,
    user: AuthenticatedUser(id: 1, name: '테스터', phone: null),
    permissions: [],
  );
}

void _registerAuthService(
  _MockAuthRepository repository,
  _FakeTokenStorage storage,
) {
  final service = AuthService(repository: repository, tokenStorage: storage);
  when(
    () => repository.login(any()),
  ).thenAnswer((_) async => _buildSampleSession());
  when(() => repository.refresh(any())).thenThrow(UnimplementedError());
  GetIt.I.registerSingleton<AuthService>(service);
}

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  setUpAll(() {
    registerFallbackValue(
      LoginRequest(identifier: '', password: '', rememberMe: false),
    );
  });

  late _MockAuthRepository authRepository;
  late _FakeTokenStorage tokenStorage;

  setUp(() async {
    await GetIt.I.reset();
    authRepository = _MockAuthRepository();
    tokenStorage = _FakeTokenStorage();
    _registerAuthService(authRepository, tokenStorage);
  });

  setUpAll(() async {
    await Environment.initialize();
  });

  Finder editableTextAt(int index) => find.byType(EditableText).at(index);

  testWidgets('사용자가 로그인 후 주요 화면을 탐색할 수 있다', (tester) async {
    final view = tester.view;
    view.physicalSize = const Size(1080, 720);
    view.devicePixelRatio = 1.0;
    addTearDown(() {
      view.resetPhysicalSize();
      view.resetDevicePixelRatio();
    });

    GetIt.I.registerSingleton<GroupRepository>(_StubGroupRepository());
    GetIt.I.registerSingleton<GroupPermissionRepository>(
      _StubGroupPermissionRepository(),
    );

    final router = _createTestRouter();
    await tester.pumpWidget(_TestApp(router: router));
    await tester.pumpAndSettle();

    expect(find.text('Superport v2 로그인'), findsOneWidget);

    await tester.enterText(editableTextAt(0), 'tester');
    await tester.enterText(editableTextAt(1), 'password123');
    await tester.tap(find.widgetWithText(ShadButton, '로그인'));
    await tester.pump(const Duration(milliseconds: 650));
    await tester.pumpAndSettle();

    expect(find.text('테스트 대시보드'), findsOneWidget);

    await tester.tap(find.widgetWithText(TextButton, '입고로 이동'));
    await tester.pumpAndSettle();
    expect(find.text('입고 화면'), findsOneWidget);

    await tester.tap(find.widgetWithText(TextButton, '대시보드로 돌아가기'));
    await tester.pumpAndSettle();
    expect(find.text('테스트 대시보드'), findsOneWidget);

    await tester.tap(find.widgetWithText(TextButton, '출고로 이동'));
    await tester.pumpAndSettle();
    expect(find.text('출고 화면'), findsOneWidget);

    await tester.tap(find.widgetWithText(TextButton, '대시보드로 돌아가기'));
    await tester.pumpAndSettle();

    await tester.tap(find.widgetWithText(TextButton, '대여로 이동'));
    await tester.pumpAndSettle();
    expect(find.text('대여 화면'), findsOneWidget);

    await tester.tap(find.widgetWithText(TextButton, '대시보드로 돌아가기'));
    await tester.pumpAndSettle();

    await tester.tap(find.byTooltip('로그아웃'));
    await tester.pumpAndSettle();
    expect(find.text('Superport v2 로그인'), findsOneWidget);
  });
}
