// Database migration script for Turso
// Custom implementation to handle multi-statement SQL files with Turso

import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { createClient } from '@libsql/client';
import { drizzle } from 'drizzle-orm/libsql';
import * as schema from './schema';

console.log('🚀 Running database migrations...');

async function runMigrations() {
  // Get database URL and auth token
  let databaseUrl = process.env.TURSO_DATABASE_URL || Bun.env?.TURSO_DATABASE_URL;
  let authToken = process.env.TURSO_AUTH_TOKEN || Bun.env?.TURSO_AUTH_TOKEN;

  if (!databaseUrl) {
    console.log('[Migration] TURSO_DATABASE_URL not found. Migrating local SQLite: file:local.db');
    databaseUrl = "file:local.db";
  }

  if (!authToken) {
    console.log('[Migration] TURSO_AUTH_TOKEN not found. Using mock-token.');
    authToken = "mock-token";
  }

  // Create Turso client
  const client = createClient({
    url: databaseUrl,
    authToken: authToken,
  });

  const _db = drizzle(client, { schema });

  // Create migrations tracking table if it doesn't exist
  await client.execute(`
    CREATE TABLE IF NOT EXISTS __drizzle_migrations (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      hash TEXT NOT NULL,
      created_at INTEGER NOT NULL
    )
  `);

  // Read migration journal
  const migrationsFolder = './src/db/migrations';
  const journalPath = join(migrationsFolder, 'meta/_journal.json');
  const journalContent = await readFile(journalPath, 'utf-8');
  const journal = JSON.parse(journalContent);

  // Get already applied migrations
  const appliedMigrations = await client.execute('SELECT hash FROM __drizzle_migrations');
  const appliedHashes = new Set(
    appliedMigrations.rows.map((row) => (row as unknown as { hash: string }).hash)
  );

  // Process each migration in order
  for (const entry of journal.entries) {
    const migrationHash = `${entry.idx}:${entry.tag}`;

    if (appliedHashes.has(migrationHash)) {
      console.log(`⏭️  Skipping already applied migration: ${entry.tag}`);
      continue;
    }

    console.log(`📦 Applying migration: ${entry.tag}`);

    // Read migration SQL file
    const sqlFilePath = join(migrationsFolder, `${entry.tag}.sql`);
    const sqlContent = await readFile(sqlFilePath, 'utf-8');

    // Split SQL into individual statements
    let statements: string[];

    if (sqlContent.includes('--> statement-breakpoint')) {
      // Drizzle-generated SQL uses statement-breakpoint
      statements = sqlContent
        .split('--> statement-breakpoint')
        .map((stmt) => {
          // Remove SQL comments (lines starting with --)
          return stmt
            .split('\n')
            .filter((line) => !line.trim().startsWith('--'))
            .join('\n')
            .trim();
        })
        .filter((stmt) => stmt.length > 0)
        .map((stmt) => stmt.replace(/;$/, ''));
    } else {
      // Hand-written SQL - need to parse carefully
      // Remove comment lines but preserve block structure for triggers
      const cleanedSql = sqlContent
        .split('\n')
        .filter((line) => {
          const trimmed = line.trim();
          return trimmed && !trimmed.startsWith('--');
        })
        .join('\n');

      // Split by semicolons, but be careful with BEGIN...END blocks
      statements = [];
      let current = '';
      let inBlock = 0;

      for (const char of cleanedSql) {
        current += char;

        // Track BEGIN...END blocks
        const upperCurrent = current.toUpperCase();
        if (upperCurrent.endsWith('BEGIN')) {
          inBlock++;
        } else if (upperCurrent.endsWith('END')) {
          inBlock--;
        }

        // Split on semicolon only if not in a block
        if (char === ';' && inBlock === 0) {
          const stmt = current.slice(0, -1).trim();
          if (stmt) {
            statements.push(stmt);
          }
          current = '';
        }
      }

      // Add any remaining statement
      const lastStmt = current.trim();
      if (lastStmt) {
        statements.push(lastStmt);
      }
    }

    // Execute each statement individually
    // Turso requires each statement to be executed separately
    if (statements.length > 0) {
      try {
        console.log(`   Executing ${statements.length} statements...`);

        for (let i = 0; i < statements.length; i++) {
          const stmt = statements[i];
          if (stmt.trim()) {
            try {
              await client.execute(stmt);
              console.log(`   ✓ Statement ${i + 1}/${statements.length}`);
            } catch (error) {
              const errorMessage = error instanceof Error ? error.message : 'Unknown error';
              console.error(`   ✗ Statement ${i + 1}/${statements.length} failed:`, errorMessage);
              throw error;
            }
          }
        }

        // Record successful migration
        await client.execute({
          sql: 'INSERT INTO __drizzle_migrations (hash, created_at) VALUES (?, ?)',
          args: [migrationHash, Date.now()],
        });

        console.log(`✅ Applied migration: ${entry.tag}`);
      } catch (error) {
        console.error(`❌ Failed to apply migration ${entry.tag}:`, error);
        throw error;
      }
    }
  }

  console.log('✅ All migrations completed successfully!');
}

try {
  await runMigrations();
  process.exit(0);
} catch (error) {
  console.error('❌ Migration failed:', error);
  process.exit(1);
}
