import 'dotenv/config';
import { Client } from 'pg';
import fs from 'node:fs';
import path from 'node:path';
import { spawnSync } from 'node:child_process';

const dbUrl = process.env.DATABASE_URL;
if (!dbUrl) {
  console.error('DATABASE_URL is not set');
  process.exit(1);
}

// جلوگیری از اجرای ناخواسته روی پروداکشن
if (process.env.NODE_ENV === 'production' && process.env.FRESH_FORCE !== '1') {
  console.error('Refusing to run fresh in production. Set FRESH_FORCE=1 to override.');
  process.exit(1);
}

async function dropEverythingInPublicSchema() {
  const client = new Client({ connectionString: dbUrl });
  await client.connect();

  try {
    await client.query(`
      DO $$
      DECLARE r RECORD;
      BEGIN
        -- views
        FOR r IN (SELECT table_name FROM information_schema.views WHERE table_schema = 'public') LOOP
          EXECUTE 'DROP VIEW IF EXISTS public.' || quote_ident(r.table_name) || ' CASCADE';
        END LOOP;

        -- tables
        FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = 'public') LOOP
          EXECUTE 'DROP TABLE IF EXISTS public.' || quote_ident(r.tablename) || ' CASCADE';
        END LOOP;

        -- sequences
        FOR r IN (SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = 'public') LOOP
          EXECUTE 'DROP SEQUENCE IF EXISTS public.' || quote_ident(r.sequence_name) || ' CASCADE';
        END LOOP;

        -- types (enums, composites, domains)
        FOR r IN (
          SELECT t.typname
          FROM pg_type t
          JOIN pg_namespace n ON n.oid = t.typnamespace
          WHERE n.nspname = 'public' AND t.typtype IN ('e','c','d')
        ) LOOP
          EXECUTE 'DROP TYPE IF EXISTS public.' || quote_ident(r.typname) || ' CASCADE';
        END LOOP;
      END $$;
    `);
  } finally {
    await client.end();
  }
}

function removeDrizzleFolder() {
  const drizzleDir = path.resolve(process.cwd(), 'drizzle');
  fs.rmSync(drizzleDir, { recursive: true, force: true });
}

function run(cmd: string, args: string[]) {
  const isWin = process.platform === 'win32';
  const res = spawnSync(cmd, args, { stdio: 'inherit', shell: isWin });
  if (res.status !== 0) process.exit(res.status ?? 1);
}

(async () => {
  await dropEverythingInPublicSchema();
  removeDrizzleFolder();
  run('pnpm', ['generate']);
  run('pnpm', ['migrate']);
})();
