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/vendor/domain/entities/vendor.dart';
import 'package:superport_v2/features/masters/vendor/domain/repositories/vendor_repository.dart';
import 'package:superport_v2/features/masters/vendor/presentation/pages/vendor_page.dart';

class _MockVendorRepository extends Mock implements VendorRepository {}

class _FakeVendorInput extends Fake implements VendorInput {}

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(_FakeVendorInput());
  });

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

  testWidgets('FEATURE_VENDORS_ENABLED=false 이면 스펙 페이지를 노출한다', (tester) async {
    dotenv.testLoad(fileInput: 'FEATURE_VENDORS_ENABLED=false\n');

    await tester.pumpWidget(
      _buildApp(VendorPage(routeUri: Uri(path: '/masters/vendors'))),
    );
    await tester.pump();

    expect(find.text('제조사(벤더) 관리'), findsOneWidget);
    expect(find.text('비활성화 (백엔드 준비 중)'), findsOneWidget);
  });

  testWidgets('기능 플래그 on 시 목록을 조회하여 표에 렌더링한다', (tester) async {
    dotenv.testLoad(fileInput: 'FEATURE_VENDORS_ENABLED=true\n');
    final repository = _MockVendorRepository();
    GetIt.I.registerLazySingleton<VendorRepository>(() => repository);

    final vendor = Vendor(id: 1, vendorCode: 'V-001', vendorName: '슈퍼벤더');

    when(
      () => repository.list(
        page: any(named: 'page'),
        pageSize: any(named: 'pageSize'),
        query: any(named: 'query'),
        isActive: any(named: 'isActive'),
      ),
    ).thenAnswer(
      (_) async => PaginatedResult<Vendor>(
        items: [vendor],
        page: 1,
        pageSize: 20,
        total: 1,
      ),
    );

    await tester.pumpWidget(
      _buildApp(VendorPage(routeUri: Uri(path: '/masters/vendors'))),
    );
    await tester.pumpAndSettle();

    expect(find.text('V-001'), findsOneWidget);
    verify(
      () => repository.list(page: 1, pageSize: 20, query: null, isActive: null),
    ).called(1);
  });

  testWidgets('목록이 비어 있으면 안내 문구를 표시한다', (tester) async {
    dotenv.testLoad(fileInput: 'FEATURE_VENDORS_ENABLED=true\n');
    final repository = _MockVendorRepository();
    GetIt.I.registerLazySingleton<VendorRepository>(() => repository);

    when(
      () => repository.list(
        page: any(named: 'page'),
        pageSize: any(named: 'pageSize'),
        query: any(named: 'query'),
        isActive: any(named: 'isActive'),
      ),
    ).thenAnswer(
      (_) async => PaginatedResult<Vendor>(
        items: const [],
        page: 1,
        pageSize: 20,
        total: 0,
      ),
    );

    await tester.pumpWidget(
      _buildApp(VendorPage(routeUri: Uri(path: '/masters/vendors'))),
    );
    await tester.pumpAndSettle();

    expect(find.text('조건에 맞는 벤더가 없습니다.'), findsOneWidget);
  });

  testWidgets('신규 등록 폼에서 필수값 미입력 시 검증 메시지를 보여준다', (tester) async {
    dotenv.testLoad(fileInput: 'FEATURE_VENDORS_ENABLED=true\n');
    final repository = _MockVendorRepository();
    GetIt.I.registerLazySingleton<VendorRepository>(() => repository);

    when(
      () => repository.list(
        page: any(named: 'page'),
        pageSize: any(named: 'pageSize'),
        query: any(named: 'query'),
        isActive: any(named: 'isActive'),
      ),
    ).thenAnswer(
      (_) async => PaginatedResult<Vendor>(
        items: const [],
        page: 1,
        pageSize: 20,
        total: 0,
      ),
    );

    await tester.pumpWidget(
      _buildApp(VendorPage(routeUri: Uri(path: '/masters/vendors'))),
    );
    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 {
    dotenv.testLoad(fileInput: 'FEATURE_VENDORS_ENABLED=true\n');
    final repository = _MockVendorRepository();
    GetIt.I.registerLazySingleton<VendorRepository>(() => repository);

    var listCallCount = 0;
    when(
      () => repository.list(
        page: any(named: 'page'),
        pageSize: any(named: 'pageSize'),
        query: any(named: 'query'),
        isActive: any(named: 'isActive'),
      ),
    ).thenAnswer((_) async {
      listCallCount += 1;
      if (listCallCount == 1) {
        return PaginatedResult<Vendor>(
          items: const [],
          page: 1,
          pageSize: 20,
          total: 0,
        );
      }
      return PaginatedResult<Vendor>(
        items: [Vendor(id: 99, vendorCode: 'NV-001', vendorName: '신규벤더')],
        page: 1,
        pageSize: 20,
        total: 1,
      );
    });

    VendorInput? capturedInput;
    when(() => repository.create(any())).thenAnswer((invocation) async {
      capturedInput = invocation.positionalArguments.first as VendorInput;
      return Vendor(
        id: 99,
        vendorCode: capturedInput!.vendorCode,
        vendorName: capturedInput!.vendorName,
      );
    });

    await tester.pumpWidget(
      _buildApp(VendorPage(routeUri: Uri(path: '/masters/vendors'))),
    );
    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), 'NV-001');
    await tester.enterText(editableTexts.at(1), '신규벤더');

    await tester.tapShadButton('등록');
    await tester.pumpAndSettle();

    expect(find.byType(Dialog), findsNothing);
    verify(() => repository.create(any())).called(1);
    expect(capturedInput, isNotNull);
    expect(capturedInput?.vendorCode, 'NV-001');
    expect(find.text('NV-001'), findsOneWidget);
  });

  testWidgets('좁은 폭에서도 오버플로 없이 렌더링', (tester) async {
    dotenv.testLoad(fileInput: 'FEATURE_VENDORS_ENABLED=true\n');
    final repository = _MockVendorRepository();
    GetIt.I.registerLazySingleton<VendorRepository>(() => repository);

    when(
      () => repository.list(
        page: any(named: 'page'),
        pageSize: any(named: 'pageSize'),
        query: any(named: 'query'),
        isActive: any(named: 'isActive'),
      ),
    ).thenAnswer(
      (_) async => PaginatedResult<Vendor>(
        items: [Vendor(id: 1, vendorCode: 'V-SMALL', vendorName: '좁은 화면 벤더')],
        page: 1,
        pageSize: 20,
        total: 1,
      ),
    );

    await tester.pumpWidget(
      _buildApp(
        Center(
          child: SizedBox(
            width: 320,
            child: VendorPage(routeUri: Uri(path: '/masters/vendors')),
          ),
        ),
      ),
    );
    await tester.pumpAndSettle();

    expect(tester.takeException(), isNull);
  });
}
