import { PrismaClient as PrismaClientAuth } from '../node_modules/.prisma/client-auth';
import bcrypt from 'bcryptjs';
import * as dotenv from 'dotenv';

// Load environment variables
dotenv.config({ path: '.env' });

const prisma = new PrismaClientAuth({
  datasourceUrl: process.env.DATABASE_URL_AUTH,
});

async function setupAuth() {
  try {
    console.log('Setting up authentication tables and admin user...\n');

    // Create tables using raw SQL (Prisma doesn't support CREATE TABLE in migrations easily)
    console.log('Creating users table...');
    await prisma.$executeRawUnsafe(`
      CREATE TABLE IF NOT EXISTS users (
        id SERIAL PRIMARY KEY,
        email VARCHAR(255) UNIQUE NOT NULL,
        name VARCHAR(255),
        password_hash VARCHAR(255) NOT NULL,
        is_admin BOOLEAN DEFAULT FALSE,
        is_active BOOLEAN DEFAULT TRUE,
        has_write_access BOOLEAN DEFAULT FALSE,
        email_verified BOOLEAN DEFAULT FALSE,
        email_confirmation_token VARCHAR(255) UNIQUE,
        email_confirmation_token_expiry TIMESTAMP,
        password_reset_token VARCHAR(255) UNIQUE,
        password_reset_token_expiry TIMESTAMP,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
      );
    `);
    
    // Add missing columns if table already exists with old schema
    console.log('Adding missing columns if needed...');
    await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS is_admin BOOLEAN DEFAULT FALSE;`);
    await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS has_write_access BOOLEAN DEFAULT FALSE;`);
    await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS email_verified BOOLEAN DEFAULT FALSE;`);
    await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS email_confirmation_token VARCHAR(255);`);
    await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS email_confirmation_token_expiry TIMESTAMP;`);
    await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS password_reset_token VARCHAR(255);`);
    await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS password_reset_token_expiry TIMESTAMP;`);
    
    // Add unique constraints if they don't exist
    await prisma.$executeRawUnsafe(`CREATE UNIQUE INDEX IF NOT EXISTS users_email_confirmation_token_key ON users(email_confirmation_token) WHERE email_confirmation_token IS NOT NULL;`);
    await prisma.$executeRawUnsafe(`CREATE UNIQUE INDEX IF NOT EXISTS users_password_reset_token_key ON users(password_reset_token) WHERE password_reset_token IS NOT NULL;`);

    console.log('Creating pending_identifications table...');
    await prisma.$executeRawUnsafe(`
      CREATE TABLE IF NOT EXISTS pending_identifications (
        id SERIAL PRIMARY KEY,
        face_id INTEGER NOT NULL,
        user_id INTEGER NOT NULL,
        first_name VARCHAR(255) NOT NULL,
        last_name VARCHAR(255) NOT NULL,
        middle_name VARCHAR(255),
        maiden_name VARCHAR(255),
        date_of_birth DATE,
        status VARCHAR(50) DEFAULT 'pending',
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
        -- Note: face_id references faces in punimtag database, but we can't use foreign key across databases
      );
    `);

    console.log('Creating indexes...');
    await prisma.$executeRawUnsafe(`CREATE INDEX IF NOT EXISTS idx_pending_identifications_face_id ON pending_identifications(face_id);`);
    await prisma.$executeRawUnsafe(`CREATE INDEX IF NOT EXISTS idx_pending_identifications_user_id ON pending_identifications(user_id);`);
    await prisma.$executeRawUnsafe(`CREATE INDEX IF NOT EXISTS idx_pending_identifications_status ON pending_identifications(status);`);

    // Check if admin user already exists
    const existingAdmin = await prisma.user.findUnique({
      where: { email: 'admin@admin.com' },
    });

    if (existingAdmin) {
      console.log('Admin user already exists. Updating password...');
      const passwordHash = await bcrypt.hash('admin', 10);
      await prisma.user.update({
        where: { email: 'admin@admin.com' },
        data: { 
          passwordHash,
          isAdmin: true,
          hasWriteAccess: true,
          emailVerified: true,
          isActive: true,
        },
      });
      console.log('✅ Admin user password updated (admin@admin.com / admin)');
    } else {
      console.log('Creating admin user...');
      const passwordHash = await bcrypt.hash('admin', 10);
      await prisma.user.create({
        data: {
          email: 'admin@admin.com',
          name: 'Admin',
          passwordHash,
          isAdmin: true,
          hasWriteAccess: true,
          emailVerified: true,
          isActive: true,
        },
      });
      console.log('✅ Admin user created (admin@admin.com / admin)');
    }

    console.log('\n✅ Setup complete!');
    console.log('\nAdmin credentials:');
    console.log('  Email: admin@admin.com');
    console.log('  Password: admin');
    console.log('\nNote: Make sure to grant appropriate database permissions:');
    console.log('  - Regular users: INSERT on pending_identifications');
    console.log('  - Admin: UPDATE on pending_identifications (for approval)');
  } catch (error: any) {
    console.error('Error setting up authentication:', error);
    if (error.message.includes('permission denied')) {
      console.error('\n⚠️  Permission denied. You may need to:');
      console.error('  1. Run this script with a user that has CREATE TABLE permissions');
      console.error('  2. Or manually create the tables using create_auth_tables.sql');
    }
    throw error;
  } finally {
    await prisma.$disconnect();
  }
}

setupAuth();

