import { existsSync, readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { readAndValidateManifest, REQUIRED_RELEASE_FILES } from './release-manifest-lib.mjs';

const root = resolve(import.meta.dirname, '..');
const failures = [];
const required = [
  'UPDATE_VENDOO.bat',
  '.gitattributes',
  '.editorconfig',
  'scripts/update-vendoo-gui.ps1',
  'scripts/updater/Vendoo.Updater.Preflight.ps1',
  'scripts/updater/Vendoo.Updater.UI.ps1',
  'scripts/updater/Vendoo.Updater.Host.ps1',
  'scripts/updater/Vendoo.Updater.Worker.ps1',
  'release-manifest.json',
  'tools/release-manifest-lib.mjs',
  'tools/generate-release-manifest.mjs',
  'tools/apply-release-manifest.mjs',
  'tools/verify-release-manifest-staging-3.0.mjs',
  'docs/PRODUCTION_UPDATER_3_2.md',
  'db/schema.sql',
];
for (const file of required) if (!existsSync(resolve(root, file))) failures.push(`Pflichtdatei fehlt: ${file}`);

const batPath = resolve(root, 'UPDATE_VENDOO.bat');
const bat = readFileSync(batPath);
const batText = bat.toString('ascii');
if (bat.length < 16) failures.push('UPDATE_VENDOO.bat ist unerwartet leer.');
if (bat[0] === 0xef && bat[1] === 0xbb && bat[2] === 0xbf) failures.push('UPDATE_VENDOO.bat darf keine UTF-8-BOM besitzen.');
for (let i = 0; i < bat.length; i += 1) {
  if (bat[i] > 0x7f) { failures.push(`UPDATE_VENDOO.bat ist nicht reines ASCII (Byte ${i}).`); break; }
  if (bat[i] === 0x0a && (i === 0 || bat[i - 1] !== 0x0d)) { failures.push(`UPDATE_VENDOO.bat enthält LF ohne CR an Byte ${i}.`); break; }
  if (bat[i] === 0x0d && (i + 1 >= bat.length || bat[i + 1] !== 0x0a)) { failures.push(`UPDATE_VENDOO.bat enthält CR ohne LF an Byte ${i}.`); break; }
}
if (!batText.startsWith('@echo off\r\n')) failures.push('UPDATE_VENDOO.bat startet nicht exakt mit @echo off + CRLF.');
for (const needle of ['cd /d "%~dp0"', '%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', 'Vendoo.Updater.Preflight.ps1', 'update-vendoo-gui.ps1', 'pause']) {
  if (!batText.includes(needle)) failures.push(`BAT-Startvertrag fehlt: ${needle}`);
}
for (const forbidden of ['chcp ', '-PackageRoot', 'start "', 'ä', 'ö', 'ü', 'ß']) if (batText.includes(forbidden)) failures.push(`BAT enthält verbotene Regression: ${forbidden}`);

const attrs = readFileSync(resolve(root, '.gitattributes'), 'ascii');
if (!attrs.includes('*.bat text eol=crlf')) failures.push('.gitattributes erzwingt CRLF für BAT nicht.');
if (!attrs.includes('*.cmd text eol=crlf')) failures.push('.gitattributes erzwingt CRLF für CMD nicht.');

for (const rel of required.filter(file => file.endsWith('.ps1'))) {
  const bytes = readFileSync(resolve(root, rel));
  if (!(bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf)) failures.push(`${rel} besitzt keine UTF-8-BOM.`);
  const text = bytes.subarray(3).toString('utf8');
  if (rel.includes('updater/Vendoo.Updater.') && !text.includes('3.3.0')) failures.push(`${rel} enthält nicht Updater-Version 3.3.0.`);
}

const workerText = readFileSync(resolve(root, 'scripts/updater/Vendoo.Updater.Worker.ps1'), 'utf8');
for (const marker of [
  "release/$TargetVersion-production-update-v3",
  'release-manifest.json',
  'tools\\apply-release-manifest.mjs',
  'overlay-with-explicit-removals',
  'Veralteter oder anderer Updater-Sitzungsstand wird nicht übernommen.',
  'StandardOutputEncoding',
  'StandardErrorEncoding',
  'Get-ProcessFailureSummary',
  'Fehlerausgabe:',
  'Letzte Standardausgabe:',
  'Coolify Auto Deploy',
  '/readyz',
]) if (!workerText.includes(marker)) failures.push(`Updater-3.3-Vertrag fehlt: ${marker}`);
for (const forbidden of [
  "tools\\prepare-git-staging.mjs'),$PackageRoot,$CloneDir",
  'cleanDestination',
  'COOLIFY_DEPLOY_WEBHOOK_URL',
  'Request-Secret',
]) if (workerText.includes(forbidden)) failures.push(`Verbotene 2.x-Regression im Worker: ${forbidden}`);

const applyText = readFileSync(resolve(root, 'tools/apply-release-manifest.mjs'), 'utf8');
const libText = readFileSync(resolve(root, 'tools/release-manifest-lib.mjs'), 'utf8');
for (const marker of ['applyReleaseManifest', 'overlay-with-explicit-removals', 'removedFiles', 'sha256File', 'db/schema.sql', 'Zielprüfung nach Kopieren', 'CONTROL_RELEASE_FILES', 'Steuerdatei-Prüfung nach Kopieren', 'allowExtraFiles']) {
  if (!(applyText + libText).includes(marker)) failures.push(`Manifest-Release-Vertrag fehlt: ${marker}`);
}
for (const forbidden of ['cleanDestination(destination)', 'for (const name of readdirSync(destination))']) {
  if (libText.includes(forbidden)) failures.push(`Manifest-Applier darf die Baseline nicht leeren: ${forbidden}`);
}

try {
  const manifest = readAndValidateManifest(root, { allowExtraFiles: true });
  if (manifest.version !== '1.43.0') failures.push(`Release-Manifest-Version falsch: ${manifest.version}`);
  if (manifest.updaterVersion !== '3.3.0') failures.push(`Release-Manifest-Updaterversion falsch: ${manifest.updaterVersion}`);
  for (const requiredFile of REQUIRED_RELEASE_FILES) {
    if (!manifest.files.some(entry => entry.path === requiredFile)) failures.push(`Release-Manifest enthält Pflichtdatei nicht: ${requiredFile}`);
  }
} catch (error) {
  failures.push(`Release-Manifest ist ungültig: ${error.message}`);
}


const ciText = readFileSync(resolve(root, '.github/workflows/ci.yml'), 'utf8');
for (const marker of ['windows-release-contract', 'runs-on: windows-latest', 'npm run verify:all', 'verify-powershell-parser.ps1']) {
  if (!ciText.includes(marker)) failures.push(`Windows-CI-Vertrag fehlt: ${marker}`);
}

if (!ciText.includes('Geführte Shell-Installer simulieren') || !ciText.includes('run: npm run verify:installer-shell')) {
  failures.push('Linux-CI-Vertrag für den funktionalen Installer-Shell-Test fehlt.');
}
const releaseWorkflow = readFileSync(resolve(root, '.github/workflows/release.yml'), 'utf8');
for (const marker of ['npm run verify:all', 'generate-release-manifest.mjs', 'git diff --exit-code -- release-manifest.json', 'Manifestbasiertes Release-Staging']) {
  if (!releaseWorkflow.includes(marker)) failures.push(`Release-Workflow-Vertrag fehlt: ${marker}`);
}
const buildRelease = readFileSync(resolve(root, 'tools/build-release.mjs'), 'utf8');
for (const marker of ['generateReleaseManifest', 'readAndValidateManifest', 'manifest.files', 'Manifestbasiertes Release-Staging']) {
  if (!buildRelease.includes(marker)) failures.push(`Manifestbasierter Release-Builder fehlt: ${marker}`);
}
if (buildRelease.includes('shouldSkipStagingEntry')) failures.push('Release-Builder verwendet weiterhin die alte Ausschlusslisten-Kopie.');

const installerWrapper = readFileSync(resolve(root, 'tools/verify-installer-shell.mjs'), 'utf8');
const installerShell = readFileSync(resolve(root, 'tools/verify-installer-shell.sh'), 'utf8');
for (const requiredMarker of ['VENDOO_INSTALLER_SHELL_HOST', 'VENDOO_TEST_WINDOWS_SHELL', "process.platform === 'win32'", "['-n', script]", 'verpflichtenden Linux-CI-Gate', 'Shell-Fehlerausgabe:', 'Shell-Standardausgabe:']) {
  if (!installerWrapper.includes(requiredMarker)) failures.push(`Installer-Wrapper-Vertrag fehlt: ${requiredMarker}`);
}
for (const requiredMarker of ['MINGW*|MSYS*|CYGWIN*', 'POSIX-Modus 0600', 'assert_env_permissions', 'show_file', '--exclude=.git']) {
  if (!installerShell.includes(requiredMarker)) failures.push(`Installer-Shell-Vertrag fehlt: ${requiredMarker}`);
}
if (!installerShell.includes("mode=$(stat -c '%a'")) failures.push('Linux/NAS/VPS-Rechteprüfung auf Modus 600 fehlt.');

const packageJson = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'));
if (packageJson.scripts?.['verify:release-manifest'] !== 'node tools/verify-release-manifest-staging-3.0.mjs') failures.push('verify:release-manifest ist nicht korrekt verdrahtet.');
if (!packageJson.scripts?.['verify:all']?.includes('verify:release-manifest')) failures.push('verify:release-manifest fehlt in verify:all.');
for (const name of ['verify:one-click-update', 'verify:updater-ui', 'verify:updater-hotfix']) {
  if (packageJson.scripts?.[name] !== 'node tools/verify-production-updater-3.3.mjs') failures.push(`${name} verweist nicht auf Updater-3.3-Gate.`);
}
for (const [name, command] of Object.entries(packageJson.scripts || {})) {
  if (/\bpython(?:3)?\b|\bpy(?:\.exe)?\s+-/i.test(command)) failures.push(`Aktiver npm-Script ${name} enthält eine Python-Abhängigkeit.`);
}

if (failures.length) {
  console.error(`Production-Updater-3.3-Gate fehlgeschlagen (${failures.length})`);
  for (const failure of failures) console.error(`- ${failure}`);
  process.exit(1);
}
console.log('Production-Updater-3.3-Gate erfolgreich: manifestbasiertes Overlay, SHA-256-Prüfung, bytegeprüfte Steuerdatei, explizite Löschungen, Pflichtdateien und Sitzungsgrenze geprüft.');
