import { existsSync, lstatSync, readFileSync, readdirSync } from 'node:fs';
import { dirname, join, relative, sep } from 'node:path';
import { fileURLToPath } from 'node:url';

const root = dirname(dirname(fileURLToPath(import.meta.url)));
const read = rel => readFileSync(join(root, rel), 'utf8');
const failures = [];
const expect = (text, marker, label = marker) => { if (!text.includes(marker)) failures.push(`Fehlt: ${label}`); };
const forbid = (text, marker, label = marker) => { if (text.includes(marker)) failures.push(`Darf nicht enthalten sein: ${label}`); };

const pkg = JSON.parse(read('package.json'));
const lock = JSON.parse(read('package-lock.json'));
const manifest = JSON.parse(read('update-manifest.json'));
const html = read('public/index.html');
const app = read('public/app.js');
const bootstrap = read('bootstrap.mjs');
const configStore = read('lib/config-store.mjs');
const runtimePaths = read('lib/runtime-paths.mjs');
const setupPs = read('setup.ps1');
const setupGui = read('setup-gui.ps1');
const setupBat = read('setup.bat');
const setupSh = read('setup.sh');
const compose = read('compose.yaml');
const composeVps = read('compose.vps.yaml');
const caddy = read('deploy/Caddyfile');
const env = read('.env.example');
const gitignore = read('.gitignore');
const ci = read('.github/workflows/ci.yml');
const release = read('.github/workflows/release.yml');
const gitDeploy = read('scripts/github-deploy.ps1');
const gitSafety = read('tools/verify-git-safety.mjs');
const gitSafetyRegression = read('tools/verify-git-safety-regression.mjs');
const releaseBuilder = read('tools/build-release.mjs');
const installerShellGate = read('tools/verify-installer-shell.sh');
const backupScript = read('scripts/docker-backup.sh');
const restoreScript = read('scripts/docker-restore.sh');
const gitStaging = read('tools/prepare-git-staging.mjs');
const gitStagingRegression = read('tools/verify-git-staging.mjs');
const architectureGate = read('tools/verify-platform-architecture-1.41.2.mjs');
const themeGate = read('tools/verify-theme-manager-1.41.2.mjs');
const securityGate = read('tools/verify-security-foundation-1.41.2.mjs');
const identityGate = read('tools/verify-identity-settings-1.41.2.mjs');
const catalogGate = read('tools/verify-catalog-media-1.41.2.mjs');
const moduleGate = read('tools/verify-module-manager-1.41.2.mjs');
const esmExportGate = read('tools/verify-esm-export-contracts.mjs');
const sourceBoundaryGate = read('tools/verify-source-boundaries-1.41.2.mjs');
const ignoreBoundaryGate = read('tools/verify-git-ignore-boundaries-1.41.2.mjs');
const fluxHotfixGate = read('tools/verify-flux-loop-hotfix-1.41.2.mjs');
const capabilityGraphGate = read('tools/verify-capability-graph-1.41.2.mjs');
const coolifyGate = read('tools/verify-coolify-deployment-1.41.2.mjs');
const initialModulesGate = read('tools/verify-initial-disabled-modules-1.41.2.mjs');
const deploymentModule = read('app/modules/deployments/service.mjs');
const coolifyEnv = read('deploy/coolify.env.example');
const moduleManager = read('public/modules/module-manager/module-manager.js');
const moduleService = read('app/modules/module-manager/service.mjs');
const themeManager = read('public/modules/theme-manager/theme-manager.js');
const tokenSource = read('public/design-system/tokens/source.json');
const tokenCss = read('public/design-system/tokens.css');
const moduleSchema = read('app/contracts/module.schema.json');
const boundaries = read('app/architecture-boundaries.json');

for (const [label, value] of [
  ['package.json', pkg.version], ['package-lock.json', lock.version],
  ['package-lock root', lock.packages?.['']?.version], ['update-manifest', manifest.version],
]) if (value !== '1.41.2') failures.push(`${label}-Version ist ${value}`);

for (const marker of ['content="1.41.2"', 'style.css?v=1.41.2', 'app.js?v=1.41.2']) expect(html, marker, `UI-Build ${marker}`);
if (!app.startsWith("const VENDOO_UI_BUILD = '1.41.2';")) failures.push('UI-Build ist nicht 1.41.2');
for (const marker of ['VENDOO_CONFIG_PATH', "await import('./server.mjs')", 'override: true']) expect(bootstrap, marker, `Bootstrap ${marker}`);
for (const marker of ['CONFIG_PATH', 'writeRuntimeConfig', 'updateRuntimeConfig', 'mode: 0o600']) expect(configStore, marker, `Konfigurationsspeicher ${marker}`);
for (const marker of ['VENDOO_CONFIG_PATH', 'runtime_config: CONFIG_PATH', 'VENDOO_MODULES_DIR', 'module_state: MODULE_STATE_PATH']) expect(runtimePaths, marker, `Runtime-Pfade ${marker}`);
for (const marker of ["setSecret('LOCAL_IMAGE_TOKEN', token, { source: 'token-regeneration' })", 'runtime_config_path: CONFIG_PATH']) expect(read('server.mjs'), marker, `Server-Konfiguration ${marker}`);
for (const marker of ['readRuntimeConfig()', 'writeRuntimeConfig(envContent)', 'ALL_FIELDS', 'Unbekanntes Einstellungsfeld']) expect(read('app/modules/settings/service.mjs'), marker, `Settings-Modul ${marker}`);
forbid(read('server.mjs'), "join(__dirname, '.env')", 'direktes Schreiben in schreibgeschütztes App-.env');

for (const marker of ["$Version = '1.41.2'", '?build=1.41.2', "'install-local'", "'install-docker'", 'Configure-VendooConsole', 'Initialize-VendooEnvironment']) expect(setupPs, marker, `Windows-Setup ${marker}`);
for (const marker of ["foreach ($name in @('uploads','config','modules'))", "module-state\\modules-state.json", 'Modulpakete und Modulzustand wiederhergestellt']) expect(setupPs, marker, `Windows-Modul-Backup ${marker}`);

for (const marker of [
  'Vendoo 1.41.2 – Installation', 'Lokal auf diesem Windows-PC', 'Docker Desktop auf diesem Windows-PC',
  'Set-Configuration', 'VENDOO_SETUP_TOKEN', 'Clipboard', 'AI- und Marktplatz-Schlüssel werden später',
]) expect(setupGui, marker, `Windows-GUI ${marker}`);
forbid(setupGui, 'PlaceholderText', 'nicht mit Windows PowerShell 5.1 kompatible PlaceholderText-Eigenschaft');
for (const marker of ['setup-gui.ps1', '-STA', 'Parser]::ParseFile']) expect(setupBat, marker, `setup.bat ${marker}`);

for (const marker of [
  'Zero-Edit Deployment Assistant', 'configure_wizard', 'VPS / öffentlicher Server mit automatischem HTTPS',
  'VENDOO_DOMAIN', 'compose.vps.yaml', 'Caddy übernimmt HTTPS automatisch', 'keine Datei musste manuell bearbeitet werden',
  'Aktualisieren (mit Sicherheitsbackup)', 'docker-backup.sh',
]) expect(setupSh, marker, `Linux-Assistent ${marker}`);

for (const marker of ['VENDOO_CONFIG_PATH: /app/data/config/vendoo.env', 'vendoo_config:/app/data/config', 'vendoo_modules:/app/data/modules']) expect(compose, marker, `Basis-Compose-Konfiguration ${marker}`);
for (const marker of ['caddy:2-alpine', '80:80', '443:443', './deploy/Caddyfile', 'condition: service_healthy', 'read_only: true', 'vendoo_config:/app/data/config', 'vendoo_modules:/app/data/modules']) expect(composeVps, marker, `VPS-Compose ${marker}`);
for (const marker of ['{$VENDOO_DOMAIN}', 'reverse_proxy vendoo:8124', 'Strict-Transport-Security']) expect(caddy, marker, `Caddy ${marker}`);
for (const marker of ['VENDOO_DOMAIN=', 'VENDOO_SETUP_TOKEN=', 'VENDOO_COOKIE_SECURE=', 'LOCAL_IMAGE_ENABLED=false']) expect(env, marker, `.env.example ${marker}`);

for (const marker of ['name: Vendoo CI', 'npm ci', 'npm run verify:git', 'npm run verify:git-regression', 'npm run verify:git-staging', 'npm run verify:ignore-boundaries', 'npm run verify:source-boundaries', 'npm run verify:esm-exports', 'npm run verify:flux-loop', 'npm run verify:capabilities', 'npm run verify:coolify', 'npm run verify:initial-modules', 'npm run verify:architecture', 'npm run verify:themes', 'npm run verify:modules', 'npm run verify:deployment', 'npm run verify:config', 'npm run verify:installer-shell', 'docker build --pull', 'compose.vps.yaml']) expect(ci, marker, `CI ${marker}`);
for (const marker of ['name: Vendoo Release', 'Release-Tag gegen Paketversion prüfen', 'npm run verify:git-staging', 'npm run verify:ignore-boundaries', 'npm run verify:source-boundaries', 'npm run verify:esm-exports', 'npm run verify:flux-loop', 'npm run verify:capabilities', 'npm run verify:coolify', 'npm run verify:initial-modules', 'npm run verify:architecture', 'npm run verify:themes', 'npm run verify:modules', 'npm run verify:config', 'npm run verify:installer-shell', 'release-output', 'gh release upload', 'ghcr.io', 'docker/build-push-action@v6', 'actions/attest@v4', 'attestations: write', 'id-token: write', 'steps.push.outputs.digest', 'linux/amd64,linux/arm64']) expect(release, marker, `Release-Workflow ${marker}`);
for (const marker of ['release/1.41.2-git-ignore-boundary-hotfix', 'verify-git-safety.mjs', 'prepare-git-staging.mjs', 'RedirectStandardOutput', 'github-deploy-safety-report.txt', 'Zum Fortfahren PUSH eingeben', 'vendoo/pull/18']) expect(gitDeploy, marker, `GitHub-Deploy ${marker}`);
for (const marker of ['fileURLToPath', 'kompletten Arbeitsbaum', 'forbiddenPathPatterns', 'secretPatterns', 'Git-Sicherheitsgate erfolgreich']) expect(gitSafety, marker, `Git-Sicherheitsgate ${marker}`);
for (const marker of ['unversioniert', '.env.local', 'untracked-secret.txt', 'Git-Sicherheitsgate-Regressionstest erfolgreich']) expect(gitSafetyRegression, marker, `Git-Sicherheitsgate-Regression ${marker}`);
for (const marker of ['prepareGitStaging', 'shouldSkipStagingEntry', 'allowedEnvTemplates', 'skippedTopLevelDirs', 'operations', 'updates', 'Ziel ist kein geklontes Git-Repository']) expect(gitStaging, marker, `Git-Staging ${marker}`);
for (const marker of ['.env.local', 'operations/staging/job.json', 'updates/backups/slice22_1_20260707-194953/setup.ps1', '.git/marker', 'Git-Staging-Regressionstest erfolgreich']) expect(gitStagingRegression, marker, `Git-Staging-Regression ${marker}`);
for (const marker of ['release-output', 'FILE_CHECKSUMS_SHA256.txt', 'createHash', 'shouldSkipStagingEntry']) expect(releaseBuilder, marker, `Release-Builder ${marker}`);
for (const marker of ['run_mode docker', 'run_mode nas', 'run_mode vps', 'VENDOO_SETUP_TOKEN', 'stat -c']) expect(installerShellGate, marker, `Shell-Installer-Gate ${marker}`);
for (const marker of ['db uploads backups operations logs config modules', 'vendoo-data.tar.gz']) expect(backupScript, marker, `Docker-Backup ${marker}`);
for (const marker of ['db uploads backups operations logs config modules', '--confirm', 'docker-backup.sh']) expect(restoreScript, marker, `Docker-Restore ${marker}`);

for (const marker of ['.env', 'runtime/', 'modules/', 'updates/', '/Archiv/', '/archive/', '/archives/', 'local-ai/comfyui/', '.vendoo-install-mode', 'release-output/']) expect(gitignore, marker, `.gitignore ${marker}`);

for (const marker of ['createPlatformKernel', "id: 'platform.status.read'", "policy: 'platform.security-admin'", 'await platformKernel.stop()']) expect(read('server.mjs'), marker, `Platform-Kernel ${marker}`);
for (const marker of ['Capability-Graph-Gate 1.41.2 erfolgreich', 'settings.configuration', 'validateGraph']) expect(capabilityGraphGate, marker, `Capability-Graph-Gate ${marker}`);
for (const marker of ['Platform-Architecture-Gate 1.41.2 erfolgreich', 'MODULE_DEPENDENCY_CYCLE', 'MODULE_DISABLED']) expect(architectureGate, marker, `Architektur-Gate ${marker}`);
for (const marker of ['Theme-Manager-Gate 1.41.2 erfolgreich', 'THEME_VALUE_INVALID', 'theme_profiles', 'user_theme_preferences']) expect(themeGate, marker, `Theme-Gate ${marker}`);
for (const marker of ['Security-Foundation-Gate 1.41.2 erfolgreich', 'SECRET_VALUE_INVALID', 'requestContextMiddleware']) expect(securityGate, marker, `Security-Gate ${marker}`);
for (const marker of ['Identity-&-Settings-Gate 1.41.2 erfolgreich', 'SESSION_NOT_OWNED', 'Unbekanntes Einstellungsfeld']) expect(identityGate, marker, `Identity-/Settings-Gate ${marker}`);
for (const marker of ['Catalog-&-Media-Gate 1.41.2 erfolgreich', 'LISTING_TRASH_NOT_FOUND', 'protectedPaths']) expect(catalogGate, marker, `Catalog-/Media-Gate ${marker}`);
for (const marker of ['Module-Manager-Gate 1.41.2 erfolgreich', 'MODULE_PROTECTED', 'MODULE_NOT_ACTIVATABLE', '.vmod-Import/Export']) expect(moduleGate, marker, `Modulmanager-Gate ${marker}`);
for (const marker of ['Git-Ignore-Grenzprüfung 1.41.2 erfolgreich', '/modules/', 'app/modules/sessions']) expect(ignoreBoundaryGate, marker, `Git-Ignore-Gate ${marker}`);
for (const marker of ['Source-Root-Grenzprüfung 1.41.2 erfolgreich', 'Archivstände ausgeschlossen', 'Produktive Pflichtdatei fehlt']) expect(sourceBoundaryGate, marker, `Source-Root-Gate ${marker}`);
for (const marker of ['ESM-Export-Vertragsprüfung erfolgreich', 'productionSourceFiles', 'sourceDirectories']) expect(esmExportGate, marker, `ESM-Export-Gate ${marker}`);
for (const marker of ['FLUX-Loop-Hotfix-Gate 1.41.2 erfolgreich', 'stopFluxPromptJobLoop', 'verify:esm-exports']) expect(fluxHotfixGate, marker, `FLUX-Hotfix-Gate ${marker}`);

for (const marker of ['Coolify-Deployment-Gate 1.41.2 erfolgreich', 'COOLIFY_DEPLOY_WEBHOOK_URL', 'docker_socket_access']) expect(coolifyGate, marker, `Coolify-Gate ${marker}`);
for (const marker of ['Initial-Module-Gate 1.41.2 erfolgreich', 'VENDOO_INITIAL_DISABLED_MODULES', 'vendoo.flux-studio']) expect(initialModulesGate, marker, `Initial-Module-Gate ${marker}`);
for (const marker of ['DEPLOYMENT_CONFIRMATION_REQUIRED', 'COOLIFY_DEPLOY_WEBHOOK_URL', 'VENDOO_BACKUP_BEFORE_DEPLOY', 'docker_socket_access: false']) expect(deploymentModule, marker, `Deployment-Modul ${marker}`);
for (const marker of ['PUBLIC_BASE_URL=https://vendoo.flatlined.de', 'VENDOO_INITIAL_DISABLED_MODULES=vendoo.flux-studio', 'VENDOO_DEPLOY_PROVIDER=none']) expect(coolifyEnv, marker, `Coolify-Env ${marker}`);
forbid(read('Dockerfile'), '/var/run/docker.sock', 'Docker-Socket im Dockerfile');

for (const marker of ['/api/admin/modules', 'dataset.moduleAction', 'module-manager-file', 'Deklarative Module sind aktivierbar']) expect(moduleManager, marker, `Modulmanager UI ${marker}`);
for (const marker of ['PROTECTED_MODULE_IDS', 'builtin-reference', 'MODULE_DISABLE_BEFORE_REMOVE', 'MODULE_EXTENSION_HOST_UNAVAILABLE']) expect(moduleService, marker, `Modulmanager Service ${marker}`);
for (const marker of ['/api/themes/preference', '/api/themes/system-default', 'previewTheme']) expect(themeManager, marker, `Theme Manager ${marker}`);
for (const marker of ['contractVersion', 'color.brand', 'density.controlHeight', 'motion.normal']) expect(tokenSource, marker, `Tokenquelle ${marker}`);
for (const marker of [':root {', '[data-theme="dark"]', '[data-theme="contrast"]', '--vd-brand:']) expect(tokenCss, marker, `Token-CSS ${marker}`);
for (const marker of ['Vendoo Module Manifest', 'legacy-bridge', 'extension-host']) expect(moduleSchema, marker, `Modulschema ${marker}`);
for (const marker of ['modular-monolith', 'denyImplicitRoutes', 'thirdPartyExtensionsInMainProcess', 'strangler']) expect(boundaries, marker, `Architekturgrenzen ${marker}`);
for (const required of ['app/kernel/platform-kernel.mjs', 'app/kernel/module-registry.mjs', 'app/kernel/route-registry.mjs', 'app/kernel/policy-engine.mjs', 'app/kernel/input-schema.mjs', 'app/core/themes/theme-contract.mjs', 'app/core/security/secret-contract.mjs', 'app/modules/security/index.mjs', 'lib/secret-store.mjs', 'lib/structured-logger.mjs', 'public/design-system/theme-runtime.js', 'public/design-system/theme-contract.json', 'public/core/frontend-module-registry.js', 'public/core/safe-dom.js', 'public/core/api-client.js', 'docs/architecture/MODULE_SYSTEM_1_35_0.md', 'docs/architecture/DESIGN_SYSTEM_1_35_0.md', 'docs/architecture/SECURITY_ARCHITECTURE_1_35_0.md', 'docs/architecture/THEME_MANAGER_1_36_0.md', 'docs/architecture/MODULE_MANAGER_1_40_0.md', 'app/core/modules/module-package-contract.mjs', 'app/core/modules/module-package-store.mjs', 'app/core/modules/module-state-store.mjs', 'app/modules/module-manager/routes.mjs', 'public/modules/module-manager/module-manager.js']) if (!existsSync(join(root, required))) failures.push(`Architektur-Pflichtdatei fehlt: ${required}`);
for (const marker of ['read_only: true', 'no-new-privileges:true', 'cap_drop:', '/readyz', 'host.docker.internal:host-gateway']) expect(compose, marker, `Basis-Compose ${marker}`);

for (const required of [
  '.github/workflows/ci.yml', '.github/workflows/release.yml', '.github/dependabot.yml', '.github/CODEOWNERS',
  'GitHub-Deploy-Assistent.bat', 'scripts/github-deploy.ps1', 'scripts/github-deploy.sh',
  'setup-gui.ps1', 'bootstrap.mjs', 'lib/config-store.mjs', 'compose.vps.yaml', 'deploy/Caddyfile', 'tools/verify-git-safety.mjs', 'tools/verify-git-safety-regression.mjs', 'tools/prepare-git-staging.mjs', 'tools/verify-git-staging.mjs', 'tools/verify-git-ignore-boundaries-1.41.2.mjs', 'tools/verify-installer-shell.sh', 'tools/build-release.mjs', 'tools/verify-source-boundaries-1.41.2.mjs', 'tools/verify-esm-export-contracts.mjs', 'tools/verify-flux-loop-hotfix-1.41.2.mjs',
]) if (!existsSync(join(root, required))) failures.push(`Pflichtdatei fehlt: ${required}`);

function walk(dir, out = []) {
  for (const name of readdirSync(dir)) {
    if (['node_modules', 'release-output', '.git', 'archiv', 'archive', 'archives'].includes(name.toLowerCase())) continue;
    const abs = join(dir, name);
    const rel = relative(root, abs).split(sep).join('/');
    const stat = lstatSync(abs);
    if (stat.isDirectory()) walk(abs, out); else out.push(rel);
  }
  return out;
}
const files = walk(root);
const forbiddenRuntime = files.filter(rel =>
  rel === '.env' || rel === '.vendoo-install-mode' ||
  /(^|\/)(runtime|node_modules|uploads|backups|logs|updates)(\/|$)/i.test(rel) || /^modules\//i.test(rel) ||
  /^db\/.*\.(db|sqlite|sqlite3)(-wal|-shm)?$/i.test(rel) ||
  /^local-ai\/(comfyui|downloads|extract-temp)\//i.test(rel)
);
if (forbiddenRuntime.length) failures.push(`Verbotene Laufzeitdaten im Paket: ${forbiddenRuntime.slice(0, 10).join(', ')}`);

forbid(read('README.md'), '.env.example` nach `.env` kopieren', 'alte manuelle .env-Anweisung im README');

if (failures.length) {
  console.error(`Deployment-Gate 1.41.2 fehlgeschlagen (${failures.length}):`);
  failures.forEach(item => console.error(`- ${item}`));
  process.exit(1);
}
console.log('Deployment-Gate 1.41.2 erfolgreich: Git-Ignore-/Source-Root-Hotfix, Capability-Graph-Hotfix, FLUX-Lifecycle, ESM-Exportverträge, 15 native Module, sicherer Modulmanager, Zero-Edit-Installer, CI und Release-Workflow geprüft.');
