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.39.0.mjs');
const themeGate = read('tools/verify-theme-manager-1.39.0.mjs');
const securityGate = read('tools/verify-security-foundation-1.39.0.mjs');
const identityGate = read('tools/verify-identity-settings-1.39.0.mjs');
const catalogGate = read('tools/verify-catalog-media-1.39.0.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.39.0') failures.push(`${label}-Version ist ${value}`);

for (const marker of ['content="1.39.0"', 'style.css?v=1.39.0', 'app.js?v=1.39.0']) expect(html, marker, `UI-Build ${marker}`);
if (!app.startsWith("const VENDOO_UI_BUILD = '1.39.0';")) failures.push('UI-Build ist nicht 1.39.0');
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']) 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.39.0'", '?build=1.39.0', "'install-local'", "'install-docker'", 'Configure-VendooConsole', 'Initialize-VendooEnvironment']) expect(setupPs, marker, `Windows-Setup ${marker}`);

for (const marker of [
  'Vendoo 1.39.0 – 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']) 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']) 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:architecture', 'npm run verify:themes', '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:architecture', 'npm run verify:themes', '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.39.0-catalog-media', 'verify-git-safety.mjs', 'prepare-git-staging.mjs', 'RedirectStandardOutput', 'github-deploy-safety-report.txt', 'Zum Fortfahren PUSH eingeben', 'vendoo/pull/12']) 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', 'vendoo-data.tar.gz']) expect(backupScript, marker, `Docker-Backup ${marker}`);
for (const marker of ['db uploads backups operations logs config', '--confirm', 'docker-backup.sh']) expect(restoreScript, marker, `Docker-Restore ${marker}`);

for (const marker of ['.env', 'runtime/', 'updates/', '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 ['Platform-Architecture-Gate 1.39.0 erfolgreich', 'MODULE_DEPENDENCY_CYCLE', 'ROUTE_POLICY_REQUIRED']) expect(architectureGate, marker, `Architektur-Gate ${marker}`);
for (const marker of ['Theme-Manager-Gate 1.39.0 erfolgreich', 'THEME_VALUE_INVALID', 'theme_profiles', 'user_theme_preferences']) expect(themeGate, marker, `Theme-Gate ${marker}`);
for (const marker of ['Security-Foundation-Gate 1.39.0 erfolgreich', 'SECRET_VALUE_INVALID', 'requestContextMiddleware']) expect(securityGate, marker, `Security-Gate ${marker}`);
for (const marker of ['Identity-&-Settings-Gate 1.39.0 erfolgreich', 'SESSION_NOT_OWNED', 'Unbekanntes Einstellungsfeld']) expect(identityGate, marker, `Identity-/Settings-Gate ${marker}`);
for (const marker of ['Catalog-&-Media-Gate 1.39.0 erfolgreich', 'LISTING_TRASH_NOT_FOUND', 'protectedPaths']) expect(catalogGate, marker, `Catalog-/Media-Gate ${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']) 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-installer-shell.sh', 'tools/build-release.mjs',
]) if (!existsSync(join(root, required))) failures.push(`Pflichtdatei fehlt: ${required}`);

function walk(dir, out = []) {
  for (const name of readdirSync(dir)) {
    if (name === 'node_modules' || name === 'release-output' || name === '.git') 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) ||
  /^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.39.0 fehlgeschlagen (${failures.length}):`);
  failures.forEach(item => console.error(`- ${item}`));
  process.exit(1);
}
console.log('Deployment-Gate 1.39.0 erfolgreich: native Auth-, Benutzer-, Sitzungs-, Settings-, Theme-, Security-, Listings-, Inventory- und Media-Module, Zero-Edit-Installer, CI und Release-Workflow geprüft.');
