import { copyFileSync } from 'node:fs';
import { join } from 'node:path';
import type { SmokeExpectation } from './package-install-smoke-contract';
import {
  assertNoFatalOutput,
  parseEvidence,
  runCommand,
} from './package-install-smoke-runner-common';
import {
  pushCommandLog,
  type SmokeWorkspace,
} from './package-install-smoke-workspace-lib';

export type SmokeGateStep = {
  label: 'pre-commit' | 'pre-push' | 'ci';
  command: string;
  args: string[];
  evidenceFile: string;
  stage: 'PRE_COMMIT' | 'PRE_PUSH' | 'CI';
};

export const runGateStep = (
  workspace: SmokeWorkspace,
  step: SmokeGateStep,
  expectation: SmokeExpectation
): { outcome: string; exitCode: number } => {
  const gateEnv: NodeJS.ProcessEnv = {
    PUMUKI_DISABLE_SYSTEM_NOTIFICATIONS: '1',
    PUMUKI_SYSTEM_NOTIFICATIONS: '0',
    PUMUKI_NOTIFICATIONS: '0',
    PUMUKI_SDD_BYPASS: '1',
    ...(step.label === 'ci' ? { GITHUB_BASE_REF: 'main' } : {}),
  };

  const result = runCommand({
    cwd: workspace.consumerRepo,
    executable: step.command,
    args: step.args,
    env: gateEnv,
  });

  pushCommandLog(workspace.commandLog, result);
  assertNoFatalOutput(result, `pumuki-${step.label}`);
  if (result.exitCode !== expectation.expectedExitCode) {
    throw new Error(
      `pumuki-${step.label} expected exit code ${expectation.expectedExitCode}, got ${result.exitCode}`
    );
  }

  copyFileSync(
    join(workspace.consumerRepo, '.ai_evidence.json'),
    join(workspace.reportRoot, step.evidenceFile)
  );

  const evidence = parseEvidence(join(workspace.reportRoot, step.evidenceFile));
  if (evidence.version !== '2.1' || evidence.stage !== step.stage) {
    throw new Error(
      `Invalid ${step.stage} evidence metadata: version=${evidence.version} stage=${evidence.stage}`
    );
  }

  if (evidence.outcome !== expectation.expectedOutcome) {
    throw new Error(
      `Unexpected ${step.stage} evidence outcome for mode: ${evidence.outcome}`
    );
  }

  return {
    outcome: evidence.outcome,
    exitCode: result.exitCode,
  };
};
