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

const root = dirname(fileURLToPath(new URL('../package.json', import.meta.url)));

const requiredRuntimeDependencies = [
  {
    packageFile: 'apps/server/package.json',
    dependencies: ['express'],
  },
];

const checks = [
  {
    file: 'Dockerfile.web',
    snippets: [
      'FROM node:20-alpine',
      'pnpm --filter @ftb/shared build',
      'pnpm --filter web build',
      'NEXT_PUBLIC_API_URL',
      'NEXT_API_PROXY_TARGET',
      'NEXT_PUBLIC_APP_VERSION',
      'ARG APP_VERSION=unknown',
      'COPY scripts ./scripts',
      'CMD ["pnpm", "--filter", "web", "start"]',
    ],
  },
  {
    file: 'Dockerfile.server',
    snippets: [
      'FROM node:20-alpine',
      'pnpm --filter @ftb/shared build',
      'pnpm --filter server build',
      'prisma generate',
      'APP_VERSION',
      'ARG APP_VERSION=unknown',
      'CMD ["pnpm", "--filter", "server", "start:prod"]',
    ],
  },
  {
    file: 'docker-compose.prod.yml',
    snippets: [
      'web:',
      'server:',
      'postgres:',
      'redis:',
      'nginx:',
      'server_data:',
      'NEXT_PUBLIC_API_URL',
      'SERVER_IMAGE',
      'WEB_IMAGE',
      'APP_VERSION',
      'NEXT_API_PROXY_TARGET',
      '/api/v1/health/version',
      'prometheus:',
      "profiles: ['monitoring']",
      'postgres-exporter:',
      'blackbox-exporter:',
      'prometheus_data:',
    ],
  },
  {
    file: '.github/workflows/deploy-production.yml',
    snippets: [
      'docker/build-push-action',
      'appleboy/ssh-action',
      'docker compose --env-file .env.production -f docker-compose.prod.yml pull',
      'pnpm --filter server db:deploy',
      'NEXT_API_PROXY_TARGET',
      'scripts/smoke-test-release.mjs',
      '--expected-version',
    ],
  },
  {
    file: 'scripts/check-runtime-version.mjs',
    snippets: ['Runtime version verified', '/api/v1/health/version', 'expectedVersion'],
  },
  {
    file: 'scripts/smoke-test-release.mjs',
    snippets: [
      'Release smoke test passed',
      '/api/v1/health/version',
      '/api/v1/v2.2/requirements?productId=__smoke__',
      '/api/v1/config/ai',
    ],
  },
  {
    file: 'scripts/backup-postgres.mjs',
    snippets: ['pg_dump', '--format=custom', '--dry-run'],
  },
  {
    file: 'scripts/restore-postgres.mjs',
    snippets: ['--confirm-overwrite', 'dropdb', 'pg_restore'],
  },
  {
    file: 'scripts/backup-server-data.mjs',
    snippets: ['server_data', 'tar -czf', '--dry-run'],
  },
  {
    file: 'scripts/check-runbook-placeholders.mjs',
    snippets: ['Runbook placeholder scan passed', 'Runbook placeholder scan failed', '--paths'],
  },
  {
    file: 'package.json',
    snippets: ['docs:check-runbooks', 'docs/runbooks', 'docs/production-readiness.md'],
  },
  {
    file: 'docker-compose.local.yml',
    snippets: [
      'web:',
      'server:',
      'postgres:',
      'redis:',
      'nginx:',
      'local_server_data:',
      'NEXT_PUBLIC_API_URL',
      'NEXT_API_PROXY_TARGET',
      '${LOCAL_HTTP_PORT:-8080}:80',
    ],
  },
  {
    file: 'apps/web/lib/api.ts',
    snippets: [
      "env.NODE_ENV === 'production'",
      'isLocalOnlyApiUrl',
      "'localhost'",
      "'127.0.0.1'",
      "'0.0.0.0'",
      "return '/api/v1'",
    ],
  },
  {
    file: 'apps/web/next.config.js',
    snippets: [
      'NEXT_API_PROXY_TARGET',
      'toApiProxyDestination',
      '/api/v1/:path*',
    ],
  },
  {
    file: 'deploy/nginx/default.conf.template',
    snippets: [
      'proxy_pass http://web:3000',
      'proxy_pass http://server:3001',
      'client_max_body_size',
      'X-Forwarded-Proto',
    ],
  },
  {
    file: 'deploy/monitoring/README.md',
    snippets: [
      '--profile monitoring',
      'FtbPostgresDown',
      'FtbXiaobaoSummaryStale',
      'no webhook URLs',
    ],
  },
  {
    file: 'deploy/monitoring/prometheus/prometheus.yml',
    snippets: ['postgres-exporter:9187', 'promtail:9080', 'blackbox-http'],
  },
  {
    file: 'deploy/monitoring/prometheus/alert-rules.yml',
    snippets: [
      'FtbPostgresDown',
      'FtbSlowApiLogBurst',
      'FtbSlowPrismaLogBurst',
      'FtbJobFailureLogBurst',
      'FtbXiaobaoSummaryStale',
    ],
  },
  {
    file: 'docs/runbooks/migration-rollback.md',
    snippets: ['Fresh Database Restore', 'Data Risks', 'pnpm restore:postgres'],
  },
  {
    file: 'docs/runbooks/appdata-retirement.md',
    snippets: ['Disable AppData Writes', 'Remove Fallback', 'Data Risks'],
  },
  {
    file: 'docs/runbooks/xiaobao-background-jobs.md',
    snippets: ['FtbXiaobaoSummaryStale', 'Future Scheduler Rules', 'Data Risks'],
  },
  {
    file: 'docs/production-readiness.md',
    snippets: [
      'Backup and restore',
      'Smoke tests',
      'Monitoring',
      'Audit',
      'RBAC',
      'Consistency',
      'Performance',
      'Post-release',
    ],
  },
  {
    file: 'deploy/monitoring/postgres/postgres-queries.yml',
    snippets: ['xiaobao_risk_summaries', 'dirty = true', 'stale_summary_count'],
  },
  {
    file: 'deploy/monitoring/promtail/config.yml',
    snippets: ['Slow API request', 'Slow Prisma query', 'AppData relation sync failed'],
  },
  {
    file: 'deploy/monitoring/grafana/dashboards/ftb-production-overview.json',
    snippets: ['FTB Production Overview', 'ftb_xiaobao_stale_summary_count', 'Server Warning/Error Logs'],
  },
  {
    file: '.env.production.example',
    snippets: [
      'POSTGRES_PASSWORD=',
      'DATABASE_URL=postgresql://',
      'NEXT_PUBLIC_API_URL=/api/v1',
      'NEXT_API_PROXY_TARGET=',
      'APP_VERSION=',
      'WEB_IMAGE=',
      'SERVER_IMAGE=',
      'NEXTAUTH_SECRET=',
      'ANTHROPIC_API_KEY=',
    ],
  },
  {
    file: '.env.local-server.example',
    snippets: [
      'LOCAL_HTTP_PORT=8080',
      'LOCAL_ACCESS_HOST=localhost',
      'DATABASE_URL=postgresql://',
      'NEXT_PUBLIC_API_URL=/api/v1',
      'NEXT_API_PROXY_TARGET=',
      'NEXTAUTH_URL=http://localhost:8080',
    ],
    forbiddenSnippets: [
      'LOCAL_SERVER_PORT=',
    ],
  },
  {
    file: 'docs/deployment.md',
    snippets: [
      'docker-compose.prod.yml',
      'docker-compose.local.yml',
      '本地服务器部署',
      'pnpm deploy:verify',
      'pnpm backup:postgres',
      'pnpm restore:postgres',
      'pnpm backup:server-data',
      'docs/runbooks/migration-rollback.md',
      'docs/production-readiness.md',
      '--profile monitoring',
      'pnpm db:migrate',
      'NEXT_PUBLIC_API_URL',
      'Nginx',
    ],
  },
];

let failed = false;

for (const check of checks) {
  const abs = join(root, check.file);
  if (!existsSync(abs)) {
    console.error(`Missing deployment artifact: ${check.file}`);
    failed = true;
    continue;
  }

  const content = readFileSync(abs, 'utf8');
  for (const snippet of check.snippets) {
    if (!content.includes(snippet)) {
      console.error(`Missing snippet in ${check.file}: ${snippet}`);
      failed = true;
    }
  }
  for (const snippet of check.forbiddenSnippets ?? []) {
    if (content.includes(snippet)) {
      console.error(`Forbidden snippet in ${check.file}: ${snippet}`);
      failed = true;
    }
  }
}

for (const check of requiredRuntimeDependencies) {
  const abs = join(root, check.packageFile);
  if (!existsSync(abs)) {
    console.error(`Missing package file: ${check.packageFile}`);
    failed = true;
    continue;
  }

  const pkg = JSON.parse(readFileSync(abs, 'utf8'));
  const dependencies = pkg.dependencies ?? {};
  for (const dependency of check.dependencies) {
    if (!dependencies[dependency]) {
      console.error(`Missing runtime dependency in ${check.packageFile}: ${dependency}`);
      failed = true;
    }
  }
}

if (failed) {
  process.exit(1);
}

console.log('Production deployment artifacts verified.');
