import 'package:flutter_test/flutter_test.dart';

import 'package:feature_policy/feature_policy.dart';
import 'package:feature_policy/src/application/get_policy_checks.dart';
import 'package:feature_policy/src/application/policy_controller.dart';

void main() {
  group('GovernanceStatus', () {
    test('has four values', () {
      expect(GovernanceStatus.values.length, 4);
    });

    test('contains expected statuses', () {
      expect(GovernanceStatus.values, contains(GovernanceStatus.compliant));
      expect(GovernanceStatus.values, contains(GovernanceStatus.nonCompliant));
      expect(GovernanceStatus.values, contains(GovernanceStatus.needsReview));
      expect(GovernanceStatus.values, contains(GovernanceStatus.notApplicable));
    });
  });

  group('FakePolicyRepository', () {
    late FakePolicyRepository repository;

    setUp(() {
      repository = FakePolicyRepository();
    });

    test('getPolicyChecks returns eight sample checks', () async {
      final checks = await repository.getPolicyChecks();
      expect(checks.length, 8);
    });

    test('getPolicyChecks returns checks with expected IDs', () async {
      final checks = await repository.getPolicyChecks();
      final ids = checks.map((c) => c.id).toList();
      expect(ids, contains('POL-001'));
      expect(ids, contains('POL-002'));
      expect(ids, contains('POL-003'));
      expect(ids, contains('POL-004'));
      expect(ids, contains('POL-005'));
      expect(ids, contains('POL-006'));
      expect(ids, contains('POL-007'));
      expect(ids, contains('POL-008'));
    });

    test('getPolicyChecks returns checks with various statuses', () async {
      final checks = await repository.getPolicyChecks();
      final statuses = checks.map((c) => c.status).toSet();
      expect(statuses, contains(GovernanceStatus.compliant));
      expect(statuses, contains(GovernanceStatus.nonCompliant));
      expect(statuses, contains(GovernanceStatus.needsReview));
      expect(statuses, contains(GovernanceStatus.notApplicable));
    });

    test('getPolicyChecks returns checks with various categories', () async {
      final checks = await repository.getPolicyChecks();
      final categories = checks.map((c) => c.category).toSet();
      expect(categories, contains('Product Compliance'));
      expect(categories, contains('Inventory Governance'));
      expect(categories, contains('Order Operations'));
      expect(categories, contains('Customer Policy'));
      expect(categories, contains('Finance & Tax'));
    });
  });

  group('PolicyController', () {
    late FakePolicyRepository repository;
    late PolicyController controller;

    setUp(() {
      repository = FakePolicyRepository();
      controller = PolicyController(GetPolicyChecks(repository));
    });

    tearDown(() {
      controller.dispose();
    });

    test('starts with empty state', () {
      expect(controller.isLoading, false);
      expect(controller.checks, isEmpty);
      expect(controller.selectedCheck, isNull);
      expect(controller.activeCategory, isNull);
      expect(controller.searchQuery, '');
      expect(controller.error, isNull);
    });

    test('load populates checks and auto-selects first', () async {
      await controller.load();

      expect(controller.isLoading, false);
      expect(controller.checks.length, 8);
      expect(controller.selectedCheck, isNotNull);
      expect(controller.selectedCheck!.id, 'POL-001');
      expect(controller.error, isNull);
    });

    test('selectCheck updates selectedCheck', () async {
      await controller.load();

      final third = controller.checks[2];
      controller.selectCheck(third);

      expect(controller.selectedCheck!.id, third.id);
    });

    test('setCategory filters by category', () async {
      await controller.load();

      controller.setCategory('Product Compliance');
      expect(controller.checks.length, 2);
      expect(controller.checks.every((c) => c.category == 'Product Compliance'), true);
    });

    test('setCategory with null shows all checks', () async {
      await controller.load();

      controller.setCategory('Order Operations');
      expect(controller.checks.length, 2);

      controller.setCategory(null);
      expect(controller.checks.length, 8);
    });

    test('setSearchQuery filters by title', () async {
      await controller.load();

      controller.setSearchQuery('pricing');
      expect(controller.checks.length, 1);
      expect(controller.checks.first.title, 'Pricing Consistency');
    });

    test('setSearchQuery filters by summary', () async {
      await controller.load();

      controller.setSearchQuery('reorder threshold');
      expect(controller.checks.length, 1);
      expect(controller.checks.first.id, 'POL-006');
    });

    test('category and search combine', () async {
      await controller.load();

      controller.setCategory('Inventory Governance');
      controller.setSearchQuery('accuracy');
      expect(controller.checks.length, 1);
      expect(controller.checks.first.id, 'POL-002');
    });

    test('selectById selects matching check', () async {
      await controller.load();

      final found = controller.selectById('POL-005');
      expect(found, true);
      expect(controller.selectedCheck!.id, 'POL-005');
    });

    test('selectById returns false for unknown ID', () async {
      await controller.load();

      final found = controller.selectById('UNKNOWN');
      expect(found, false);
    });

    test('selection is cleared when filtered out', () async {
      await controller.load();

      // Select a Product Compliance check.
      controller.selectById('POL-001');
      expect(controller.selectedCheck, isNotNull);

      // Filter to Order Operations — the selected check should be cleared.
      controller.setCategory('Order Operations');
      expect(controller.selectedCheck, isNull);
    });
  });
}
