import assert from 'node:assert/strict';
import test from 'node:test';
import { androidRules } from './android';

test('androidRules define reglas heurísticas locked para plataforma android', () => {
  assert.equal(androidRules.length, 42);

  const ids = androidRules.map((rule) => rule.id);
  assert.deepEqual(ids, [
    'heuristics.android.thread-sleep.ast',
    'heuristics.android.globalscope.ast',
    'heuristics.android.run-blocking.ast',
    'heuristics.android.flow.livedata-state-exposure.ast',
    'heuristics.android.flow.viewmodel-flow-without-statein.ast',
    'heuristics.android.flow.sharedflow-used-as-state.ast',
    'heuristics.android.security.legacy-fingerprint-api.ast',
    'heuristics.android.architecture.custom-singleton-object.ast',
    'heuristics.android.di.hilt-injection-without-entrypoint.ast',
    'heuristics.android.concurrency.asynctask.ast',
    'heuristics.android.architecture.god-activity.ast',
    'heuristics.android.startup.application-oncreate-heavy-init.ast',
    'heuristics.android.compose.non-lazy-scrollable-collection.ast',
    'heuristics.android.compose.unstable-launched-effect-key.ast',
    'heuristics.android.compose.launched-effect-busy-loop.ast',
    'heuristics.android.observability.production-logging.ast',
    'heuristics.android.compose.modifier-background-before-padding.ast',
    'heuristics.android.accessibility.missing-content-description.ast',
    'heuristics.android.accessibility.fontscale-disabled.ast',
    'heuristics.android.compose.incomplete-material-theme.ast',
    'heuristics.android.compose.legacy-bottom-navigation.ast',
    'heuristics.android.navigation.imperative-navigation.ast',
    'heuristics.android.compose.object-creation-without-remember.ast',
    'heuristics.android.compose.state-creation-without-remember.ast',
    'heuristics.android.null-safety.force-unwrap.ast',
    'heuristics.android.security.local-properties-tracked.ast',
    'heuristics.android.persistence.shared-preferences-usage.ast',
    'heuristics.android.testing.junit4-usage.ast',
    'heuristics.android.testing.production-mock-usage.ast',
    'heuristics.android.ui.hardcoded-string.ast',
    'heuristics.android.coroutines.manual-scope-in-viewmodel.ast',
    'heuristics.android.coroutines.dispatchers-main-boundary-leak.ast',
    'heuristics.android.coroutines.hardcoded-background-dispatcher.ast',
    'heuristics.android.coroutines.with-context.ast',
    'heuristics.android.coroutines.lifecycle-scope-boundary-leak.ast',
    'heuristics.android.coroutines.supervisor-scope.ast',
    'heuristics.android.coroutines.try-catch.ast',
    'heuristics.android.solid.srp.presentation-mixed-responsibilities.ast',
    'heuristics.android.solid.ocp.discriminator-branching.ast',
    'heuristics.android.solid.dip.concrete-framework-dependency.ast',
    'heuristics.android.solid.isp.fat-interface-dependency.ast',
    'heuristics.android.solid.lsp.narrowed-precondition.ast',
  ]);

  const byId = new Map(androidRules.map((rule) => [rule.id, rule]));
  const coroutineRuleIds = [
    'heuristics.android.globalscope.ast',
    'heuristics.android.run-blocking.ast',
  ];

  for (const ruleId of coroutineRuleIds) {
    assert.equal(byId.get(ruleId)?.platform, 'android');
    assert.equal(byId.get(ruleId)?.locked, true);
  }

  assert.equal(
    byId.get('heuristics.android.thread-sleep.ast')?.then.code,
    'HEURISTICS_ANDROID_THREAD_SLEEP_AST'
  );
  assert.equal(
    byId.get('heuristics.android.globalscope.ast')?.then.code,
    'HEURISTICS_ANDROID_GLOBAL_SCOPE_AST'
  );
  assert.equal(
    byId.get('heuristics.android.run-blocking.ast')?.then.code,
    'HEURISTICS_ANDROID_RUN_BLOCKING_AST'
  );
  assert.equal(
    byId.get('heuristics.android.flow.livedata-state-exposure.ast')?.then.code,
    'HEURISTICS_ANDROID_FLOW_LIVEDATA_STATE_EXPOSURE_AST'
  );
  assert.equal(
    byId.get('heuristics.android.flow.viewmodel-flow-without-statein.ast')?.then.code,
    'HEURISTICS_ANDROID_FLOW_VIEWMODEL_FLOW_WITHOUT_STATEIN_AST'
  );
  assert.equal(
    byId.get('heuristics.android.flow.sharedflow-used-as-state.ast')?.then.code,
    'HEURISTICS_ANDROID_FLOW_SHAREDFLOW_USED_AS_STATE_AST'
  );
  assert.equal(
    byId.get('heuristics.android.security.legacy-fingerprint-api.ast')?.then.code,
    'HEURISTICS_ANDROID_SECURITY_LEGACY_FINGERPRINT_API_AST'
  );
  assert.equal(
    byId.get('heuristics.android.architecture.custom-singleton-object.ast')?.then.code,
    'HEURISTICS_ANDROID_ARCHITECTURE_CUSTOM_SINGLETON_OBJECT_AST'
  );
  assert.equal(
    byId.get('heuristics.android.di.hilt-injection-without-entrypoint.ast')?.then.code,
    'HEURISTICS_ANDROID_DI_HILT_INJECTION_WITHOUT_ENTRYPOINT_AST'
  );
  assert.equal(
    byId.get('heuristics.android.concurrency.asynctask.ast')?.then.code,
    'HEURISTICS_ANDROID_CONCURRENCY_ASYNCTASK_AST'
  );
  assert.equal(
    byId.get('heuristics.android.architecture.god-activity.ast')?.then.code,
    'HEURISTICS_ANDROID_ARCHITECTURE_GOD_ACTIVITY_AST'
  );
  assert.equal(
    byId.get('heuristics.android.startup.application-oncreate-heavy-init.ast')?.then.code,
    'HEURISTICS_ANDROID_STARTUP_APPLICATION_ONCREATE_HEAVY_INIT_AST'
  );
  assert.equal(
    byId.get('heuristics.android.compose.non-lazy-scrollable-collection.ast')?.then.code,
    'HEURISTICS_ANDROID_COMPOSE_NON_LAZY_SCROLLABLE_COLLECTION_AST'
  );
  assert.equal(
    byId.get('heuristics.android.compose.unstable-launched-effect-key.ast')?.then.code,
    'HEURISTICS_ANDROID_COMPOSE_UNSTABLE_LAUNCHED_EFFECT_KEY_AST'
  );
  assert.equal(
    byId.get('heuristics.android.compose.launched-effect-busy-loop.ast')?.then.code,
    'HEURISTICS_ANDROID_COMPOSE_LAUNCHED_EFFECT_BUSY_LOOP_AST'
  );
  assert.equal(
    byId.get('heuristics.android.observability.production-logging.ast')?.then.code,
    'HEURISTICS_ANDROID_OBSERVABILITY_PRODUCTION_LOGGING_AST'
  );
  assert.equal(
    byId.get('heuristics.android.compose.modifier-background-before-padding.ast')?.then.code,
    'HEURISTICS_ANDROID_COMPOSE_MODIFIER_BACKGROUND_BEFORE_PADDING_AST'
  );
  assert.equal(
    byId.get('heuristics.android.accessibility.missing-content-description.ast')?.then.code,
    'HEURISTICS_ANDROID_ACCESSIBILITY_MISSING_CONTENT_DESCRIPTION_AST'
  );
  assert.equal(
    byId.get('heuristics.android.accessibility.fontscale-disabled.ast')?.then.code,
    'HEURISTICS_ANDROID_ACCESSIBILITY_FONTSCALE_DISABLED_AST'
  );
  assert.equal(
    byId.get('heuristics.android.compose.incomplete-material-theme.ast')?.then.code,
    'HEURISTICS_ANDROID_COMPOSE_INCOMPLETE_MATERIAL_THEME_AST'
  );
  assert.equal(
    byId.get('heuristics.android.compose.legacy-bottom-navigation.ast')?.then.code,
    'HEURISTICS_ANDROID_COMPOSE_LEGACY_BOTTOM_NAVIGATION_AST'
  );
  assert.equal(
    byId.get('heuristics.android.navigation.imperative-navigation.ast')?.then.code,
    'HEURISTICS_ANDROID_NAVIGATION_IMPERATIVE_NAVIGATION_AST'
  );
  assert.equal(
    byId.get('heuristics.android.compose.object-creation-without-remember.ast')?.then.code,
    'HEURISTICS_ANDROID_COMPOSE_OBJECT_CREATION_WITHOUT_REMEMBER_AST'
  );
  assert.equal(
    byId.get('heuristics.android.compose.state-creation-without-remember.ast')?.then.code,
    'HEURISTICS_ANDROID_COMPOSE_STATE_CREATION_WITHOUT_REMEMBER_AST'
  );
  assert.equal(
    byId.get('heuristics.android.null-safety.force-unwrap.ast')?.then.code,
    'HEURISTICS_ANDROID_NULL_SAFETY_FORCE_UNWRAP_AST'
  );
  assert.equal(
    byId.get('heuristics.android.security.local-properties-tracked.ast')?.then.code,
    'HEURISTICS_ANDROID_SECURITY_LOCAL_PROPERTIES_TRACKED_AST'
  );
  assert.equal(
    byId.get('heuristics.android.persistence.shared-preferences-usage.ast')?.then.code,
    'HEURISTICS_ANDROID_PERSISTENCE_SHARED_PREFERENCES_USAGE_AST'
  );
  assert.equal(
    byId.get('heuristics.android.testing.junit4-usage.ast')?.then.code,
    'HEURISTICS_ANDROID_TESTING_JUNIT4_USAGE_AST'
  );
  assert.equal(
    byId.get('heuristics.android.testing.production-mock-usage.ast')?.then.code,
    'HEURISTICS_ANDROID_TESTING_PRODUCTION_MOCK_USAGE_AST'
  );
  assert.equal(
    byId.get('heuristics.android.ui.hardcoded-string.ast')?.then.code,
    'HEURISTICS_ANDROID_UI_HARDCODED_STRING_AST'
  );
  assert.equal(
    byId.get('heuristics.android.coroutines.manual-scope-in-viewmodel.ast')?.then.code,
    'HEURISTICS_ANDROID_COROUTINES_MANUAL_SCOPE_IN_VIEWMODEL_AST'
  );
  assert.equal(
    byId.get('heuristics.android.coroutines.dispatchers-main-boundary-leak.ast')?.then.code,
    'HEURISTICS_ANDROID_COROUTINES_DISPATCHERS_MAIN_BOUNDARY_LEAK_AST'
  );
  assert.equal(
    byId.get('heuristics.android.coroutines.hardcoded-background-dispatcher.ast')?.then.code,
    'HEURISTICS_ANDROID_COROUTINES_HARDCODED_BACKGROUND_DISPATCHER_AST'
  );
  assert.equal(
    byId.get('heuristics.android.coroutines.with-context.ast')?.then.code,
    'HEURISTICS_ANDROID_COROUTINES_WITH_CONTEXT_AST'
  );
  assert.equal(
    byId.get('heuristics.android.coroutines.lifecycle-scope-boundary-leak.ast')?.then.code,
    'HEURISTICS_ANDROID_COROUTINES_LIFECYCLE_SCOPE_BOUNDARY_LEAK_AST'
  );
  assert.equal(
    byId.get('heuristics.android.coroutines.supervisor-scope.ast')?.then.code,
    'HEURISTICS_ANDROID_COROUTINES_SUPERVISOR_SCOPE_AST'
  );
  assert.equal(
    byId.get('heuristics.android.coroutines.try-catch.ast')?.then.code,
    'HEURISTICS_ANDROID_COROUTINES_TRY_CATCH_AST'
  );
  assert.equal(
    byId.get('heuristics.android.solid.srp.presentation-mixed-responsibilities.ast')?.then.code,
    'HEURISTICS_ANDROID_SOLID_SRP_PRESENTATION_MIXED_RESPONSIBILITIES_AST'
  );
  assert.equal(
    byId.get('heuristics.android.solid.ocp.discriminator-branching.ast')?.then.code,
    'HEURISTICS_ANDROID_SOLID_OCP_DISCRIMINATOR_BRANCHING_AST'
  );
  assert.equal(
    byId.get('heuristics.android.solid.dip.concrete-framework-dependency.ast')?.then.code,
    'HEURISTICS_ANDROID_SOLID_DIP_CONCRETE_FRAMEWORK_DEPENDENCY_AST'
  );
  assert.equal(
    byId.get('heuristics.android.solid.isp.fat-interface-dependency.ast')?.then.code,
    'HEURISTICS_ANDROID_SOLID_ISP_FAT_INTERFACE_DEPENDENCY_AST'
  );
  assert.equal(
    byId.get('heuristics.android.solid.lsp.narrowed-precondition.ast')?.then.code,
    'HEURISTICS_ANDROID_SOLID_LSP_NARROWED_PRECONDITION_AST'
  );

  for (const rule of androidRules) {
    assert.equal(rule.platform, 'android');
    assert.equal(rule.severity, 'WARN');
    assert.equal(rule.locked, true);
    assert.equal(rule.when.kind, 'Heuristic');
    assert.equal(rule.then.kind, 'Finding');
    assert.equal(rule.when.where?.ruleId, rule.id);
  }
});
