import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';

import 'package:superport_v2/core/common/models/paginated_result.dart';
import 'package:superport_v2/features/masters/customer/domain/entities/customer.dart';
import 'package:superport_v2/features/masters/customer/domain/repositories/customer_repository.dart';
import 'package:superport_v2/features/masters/customer/presentation/controllers/customer_controller.dart';

class _MockCustomerRepository extends Mock implements CustomerRepository {}

class _FakeCustomerInput extends Fake implements CustomerInput {}

void main() {
  late CustomerController controller;
  late _MockCustomerRepository repository;

  final sampleCustomer = Customer(
    id: 1,
    customerCode: 'C-001',
    customerName: '슈퍼포트',
    isPartner: true,
    isGeneral: true,
  );

  PaginatedResult<Customer> createResult({List<Customer>? items}) {
    final list = items ?? [sampleCustomer];
    return PaginatedResult<Customer>(
      items: list,
      page: 1,
      pageSize: 20,
      total: list.length,
    );
  }

  setUpAll(() {
    registerFallbackValue(_FakeCustomerInput());
  });

  setUp(() {
    repository = _MockCustomerRepository();
    controller = CustomerController(repository: repository);
  });

  group('fetch', () {
    test('정상 조회 시 결과 저장', () async {
      when(
        () => repository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          query: any(named: 'query'),
          isPartner: any(named: 'isPartner'),
          isGeneral: any(named: 'isGeneral'),
          isActive: any(named: 'isActive'),
        ),
      ).thenAnswer((_) async => createResult());

      await controller.fetch();

      expect(controller.result?.items, isNotEmpty);
      verify(
        () => repository.list(
          page: 1,
          pageSize: 20,
          query: null,
          isPartner: null,
          isGeneral: null,
          isActive: null,
        ),
      ).called(1);
    });

    test('에러 발생 시 errorMessage 설정', () async {
      when(
        () => repository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          query: any(named: 'query'),
          isPartner: any(named: 'isPartner'),
          isGeneral: any(named: 'isGeneral'),
          isActive: any(named: 'isActive'),
        ),
      ).thenThrow(Exception('fail'));

      await controller.fetch();

      expect(controller.errorMessage, isNotNull);
    });
  });

  test('필터 업데이트 반영', () {
    controller.updateQuery('abc');
    controller.updateTypeFilter(CustomerTypeFilter.partner);
    controller.updateStatusFilter(CustomerStatusFilter.inactiveOnly);

    expect(controller.query, 'abc');
    expect(controller.typeFilter, CustomerTypeFilter.partner);
    expect(controller.statusFilter, CustomerStatusFilter.inactiveOnly);
  });

  group('mutations', () {
    setUp(() {
      when(
        () => repository.list(
          page: any(named: 'page'),
          pageSize: any(named: 'pageSize'),
          query: any(named: 'query'),
          isPartner: any(named: 'isPartner'),
          isGeneral: any(named: 'isGeneral'),
          isActive: any(named: 'isActive'),
        ),
      ).thenAnswer((_) async => createResult());
    });

    final input = CustomerInput(
      customerCode: 'C-001',
      customerName: '슈퍼포트',
      isPartner: true,
      isGeneral: true,
    );

    test('create 성공', () async {
      when(
        () => repository.create(any()),
      ).thenAnswer((_) async => sampleCustomer);

      final created = await controller.create(input);

      expect(created, isNotNull);
      verify(() => repository.create(any())).called(1);
    });

    test('update 성공', () async {
      when(
        () => repository.update(any(), any()),
      ).thenAnswer((_) async => sampleCustomer);

      final updated = await controller.update(1, input);

      expect(updated, isNotNull);
      verify(() => repository.update(1, any())).called(1);
    });

    test('delete 성공', () async {
      when(() => repository.delete(any())).thenAnswer((_) async {});

      final success = await controller.delete(1);

      expect(success, isTrue);
      verify(() => repository.delete(1)).called(1);
    });

    test('restore 성공', () async {
      when(
        () => repository.restore(any()),
      ).thenAnswer((_) async => sampleCustomer);

      final restored = await controller.restore(1);

      expect(restored, isNotNull);
      verify(() => repository.restore(1)).called(1);
    });
  });
}
