import { readFileSync } from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import {
  DEPLOYMENT_STATES,
  ACTIVE_DEPLOYMENT_STATES,
  canTransitionDeployment,
  isActiveDeploymentState,
} from '../app/modules/deployments/state-machine.mjs';

const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const read = path => readFileSync(join(root, path), 'utf8');
const failures = [];
const assert = (condition, message) => { if (!condition) failures.push(message); };
const contains = (file, markers) => {
  const source = read(file);
  for (const marker of markers) assert(source.includes(marker), `${file}: Vertrag fehlt: ${marker}`);
  return source;
};

const pkg = JSON.parse(read('package.json'));
assert(pkg.version === '1.43.0', `package.json ist ${pkg.version}`);
assert(pkg.scripts['verify:production-operations']?.includes('verify-production-operations-1.42.0.mjs'), 'NPM-Gate für Production Operations fehlt');

assert(DEPLOYMENT_STATES.length === 10, `State-Machine hat ${DEPLOYMENT_STATES.length} statt 10 Zustände`);
for (const state of ['checking','backup_pending','backup_running','backup_verified','deploy_requested','deploy_running','health_wait','succeeded','failed','rollback_required']) {
  assert(DEPLOYMENT_STATES.includes(state), `Zustand fehlt: ${state}`);
}
for (const [from, to] of [
  ['checking','backup_pending'], ['backup_running','backup_verified'], ['backup_verified','deploy_requested'],
  ['deploy_requested','deploy_running'], ['deploy_running','health_wait'], ['health_wait','succeeded'],
  ['health_wait','rollback_required'], ['rollback_required','failed'],
]) assert(canTransitionDeployment(from, to), `Legaler Übergang blockiert: ${from} -> ${to}`);
for (const [from, to] of [['checking','succeeded'], ['succeeded','deploy_requested'], ['failed','checking'], ['rollback_required','succeeded']]) {
  assert(!canTransitionDeployment(from, to), `Illegaler Übergang erlaubt: ${from} -> ${to}`);
}
assert(ACTIVE_DEPLOYMENT_STATES.includes('rollback_required'), 'Rollbackbedarf blockiert keine Folgeaufträge');
assert(isActiveDeploymentState('health_wait') && !isActiveDeploymentState('succeeded'), 'Aktivstatus ist fehlerhaft');

contains('lib/db.mjs', [
  'CREATE TABLE IF NOT EXISTS deployment_runs', 'idempotency_key TEXT NOT NULL UNIQUE',
  'CREATE TABLE IF NOT EXISTS deployment_events', 'CREATE TABLE IF NOT EXISTS backup_verifications',
  'CREATE TABLE IF NOT EXISTS production_checks', "production-operations-1.42.0",
]);
const repository = contains('app/modules/deployments/repository.mjs', [
  'DEPLOYMENT_ALREADY_ACTIVE', 'findByIdempotencyKey', 'recordBackupVerification',
  'createProductionCheck', 'canTransitionDeployment',
]);
assert(!repository.includes('DELETE FROM deployment_runs'), 'Deployment-Repository löscht Verlauf');

const service = contains('app/modules/deployments/service.mjs', [
  "input.confirmation !== 'DEPLOY'", "input.confirmation !== 'CONFIRM'",
  'verifyStoredBackup(backup.id)', 'DEPLOYMENT_BACKUP_INVALID', 'DEPLOYMENT_TARGET_NOT_APPROVED',
  'UPDATE_CHECKSUM_MISSING', 'UPDATE_URL_INSECURE', 'deployment_status_endpoint',
  'probePublicReadiness', 'targetMatches', 'rollback_required', 'runProductionCheck',
  'VENDOO_COOLIFY_AUTO_DEPLOY', 'docker_socket_access: false',
]);
for (const forbidden of ['docker.sock', 'git pull', 'npm install', 'docker compose', 'child_process']) {
  assert(!service.toLowerCase().includes(forbidden), `Deployment-Service enthält verbotenen Selbstupdate-/Hostzugriff: ${forbidden}`);
}

contains('app/modules/deployments/routes.mjs', [
  "policy: 'updates.manage'", "csrf: true", '/api/admin/deployment/runs',
  '/api/admin/deployment/runs/:id/refresh', '/api/admin/deployment/runs/:id/confirm',
  '/api/admin/deployment/production-check', "req.get('Idempotency-Key')",
]);
contains('server.mjs', ['verifyStoredBackup,', 'getPlatformSnapshot: () => platformKernel.snapshot()', 'registerDeploymentRoutes']);
contains('public/index.html', [
  'deployment-production-overview', 'deployment-production-check', 'deployment-status-endpoint',
  'deployment-target-version', 'deployment-run-list', 'content="1.43.0"',
]);
contains('public/app.js', [
  "const VENDOO_UI_BUILD = '1.43.0';", 'deploymentStateLabel', 'data-deployment-refresh',
  'data-deployment-confirm', 'data-deployment-resolve', 'idempotency_key',
]);
contains('.env.example', [
  'COOLIFY_DEPLOYMENT_STATUS_ENDPOINT=', 'VENDOO_DEPLOY_TIMEOUT_SECONDS=900',
  'VENDOO_DEPLOY_HEALTH_POLL_SECONDS=15', 'VENDOO_COOLIFY_AUTO_DEPLOY=false',
]);
const moduleManifest = JSON.parse(read('app/modules/deployments/module.json'));
assert(moduleManifest.version === '1.1.0', `Deployment-Modulversion ist ${moduleManifest.version}`);
assert(moduleManifest.provides.includes('deployments.state-machine'), 'State-Machine-Capability fehlt');
assert(moduleManifest.provides.includes('deployments.production-checks'), 'Production-Check-Capability fehlt');

if (failures.length) {
  console.error(`Production-Operations-Gate 1.42.0 fehlgeschlagen (${failures.length}):`);
  for (const failure of failures) console.error(`- ${failure}`);
  process.exit(1);
}
console.log('Production-Operations-Gate 1.42.0 erfolgreich: State-Machine, Idempotenz, Backup-Gate, Coolify-Status, Readiness, Rollback-Sperre, Produktionscheck, API und UI geprüft.');
