import 'dotenv/config'
import { getDb } from './client.js'

const sql = getDb()

const migrate = async () => {
  await sql`
    CREATE EXTENSION IF NOT EXISTS "pgcrypto"
  `

  await sql`
    CREATE TABLE IF NOT EXISTS roles (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      name VARCHAR(100) NOT NULL UNIQUE,
      permissions JSONB NOT NULL DEFAULT '{}',
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    CREATE TABLE IF NOT EXISTS customers (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      firebase_uid VARCHAR(255) UNIQUE,
      phone VARCHAR(20) UNIQUE,
      display_name VARCHAR(100) NOT NULL,
      is_anonymous BOOLEAN NOT NULL DEFAULT TRUE,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    CREATE TABLE IF NOT EXISTS mitras (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      firebase_uid VARCHAR(255) UNIQUE,
      phone VARCHAR(20) NOT NULL UNIQUE,
      display_name VARCHAR(100) NOT NULL,
      is_active BOOLEAN NOT NULL DEFAULT FALSE,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    CREATE TABLE IF NOT EXISTS control_center_users (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      firebase_uid VARCHAR(255) NOT NULL UNIQUE,
      email VARCHAR(255) NOT NULL UNIQUE,
      display_name VARCHAR(100) NOT NULL,
      role_id UUID NOT NULL REFERENCES roles(id),
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    CREATE TABLE IF NOT EXISTS app_config (
      key VARCHAR(100) PRIMARY KEY,
      value JSONB NOT NULL,
      updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('anonymity', '{"enabled": false}')
    ON CONFLICT (key) DO NOTHING
  `

  // --- Phase 2: Mitra Online Status & Pairing ---

  await sql`
    CREATE TABLE IF NOT EXISTS mitra_online_status (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      mitra_id UUID NOT NULL UNIQUE REFERENCES mitras(id),
      is_online BOOLEAN NOT NULL DEFAULT FALSE,
      last_online_at TIMESTAMPTZ,
      last_offline_at TIMESTAMPTZ,
      last_heartbeat_at TIMESTAMPTZ,
      updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    CREATE TABLE IF NOT EXISTS mitra_online_logs (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      mitra_id UUID NOT NULL REFERENCES mitras(id),
      status VARCHAR(10) NOT NULL,
      timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_mitra_online_logs_mitra_id
    ON mitra_online_logs (mitra_id)
  `

  await sql`
    CREATE TABLE IF NOT EXISTS chat_sessions (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      customer_id UUID NOT NULL REFERENCES customers(id),
      mitra_id UUID REFERENCES mitras(id),
      status VARCHAR(30) NOT NULL DEFAULT 'searching',
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      paired_at TIMESTAMPTZ,
      ended_at TIMESTAMPTZ,
      ended_by VARCHAR(20)
    )
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_chat_sessions_customer_id
    ON chat_sessions (customer_id)
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_chat_sessions_mitra_id
    ON chat_sessions (mitra_id)
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_chat_sessions_status
    ON chat_sessions (status)
  `

  await sql`
    CREATE TABLE IF NOT EXISTS chat_request_notifications (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      session_id UUID NOT NULL REFERENCES chat_sessions(id),
      mitra_id UUID NOT NULL REFERENCES mitras(id),
      notified_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      response VARCHAR(20),
      responded_at TIMESTAMPTZ
    )
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_chat_request_notifications_session_id
    ON chat_request_notifications (session_id)
  `

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('max_customers_per_mitra', '{"value": 3}')
    ON CONFLICT (key) DO NOTHING
  `

  // --- Phase 3: Chat Engine ---

  // Add session duration/pricing columns to chat_sessions
  await sql`
    ALTER TABLE chat_sessions
    ADD COLUMN IF NOT EXISTS duration_minutes INT,
    ADD COLUMN IF NOT EXISTS price INT DEFAULT 0,
    ADD COLUMN IF NOT EXISTS is_free_trial BOOLEAN NOT NULL DEFAULT FALSE,
    ADD COLUMN IF NOT EXISTS expires_at TIMESTAMPTZ,
    ADD COLUMN IF NOT EXISTS extended_minutes INT NOT NULL DEFAULT 0
  `

  // Add FCM token columns
  await sql`
    ALTER TABLE customers
    ADD COLUMN IF NOT EXISTS fcm_token VARCHAR(255)
  `

  await sql`
    ALTER TABLE mitras
    ADD COLUMN IF NOT EXISTS fcm_token VARCHAR(255)
  `

  await sql`
    CREATE TABLE IF NOT EXISTS chat_messages (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      session_id UUID NOT NULL REFERENCES chat_sessions(id),
      sender_type VARCHAR(10) NOT NULL,
      sender_id UUID NOT NULL,
      type VARCHAR(20) NOT NULL DEFAULT 'text',
      content TEXT NOT NULL,
      metadata JSONB,
      status VARCHAR(20) NOT NULL DEFAULT 'sent',
      delivered_at TIMESTAMPTZ,
      read_at TIMESTAMPTZ,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_chat_messages_session_created
    ON chat_messages (session_id, created_at)
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_chat_messages_session_status
    ON chat_messages (session_id, status)
  `

  await sql`
    CREATE TABLE IF NOT EXISTS session_closures (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      session_id UUID NOT NULL REFERENCES chat_sessions(id),
      user_type VARCHAR(10) NOT NULL,
      user_id UUID NOT NULL,
      message TEXT NOT NULL,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    CREATE TABLE IF NOT EXISTS session_extensions (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      session_id UUID NOT NULL REFERENCES chat_sessions(id),
      requested_duration_minutes INT NOT NULL,
      requested_price INT NOT NULL,
      status VARCHAR(20) NOT NULL DEFAULT 'pending',
      requested_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      responded_at TIMESTAMPTZ
    )
  `

  await sql`
    CREATE TABLE IF NOT EXISTS customer_transactions (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      customer_id UUID NOT NULL REFERENCES customers(id),
      session_id UUID NOT NULL REFERENCES chat_sessions(id),
      type VARCHAR(20) NOT NULL,
      amount INT NOT NULL DEFAULT 0,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_customer_transactions_customer_id
    ON customer_transactions (customer_id)
  `

  // Phase 3 config keys
  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('free_trial_enabled', '{"value": true}')
    ON CONFLICT (key) DO NOTHING
  `

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('free_trial_duration_minutes', '{"value": 5}')
    ON CONFLICT (key) DO NOTHING
  `

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('extension_timeout_seconds', '{"value": 60}')
    ON CONFLICT (key) DO NOTHING
  `

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('early_end_mitra_enabled', '{"value": false}')
    ON CONFLICT (key) DO NOTHING
  `

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('early_end_customer_enabled', '{"value": false}')
    ON CONFLICT (key) DO NOTHING
  `

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('price_tiers', ${sql.json({ tiers: [
      { duration_minutes: 1, price: 5000, label: '1 Menit (Test)' },
      { duration_minutes: 15, price: 30000, label: '15 Menit' },
      { duration_minutes: 30, price: 60000, label: '30 Menit' },
      { duration_minutes: 45, price: 100000, label: '45 Menit' },
      { duration_minutes: 60, price: 150000, label: '60 Menit' },
      { duration_minutes: 1440, price: 250000, label: '24 Jam' },
    ]})})
    ON CONFLICT (key) DO NOTHING
  `

  // --- Phase 3.1: Mitra Ping Config ---

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('require_mitra_ping', '{"value": true}')
    ON CONFLICT (key) DO NOTHING
  `

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('mitra_ping_interval_seconds', '{"value": 15}')
    ON CONFLICT (key) DO NOTHING
  `

  // --- Phase 3.2: Mitra Request Activity Log ---

  await sql`
    ALTER TABLE chat_request_notifications
    ADD COLUMN IF NOT EXISTS active_session_count INT NOT NULL DEFAULT 0
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_chat_request_notifications_mitra_notified
    ON chat_request_notifications (mitra_id, notified_at)
  `

  // --- Phase 3.3: Session Topic Sensitivity ---

  await sql`
    ALTER TABLE chat_sessions
    ADD COLUMN IF NOT EXISTS topic_sensitivity VARCHAR(16) NOT NULL DEFAULT 'regular'
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_chat_sessions_topic_sensitivity
    ON chat_sessions (topic_sensitivity)
  `

  await sql`
    CREATE TABLE IF NOT EXISTS session_sensitivity_log (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      session_id UUID NOT NULL REFERENCES chat_sessions(id) ON DELETE CASCADE,
      changed_by_mitra_id UUID NOT NULL REFERENCES mitras(id),
      from_value VARCHAR(16) NOT NULL,
      to_value VARCHAR(16) NOT NULL,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `

  await sql`
    CREATE INDEX IF NOT EXISTS idx_session_sensitivity_log_session
    ON session_sensitivity_log (session_id)
  `

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('sensitive_flip_confirmation_enabled', '{"value": true}')
    ON CONFLICT (key) DO NOTHING
  `

  await sql`
    INSERT INTO app_config (key, value)
    VALUES ('sensitive_flag_one_way_latch', '{"value": false}')
    ON CONFLICT (key) DO NOTHING
  `

  // --- Phase 3.4: Self-Managed Auth ---

  // Customers: add social identity columns
  await sql`
    ALTER TABLE customers
      ADD COLUMN IF NOT EXISTS email VARCHAR(255),
      ADD COLUMN IF NOT EXISTS google_sub VARCHAR(255),
      ADD COLUMN IF NOT EXISTS apple_sub VARCHAR(255)
  `
  await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_customers_google_sub ON customers (google_sub) WHERE google_sub IS NOT NULL`
  await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_customers_apple_sub ON customers (apple_sub) WHERE apple_sub IS NOT NULL`

  // display_name is set after sign-in via the set-display-name screen for
  // direct phone/Google/Apple sign-ups (no anonymous bootstrap). Allow null.
  await sql`ALTER TABLE customers ALTER COLUMN display_name DROP NOT NULL`

  // Control center users: password-based auth columns
  // firebase_uid stays for backward compat during migration; will be dropped in a later cleanup migration
  await sql`ALTER TABLE control_center_users ALTER COLUMN firebase_uid DROP NOT NULL`
  await sql`
    ALTER TABLE control_center_users
      ADD COLUMN IF NOT EXISTS password_hash VARCHAR(60) NOT NULL DEFAULT '',
      ADD COLUMN IF NOT EXISTS failed_login_count INT NOT NULL DEFAULT 0,
      ADD COLUMN IF NOT EXISTS lockout_until TIMESTAMPTZ
  `

  // Auth sessions (refresh tokens + multi-device)
  await sql`
    CREATE TABLE IF NOT EXISTS auth_sessions (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      user_type VARCHAR(16) NOT NULL,
      user_id UUID NOT NULL,
      refresh_token_hash VARCHAR(60) NOT NULL,
      device_info JSONB,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      last_used_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      expires_at TIMESTAMPTZ NOT NULL,
      revoked_at TIMESTAMPTZ
    )
  `
  await sql`CREATE INDEX IF NOT EXISTS idx_auth_sessions_user ON auth_sessions (user_type, user_id)`
  await sql`CREATE INDEX IF NOT EXISTS idx_auth_sessions_expires ON auth_sessions (expires_at) WHERE revoked_at IS NULL`

  // OTP requests (Fazpass reference + rate-limit tracking)
  await sql`
    CREATE TABLE IF NOT EXISTS otp_requests (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      phone VARCHAR(20) NOT NULL,
      ip_address VARCHAR(45),
      user_type VARCHAR(16) NOT NULL,
      fazpass_reference VARCHAR(255),
      channel VARCHAR(16),
      attempts INT NOT NULL DEFAULT 0,
      used_at TIMESTAMPTZ,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      expires_at TIMESTAMPTZ NOT NULL
    )
  `
  await sql`CREATE INDEX IF NOT EXISTS idx_otp_requests_phone_created ON otp_requests (phone, created_at)`
  await sql`CREATE INDEX IF NOT EXISTS idx_otp_requests_ip_created ON otp_requests (ip_address, created_at)`

  // Auth-related app_config defaults
  await sql`
    INSERT INTO app_config (key, value) VALUES
      ('otp_max_per_phone_per_hour', '{"value": 3}'),
      ('otp_max_per_ip_per_hour', '{"value": 10}'),
      ('otp_resend_cooldown_seconds', '{"value": 60}'),
      ('otp_verify_max_attempts', '{"value": 5}'),
      ('cc_login_max_attempts', '{"value": 5}'),
      ('cc_login_lockout_minutes', '{"value": 15}')
    ON CONFLICT (key) DO NOTHING
  `

  console.log('Migration complete.')
  await sql.end()
}

migrate().catch((err) => {
  console.error('Migration failed:', err)
  process.exit(1)
})
