import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get_it/get_it.dart';
import 'package:mocktail/mocktail.dart';
import 'package:shadcn_ui/shadcn_ui.dart';

import '../../../../../helpers/tester_extensions.dart';
import 'package:superport_v2/core/common/models/paginated_result.dart';
import 'package:superport_v2/core/permissions/permission_manager.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';
import 'package:superport_v2/features/masters/group_permission/presentation/pages/group_permission_page.dart';
import 'package:superport_v2/features/masters/menu/domain/entities/menu.dart';
import 'package:superport_v2/features/masters/menu/domain/repositories/menu_repository.dart';

class _MockPermissionRepository extends Mock
    implements GroupPermissionRepository {}

class _MockGroupRepository extends Mock implements GroupRepository {}

class _MockMenuRepository extends Mock implements MenuRepository {}

class _FakeGroupPermissionInput extends Fake implements GroupPermissionInput {}

Widget _buildApp(Widget child) {
  return PermissionScope(
    manager: PermissionManager(),
    child: MaterialApp(
      home: ShadTheme(
        data: ShadThemeData(
          colorScheme: const ShadSlateColorScheme.light(),
          brightness: Brightness.light,
        ),
        child: Scaffold(body: child),
      ),
    ),
  );
}

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  setUpAll(() {
    registerFallbackValue(_FakeGroupPermissionInput());
  });

  tearDown(() async {
    await GetIt.I.reset();
    dotenv.clean();
  });

  testWidgets('플래그 Off 시 스펙 화면 표시', (tester) async {
    dotenv.testLoad(fileInput: 'FEATURE_GROUP_PERMISSIONS_ENABLED=false\n');

    await tester.pumpWidget(_buildApp(const GroupPermissionPage()));
    await tester.pump();

    expect(find.text('그룹 권한 관리'), findsOneWidget);
    expect(find.text('비활성화 (백엔드 준비 중)'), findsOneWidget);
  });

  group('플래그 On', () {
    late _MockPermissionRepository permissionRepository;
    late _MockGroupRepository groupRepository;
    late _MockMenuRepository menuRepository;

    setUp(() {
      dotenv.testLoad(fileInput: 'FEATURE_GROUP_PERMISSIONS_ENABLED=true\n');
      permissionRepository = _MockPermissionRepository();
      groupRepository = _MockGroupRepository();
      menuRepository = _MockMenuRepository();
      GetIt.I.registerLazySingleton<GroupPermissionRepository>(
        () => permissionRepository,
      );
      GetIt.I.registerLazySingleton<GroupRepository>(() => groupRepository);
      GetIt.I.registerLazySingleton<MenuRepository>(() => menuRepository);

      when(
        () => groupRepository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          query: any(named: 'query'),
          isDefault: any(named: 'isDefault'),
          isActive: any(named: 'isActive'),
          includePermissions: any(named: 'includePermissions'),
          includeEmployees: any(named: 'includeEmployees'),
        ),
      ).thenAnswer(
        (_) async => PaginatedResult<Group>(
          items: [Group(id: 1, groupName: '관리자')],
          page: 1,
          pageSize: 20,
          total: 1,
        ),
      );

      when(
        () => menuRepository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          query: any(named: 'query'),
          parentId: any(named: 'parentId'),
          isActive: any(named: 'isActive'),
          includeDeleted: any(named: 'includeDeleted'),
        ),
      ).thenAnswer(
        (_) async => PaginatedResult<MenuItem>(
          items: [MenuItem(id: 10, menuCode: 'MENU001', menuName: '대시보드')],
          page: 1,
          pageSize: 20,
          total: 1,
        ),
      );
    });

    testWidgets('목록을 조회해 테이블에 렌더링한다', (tester) async {
      when(
        () => permissionRepository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          groupId: any(named: 'groupId'),
          menuId: any(named: 'menuId'),
          isActive: any(named: 'isActive'),
          includeDeleted: any(named: 'includeDeleted'),
        ),
      ).thenAnswer(
        (_) async => PaginatedResult<GroupPermission>(
          items: [
            GroupPermission(
              id: 1,
              group: GroupPermissionGroup(id: 1, groupName: '관리자'),
              menu: GroupPermissionMenu(
                id: 10,
                menuCode: 'DASHBOARD',
                menuName: '대시보드',
                path: '/dashboard',
              ),
              canCreate: true,
              canRead: true,
            ),
          ],
          page: 1,
          pageSize: 20,
          total: 1,
        ),
      );

      await tester.pumpWidget(_buildApp(const GroupPermissionPage()));
      await tester.pumpAndSettle();

      expect(find.text('대시보드'), findsWidgets);
      expect(find.text('관리자'), findsOneWidget);
    });

    testWidgets('신규 등록 폼 검증 메시지를 표시한다', (tester) async {
      when(
        () => permissionRepository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          groupId: any(named: 'groupId'),
          menuId: any(named: 'menuId'),
          isActive: any(named: 'isActive'),
          includeDeleted: any(named: 'includeDeleted'),
        ),
      ).thenAnswer(
        (_) async => PaginatedResult<GroupPermission>(
          items: const [],
          page: 1,
          pageSize: 20,
          total: 0,
        ),
      );

      await tester.pumpWidget(_buildApp(const GroupPermissionPage()));
      await tester.pumpAndSettle();

      await tester.tap(find.text('신규 등록'));
      await tester.pumpAndSettle();

      await tester.tapShadButton('등록', settle: false);
      await tester.pump();

      expect(find.text('그룹을 선택하세요.'), findsOneWidget);
      expect(find.text('메뉴를 선택하세요.'), findsOneWidget);
    });

    testWidgets('신규 등록 성공 시 repository.create 호출', (tester) async {
      var listCall = 0;
      when(
        () => permissionRepository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          groupId: any(named: 'groupId'),
          menuId: any(named: 'menuId'),
          isActive: any(named: 'isActive'),
          includeDeleted: any(named: 'includeDeleted'),
        ),
      ).thenAnswer((_) async {
        listCall += 1;
        if (listCall == 1) {
          return PaginatedResult<GroupPermission>(
            items: const [],
            page: 1,
            pageSize: 20,
            total: 0,
          );
        }
        return PaginatedResult<GroupPermission>(
          items: [
            GroupPermission(
              id: 5,
              group: GroupPermissionGroup(id: 1, groupName: '관리자'),
              menu: GroupPermissionMenu(
                id: 10,
                menuCode: 'DASHBOARD',
                menuName: '대시보드',
                path: '/dashboard',
              ),
              canCreate: true,
              canRead: true,
            ),
          ],
          page: 1,
          pageSize: 20,
          total: 1,
        );
      });

      GroupPermissionInput? capturedInput;
      when(() => permissionRepository.create(any())).thenAnswer((
        invocation,
      ) async {
        capturedInput =
            invocation.positionalArguments.first as GroupPermissionInput;
        return GroupPermission(
          id: 5,
          group: GroupPermissionGroup(
            id: capturedInput!.groupId,
            groupName: '관리자',
          ),
          menu: GroupPermissionMenu(
            id: capturedInput!.menuId,
            menuCode: 'DASHBOARD',
            menuName: '대시보드',
            path: '/dashboard',
          ),
          canCreate: capturedInput!.canCreate,
          canRead: capturedInput!.canRead,
        );
      });

      await tester.pumpWidget(_buildApp(const GroupPermissionPage()));
      await tester.pumpAndSettle();

      await tester.tap(find.text('신규 등록'));
      await tester.pumpAndSettle();

      final dialog = find.byType(Dialog);
      final selects = find.descendant(
        of: dialog,
        matching: find.byWidgetPredicate((widget) => widget is ShadSelect),
      );

      // 그룹 선택
      await tester.tap(selects.at(0));
      await tester.pumpAndSettle();
      await tester.tap(find.text('관리자').last);
      await tester.pumpAndSettle();

      // 메뉴 선택
      await tester.tap(selects.at(1));
      await tester.pumpAndSettle();
      await tester.tap(find.text('대시보드').last);
      await tester.pumpAndSettle();

      // 권한 체크 (생성, 수정, 삭제 on)
      final switches = find.descendant(
        of: dialog,
        matching: find.byType(ShadSwitch),
      );
      await tester.tap(switches.at(0));
      await tester.pump();
      await tester.tap(switches.at(2));
      await tester.pump();
      await tester.tap(switches.at(3));
      await tester.pump();

      await tester.tapShadButton('등록');

      expect(capturedInput, isNotNull);
      expect(capturedInput?.groupId, 1);
      expect(capturedInput?.menuId, 10);
      expect(capturedInput?.canCreate, isTrue);
      expect(capturedInput?.canUpdate, isTrue);
      expect(find.byType(Dialog), findsNothing);
      expect(find.text('대시보드'), findsWidgets);
      verify(() => permissionRepository.create(any())).called(1);
    });
  });
}
