const Database = require('better-sqlite3');
const path = require('path');
const fs = require('fs');

const dbPath = process.env.DB_PATH || path.join(__dirname, 'data', 'jackbox.db');
const dbDir = path.dirname(dbPath);

// Ensure data directory exists with proper permissions
try {
  if (!fs.existsSync(dbDir)) {
    fs.mkdirSync(dbDir, { recursive: true, mode: 0o777 });
  }
  // Also ensure the directory is writable
  fs.accessSync(dbDir, fs.constants.W_OK);
} catch (err) {
  console.error(`Error with database directory ${dbDir}:`, err.message);
  console.error('Please ensure the directory exists and is writable');
  process.exit(1);
}

const db = new Database(dbPath);

// Enable foreign keys
db.pragma('foreign_keys = ON');

// Create tables
function initializeDatabase() {
  // Games table
  db.exec(`
    CREATE TABLE IF NOT EXISTS games (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      pack_name TEXT NOT NULL,
      title TEXT NOT NULL,
      min_players INTEGER NOT NULL,
      max_players INTEGER NOT NULL,
      length_minutes INTEGER,
      has_audience INTEGER DEFAULT 0,
      family_friendly INTEGER DEFAULT 0,
      game_type TEXT,
      secondary_type TEXT,
      play_count INTEGER DEFAULT 0,
      popularity_score INTEGER DEFAULT 0,
      enabled INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )
  `);

  // Sessions table
  db.exec(`
    CREATE TABLE IF NOT EXISTS sessions (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      closed_at DATETIME,
      is_active INTEGER DEFAULT 1,
      notes TEXT
    )
  `);

  // Add archived column if it doesn't exist (for existing databases)
  try {
    db.exec(`ALTER TABLE sessions ADD COLUMN archived INTEGER DEFAULT 0`);
  } catch (err) {
    // Column already exists, ignore error
  }

  // Poll state columns on sessions
  try {
    db.exec(`ALTER TABLE sessions ADD COLUMN poll_active INTEGER DEFAULT 0`);
  } catch (err) {
    // Column already exists, ignore error
  }
  try {
    db.exec(`ALTER TABLE sessions ADD COLUMN poll_started_at TEXT`);
  } catch (err) {
    // Column already exists, ignore error
  }
  try {
    db.exec(`ALTER TABLE sessions ADD COLUMN poll_leading_game_id INTEGER`);
  } catch (err) {
    // Column already exists, ignore error
  }
  try {
    db.exec(`ALTER TABLE sessions ADD COLUMN poll_leading_label TEXT`);
  } catch (err) {
    // Column already exists, ignore error
  }
  try {
    db.exec(`ALTER TABLE sessions ADD COLUMN poll_leading_votes INTEGER`);
  } catch (err) {
    // Column already exists, ignore error
  }

  // Session games table
  db.exec(`
    CREATE TABLE IF NOT EXISTS session_games (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      session_id INTEGER NOT NULL,
      game_id INTEGER NOT NULL,
      played_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      manually_added INTEGER DEFAULT 0,
      status TEXT DEFAULT 'played',
      FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE,
      FOREIGN KEY (game_id) REFERENCES games(id) ON DELETE CASCADE
    )
  `);
  
  // Add status column if it doesn't exist (for existing databases)
  try {
    db.exec(`ALTER TABLE session_games ADD COLUMN status TEXT DEFAULT 'played'`);
  } catch (err) {
    // Column already exists, ignore error
  }

  // Add room_code column if it doesn't exist (for existing databases)
  try {
    db.exec(`ALTER TABLE session_games ADD COLUMN room_code TEXT`);
  } catch (err) {
    // Column already exists, ignore error
  }

  // Add player_count column if it doesn't exist (for existing databases)
  try {
    db.exec(`ALTER TABLE session_games ADD COLUMN player_count INTEGER`);
  } catch (err) {
    // Column already exists, ignore error
  }

  // Add player_count_check_status column if it doesn't exist (for existing databases)
  try {
    db.exec(`ALTER TABLE session_games ADD COLUMN player_count_check_status TEXT DEFAULT 'not_started'`);
  } catch (err) {
    // Column already exists, ignore error
  }

  // Add favor_bias column to games if it doesn't exist
  try {
    db.exec(`ALTER TABLE games ADD COLUMN favor_bias INTEGER DEFAULT 0`);
  } catch (err) {
    // Column already exists, ignore error
  }

  // Add upvotes and downvotes columns to games if they don't exist
  try {
    db.exec(`ALTER TABLE games ADD COLUMN upvotes INTEGER DEFAULT 0`);
  } catch (err) {
    // Column already exists, ignore error
  }
  
  try {
    db.exec(`ALTER TABLE games ADD COLUMN downvotes INTEGER DEFAULT 0`);
  } catch (err) {
    // Column already exists, ignore error
  }

  // Add ticker column for ticker-symbol voting
  try {
    db.exec(`ALTER TABLE games ADD COLUMN ticker TEXT`);
  } catch (err) {
    // Column already exists, ignore error
  }

  try {
    db.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_games_ticker ON games(ticker)`);
  } catch (err) {
    // Index already exists, ignore error
  }

  // Migrate existing popularity_score to upvotes/downvotes if needed
  try {
    const gamesWithScore = db.prepare(`
      SELECT id, popularity_score FROM games 
      WHERE popularity_score != 0 AND (upvotes = 0 AND downvotes = 0)
    `).all();
    
    if (gamesWithScore.length > 0) {
      const updateGame = db.prepare(`
        UPDATE games 
        SET upvotes = ?, downvotes = ? 
        WHERE id = ?
      `);
      
      for (const game of gamesWithScore) {
        if (game.popularity_score > 0) {
          updateGame.run(game.popularity_score, 0, game.id);
        } else {
          updateGame.run(0, Math.abs(game.popularity_score), game.id);
        }
      }
      console.log(`Migrated popularity scores for ${gamesWithScore.length} games`);
    }
  } catch (err) {
    console.error('Error migrating popularity scores:', err);
  }

  // Packs table for pack-level favoriting
  db.exec(`
    CREATE TABLE IF NOT EXISTS packs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL UNIQUE,
      favor_bias INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )
  `);

  // Populate packs table with unique pack names from games
  db.exec(`
    INSERT OR IGNORE INTO packs (name)
    SELECT DISTINCT pack_name FROM games
  `);

  // Chat logs table
  db.exec(`
    CREATE TABLE IF NOT EXISTS chat_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      session_id INTEGER NOT NULL,
      chatter_name TEXT NOT NULL,
      message TEXT NOT NULL,
      timestamp DATETIME NOT NULL,
      parsed_vote TEXT,
      FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
    )
  `);

  // Add message_hash column if it doesn't exist
  try {
    db.exec(`ALTER TABLE chat_logs ADD COLUMN message_hash TEXT`);
  } catch (err) {
    // Column already exists, ignore error
  }

  // Create index on message_hash for fast duplicate checking
  try {
    db.exec(`CREATE INDEX IF NOT EXISTS idx_chat_logs_hash ON chat_logs(message_hash)`);
  } catch (err) {
    // Index already exists, ignore error
  }

  // Live votes table for real-time voting
  db.exec(`
    CREATE TABLE IF NOT EXISTS live_votes (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      session_id INTEGER NOT NULL,
      game_id INTEGER NOT NULL,
      username TEXT NOT NULL,
      vote_type INTEGER NOT NULL,
      timestamp DATETIME NOT NULL,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE,
      FOREIGN KEY (game_id) REFERENCES games(id) ON DELETE CASCADE
    )
  `);

  // Create index for duplicate checking (username + timestamp within 1 second)
  try {
    db.exec(`CREATE INDEX IF NOT EXISTS idx_live_votes_dedup ON live_votes(username, timestamp)`);
  } catch (err) {
    // Index already exists, ignore error
  }

  // Webhooks table for external integrations
  db.exec(`
    CREATE TABLE IF NOT EXISTS webhooks (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      url TEXT NOT NULL,
      secret TEXT NOT NULL,
      events TEXT NOT NULL,
      enabled INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )
  `);

  // Webhook logs table for debugging
  db.exec(`
    CREATE TABLE IF NOT EXISTS webhook_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      webhook_id INTEGER NOT NULL,
      event_type TEXT NOT NULL,
      payload TEXT NOT NULL,
      response_status INTEGER,
      error_message TEXT,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      FOREIGN KEY (webhook_id) REFERENCES webhooks(id) ON DELETE CASCADE
    )
  `);

  console.log('Database initialized successfully');
}

initializeDatabase();

module.exports = db;

