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/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/presentation/pages/group_page.dart';

class _MockGroupRepository extends Mock implements GroupRepository {}

class _FakeGroupInput extends Fake implements GroupInput {}

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

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  setUpAll(() {
    registerFallbackValue(_FakeGroupInput());
  });

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

  testWidgets('플래그 Off 시 스펙 페이지 표시', (tester) async {
    dotenv.testLoad(fileInput: 'FEATURE_GROUPS_ENABLED=false\n');

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

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

  group('플래그 On', () {
    late _MockGroupRepository repository;

    setUp(() {
      dotenv.testLoad(fileInput: 'FEATURE_GROUPS_ENABLED=true\n');
      repository = _MockGroupRepository();
      GetIt.I.registerLazySingleton<GroupRepository>(() => repository);
    });

    testWidgets('목록을 조회하여 표에 렌더링한다', (tester) async {
      when(
        () => repository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          query: any(named: 'query'),
          isDefault: any(named: 'isDefault'),
          isActive: any(named: 'isActive'),
        ),
      ).thenAnswer(
        (_) async => PaginatedResult<Group>(
          items: [
            Group(
              id: 1,
              groupName: '관리자',
              description: '전체 권한',
              isDefault: true,
            ),
          ],
          page: 1,
          pageSize: 20,
          total: 1,
        ),
      );

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

      expect(find.text('관리자'), findsOneWidget);
      verify(
        () => repository.list(
          page: 1,
          pageSize: 20,
          query: null,
          isDefault: null,
          isActive: null,
        ),
      ).called(1);
    });

    testWidgets('신규 등록 폼 검증 오류를 노출한다', (tester) async {
      when(
        () => repository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          query: any(named: 'query'),
          isDefault: any(named: 'isDefault'),
          isActive: any(named: 'isActive'),
        ),
      ).thenAnswer(
        (_) async => PaginatedResult<Group>(
          items: const [],
          page: 1,
          pageSize: 20,
          total: 0,
        ),
      );

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

      await tester.tap(find.text('신규 등록'));
      await tester.pumpAndSettle();
      await tester.tapShadButton('등록', settle: false);
      await tester.pump();

      expect(find.text('그룹명을 입력하세요.'), findsOneWidget);
    });

    testWidgets('신규 등록 성공 시 목록이 갱신된다', (tester) async {
      var listCallCount = 0;
      when(
        () => repository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          query: any(named: 'query'),
          isDefault: any(named: 'isDefault'),
          isActive: any(named: 'isActive'),
        ),
      ).thenAnswer((_) async {
        listCallCount += 1;
        if (listCallCount == 1) {
          return PaginatedResult<Group>(
            items: const [],
            page: 1,
            pageSize: 20,
            total: 0,
          );
        }
        return PaginatedResult<Group>(
          items: [Group(id: 2, groupName: '운영팀', description: '운영 담당')],
          page: 1,
          pageSize: 20,
          total: 1,
        );
      });

      GroupInput? capturedInput;
      when(() => repository.create(any())).thenAnswer((invocation) async {
        capturedInput = invocation.positionalArguments.first as GroupInput;
        return Group(
          id: 2,
          groupName: capturedInput!.groupName,
          description: capturedInput!.description,
        );
      });

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

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

      final dialog = find.byType(Dialog);
      final editableTexts = find.descendant(
        of: dialog,
        matching: find.byType(EditableText),
      );

      await tester.enterText(editableTexts.at(0), '운영팀');
      await tester.enterText(editableTexts.at(1), '운영 담당');

      await tester.tapShadButton('등록');

      expect(capturedInput, isNotNull);
      expect(capturedInput?.groupName, '운영팀');
      expect(find.byType(Dialog), findsNothing);
      expect(find.text('운영팀'), findsOneWidget);
      verify(() => repository.create(any())).called(1);
    });
  });
}
