import fs from 'node:fs';
import path from 'node:path';
import { DatabaseSync } from 'node:sqlite';
import { config } from './config.js';
import { nowIso, nowSeconds, uuid } from './utils.js';
import { inspectDatabaseFile } from './database-health.js';
import { applyMigrations } from './migrations.js';

let singleton;

const defaultSettings = {
  app_name: 'OnlyCoin',
  launch_at: new Date(Date.now() + 90 * 86400000).toISOString(),
  launch_message: 'OnlyCoin lansmanına kalan süre',
  announcement: 'Ücretsiz dağıtım dönemi devam ediyor. Her gün giriş yap, görevleri tamamla ve OC_POINTS kazan.',
  maintenance_mode: false,
  conversion_enabled: false,
  conversion_unlock_at_launch: false,
  conversion_rate_bps: 1000,
  conversion_min_points: 1000,
  conversion_daily_limit_points: 1000000,
  initial_points: 0,
  tap_reward_points: 5,
  tap_batch_limit: 50,
  energy_capacity: 1000,
  energy_refill_per_minute: 10,
  auto_points_per_hour: 125,
  auto_offline_cap_hours: 8,
  paid_spin_cost_points: 50,
  wheel_daily_free_spins: 3,
  wheel_daily_total_limit: 10,
  wheel_spin_cooldown_seconds: 5,
  wheel_animation_ms: 4600,
  wheel_prevent_immediate_repeat: true,
  ad_spin_enabled: false,
  ad_reward_points: 250,
  ad_cooldown_seconds: 60,
  referral_reward_points: 1000,
  referral_qualifying_taps: 100,
  referral_level_1_bps: 1000,
  referral_level_2_bps: 500,
  referral_level_3_bps: 200,
  referral_multilevel_enabled: false,
  telegram_enabled: true,
  pwa_enabled: true,
  android_enabled: true,
  ios_enabled: true,
  purchases_enabled: false,
  support_email: 'support@onlycoin.io',
  terms_url: '/terms',
  privacy_url: '/privacy',
  site_enabled: true,
  telegram_login_enabled: true,
  telegram_bot_username: '',
  telegram_phone_collection_enabled: true,
  project_token_symbol: 'OC',
  project_token_decimals: 18,
  project_token_contract: '',
  usdt_network: 'EVM',
  usdt_network_name: 'BSC / EVM',
  usdt_chain_id: 56,
  usdt_contract_address: '',
  usdt_decimals: 6,
  treasury_deposit_address: '',
  blockchain_explorer_url: '',
  blockchain_rpc_mode: 'manual',
  presale_enabled: false,
  presale_require_launch: false,
  presale_min_usdt_micros: 10000000,
  presale_max_usdt_micros: 100000000000,
  presale_hard_cap_usdt_micros: 5000000000000,
  presale_soft_cap_usdt_micros: 1000000000000,
  presale_total_token_base_units: 10000000000,
  deposit_enabled: false,
  withdrawal_enabled: false,
  withdrawal_min_token: 1000,
  withdrawal_fee_token: 10,
  withdrawal_daily_limit_token: 10000000,
  withdrawal_min_usdt_micros: 10000000,
  withdrawal_fee_usdt_micros: 1000000,
  withdrawal_daily_limit_usdt_micros: 1000000000,
  points_transfer_enabled: true,
  points_transfer_min: 100,
  points_transfer_max: 1000000,
  points_transfer_daily_limit: 5000000,
  points_transfer_fee_bps: 100,
  whitepaper_download_url: '',
  whitepaper_version: '1.0',
  whitepaper_updated_at: 'July 2026',
  whitepaper_total_pages: 42,
  contact_address: 'Türkiye',
  social_telegram_url: '',
  social_x_url: '',
  social_discord_url: '',
  social_youtube_url: '',
  base_currency: 'TRY',
  display_currency: 'TRY',
  settlement_currency: 'TRY',
  enabled_fiat_currencies: ['TRY','USD','EUR','GBP'],
  fiat_payments_enabled: false,
  bank_transfer_enabled: false,
  crypto_funding_enabled: false,
  crypto_payment_for_goods_enabled: false,
  crypto_payment_region_mode: 'presale_deposit_only',
  country_code: 'TR',
  fx_rate_source: 'manual',
  fx_auto_update_enabled: false,
  fx_update_interval_minutes: 360,
  fx_rate_margin_bps: 0,
  payment_order_expiry_minutes: 60,
  payment_callback_base_url: '',
  payment_success_url: '/game/#payment-success',
  payment_failure_url: '/game/#payment-failed',
  payment_max_installment: 1,
  payment_3d_secure_required: true,
  payment_provider_timeout_seconds: 20,
  payment_webhook_replay_window_seconds: 300,
  kyc_required_for_crypto: true,
  kyc_required_for_withdrawal: true,
  aml_screening_enabled: false,
  sanctions_screening_enabled: false,
  min_user_age: 18,
  allowed_country_codes: ['TR'],
  blocked_country_codes: [],
  smtp_enabled: false,
  smtp_host: '',
  smtp_port: 587,
  smtp_secure: false,
  smtp_username: '',
  smtp_from_email: '',
  smtp_from_name: 'OnlyCoin',
  sms_provider: 'none',
  sms_sender: 'ONLYCOIN',
  push_enabled: false,
  firebase_project_id: '',
  maintenance_message: 'Sistem kısa süreli bakım çalışmasındadır.',
  support_phone: '',
  company_legal_name: '',
  company_tax_office: '',
  company_tax_number: '',
  company_mersis_number: '',
  company_address: '',
  privacy_contact_email: 'privacy@onlycoin.io',
  default_language: 'tr',
  enabled_languages: ['tr','en'],
  timezone: 'Europe/Istanbul',
  seo_default_title: 'OnlyCoin',
  seo_default_description: 'OnlyCoin dijital değer ve tap-to-earn ekosistemi',
  analytics_enabled: false,
  analytics_provider: 'none',
  analytics_measurement_id: '',
  backup_enabled: true,
  backup_retention_days: 14,
  audit_retention_days: 365,
  session_duration_minutes: 60,
  admin_session_duration_minutes: 30,
  rate_limit_profile: 'standard'
};

function createSchema(db) {
  db.exec(`
    PRAGMA foreign_keys = ON;
    PRAGMA journal_mode = WAL;
    PRAGMA synchronous = NORMAL;
    PRAGMA busy_timeout = 5000;

    CREATE TABLE IF NOT EXISTS settings (
      key TEXT PRIMARY KEY,
      value TEXT NOT NULL,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS users (
      id TEXT PRIMARY KEY,
      telegram_id TEXT UNIQUE,
      username TEXT NOT NULL,
      display_name TEXT NOT NULL,
      avatar TEXT NOT NULL DEFAULT '',
      referral_code TEXT NOT NULL UNIQUE,
      referred_by TEXT REFERENCES users(id),
      status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','review','blocked','deleted')),
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS user_game_state (
      user_id TEXT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
      level INTEGER NOT NULL DEFAULT 1 CHECK(level >= 1),
      xp INTEGER NOT NULL DEFAULT 0 CHECK(xp >= 0),
      energy INTEGER NOT NULL DEFAULT 1000 CHECK(energy >= 0),
      energy_updated_at INTEGER NOT NULL,
      tap_total INTEGER NOT NULL DEFAULT 0 CHECK(tap_total >= 0),
      auto_settled_at INTEGER NOT NULL,
      vip_tier INTEGER NOT NULL DEFAULT 0 CHECK(vip_tier BETWEEN 0 AND 5),
      vip_expires_at INTEGER,
      last_login_day TEXT,
      streak_days INTEGER NOT NULL DEFAULT 0 CHECK(streak_days >= 0),
      last_free_spin_day TEXT,
      free_spins_used INTEGER NOT NULL DEFAULT 0 CHECK(free_spins_used >= 0),
      ad_spin_credits INTEGER NOT NULL DEFAULT 0 CHECK(ad_spin_credits >= 0),
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS vip_plans (
      tier INTEGER PRIMARY KEY CHECK(tier BETWEEN 1 AND 5),
      name TEXT NOT NULL,
      subtitle TEXT NOT NULL,
      price_points INTEGER NOT NULL CHECK(price_points >= 0),
      price_try_cents INTEGER NOT NULL DEFAULT 0 CHECK(price_try_cents >= 0),
      tap_multiplier_bps INTEGER NOT NULL CHECK(tap_multiplier_bps >= 10000),
      energy_multiplier_bps INTEGER NOT NULL CHECK(energy_multiplier_bps >= 10000),
      auto_multiplier_bps INTEGER NOT NULL CHECK(auto_multiplier_bps >= 10000),
      daily_free_spins INTEGER NOT NULL DEFAULT 1 CHECK(daily_free_spins >= 0),
      referral_multiplier_bps INTEGER NOT NULL CHECK(referral_multiplier_bps >= 10000),
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS quests (
      id TEXT PRIMARY KEY,
      title TEXT NOT NULL,
      description TEXT NOT NULL,
      event_type TEXT NOT NULL,
      target_count INTEGER NOT NULL CHECK(target_count > 0),
      reward_points INTEGER NOT NULL CHECK(reward_points >= 0),
      repeat_type TEXT NOT NULL CHECK(repeat_type IN ('daily','weekly','once')),
      sort_order INTEGER NOT NULL DEFAULT 0,
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS quest_progress (
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      quest_id TEXT NOT NULL REFERENCES quests(id) ON DELETE CASCADE,
      period_key TEXT NOT NULL,
      progress INTEGER NOT NULL DEFAULT 0 CHECK(progress >= 0),
      claimed INTEGER NOT NULL DEFAULT 0 CHECK(claimed IN (0,1)),
      updated_at TEXT NOT NULL,
      PRIMARY KEY(user_id, quest_id, period_key)
    );

    CREATE TABLE IF NOT EXISTS wheel_segments (
      id TEXT PRIMARY KEY,
      label TEXT NOT NULL,
      reward_type TEXT NOT NULL CHECK(reward_type IN ('points','energy','booster','vip_trial','ad_spin')),
      reward_value INTEGER NOT NULL CHECK(reward_value >= 0),
      weight INTEGER NOT NULL CHECK(weight >= 0),
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      sort_order INTEGER NOT NULL DEFAULT 0,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS user_boosters (
      id TEXT PRIMARY KEY,
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      type TEXT NOT NULL,
      multiplier_bps INTEGER NOT NULL DEFAULT 10000,
      starts_at INTEGER NOT NULL,
      expires_at INTEGER NOT NULL,
      source TEXT NOT NULL,
      created_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS referrals (
      id TEXT PRIMARY KEY,
      inviter_id TEXT NOT NULL REFERENCES users(id),
      invitee_id TEXT NOT NULL UNIQUE REFERENCES users(id),
      status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','qualified','rewarded','rejected')),
      qualified_at TEXT,
      rewarded_at TEXT,
      created_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS ledger_accounts (
      id TEXT PRIMARY KEY,
      user_id TEXT REFERENCES users(id) ON DELETE CASCADE,
      asset TEXT NOT NULL CHECK(asset IN ('OC_POINTS','OC_TOKEN','USDT')),
      code TEXT NOT NULL UNIQUE,
      name TEXT NOT NULL,
      allow_negative INTEGER NOT NULL DEFAULT 0 CHECK(allow_negative IN (0,1)),
      balance INTEGER NOT NULL DEFAULT 0,
      created_at TEXT NOT NULL
    );

    CREATE INDEX IF NOT EXISTS idx_ledger_accounts_user_asset ON ledger_accounts(user_id, asset);

    CREATE TABLE IF NOT EXISTS ledger_transactions (
      id TEXT PRIMARY KEY,
      type TEXT NOT NULL,
      ref TEXT NOT NULL,
      idempotency_key TEXT NOT NULL UNIQUE,
      metadata TEXT NOT NULL DEFAULT '{}',
      created_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS ledger_entries (
      id TEXT PRIMARY KEY,
      transaction_id TEXT NOT NULL REFERENCES ledger_transactions(id) ON DELETE RESTRICT,
      account_id TEXT NOT NULL REFERENCES ledger_accounts(id) ON DELETE RESTRICT,
      amount INTEGER NOT NULL CHECK(amount <> 0),
      created_at TEXT NOT NULL
    );

    CREATE INDEX IF NOT EXISTS idx_ledger_entries_tx ON ledger_entries(transaction_id);
    CREATE INDEX IF NOT EXISTS idx_ledger_entries_account ON ledger_entries(account_id, created_at DESC);

    CREATE TABLE IF NOT EXISTS game_events (
      id TEXT PRIMARY KEY,
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      type TEXT NOT NULL,
      value INTEGER NOT NULL DEFAULT 1,
      metadata TEXT NOT NULL DEFAULT '{}',
      idempotency_key TEXT NOT NULL UNIQUE,
      created_at TEXT NOT NULL
    );

    CREATE INDEX IF NOT EXISTS idx_game_events_user_type ON game_events(user_id, type, created_at DESC);

    CREATE TABLE IF NOT EXISTS wheel_spins (
      id TEXT PRIMARY KEY,
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      mode TEXT NOT NULL CHECK(mode IN ('free','points','ad')),
      segment_id TEXT NOT NULL REFERENCES wheel_segments(id),
      reward_type TEXT NOT NULL,
      reward_value INTEGER NOT NULL,
      idempotency_key TEXT NOT NULL UNIQUE,
      created_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS ad_sessions (
      id TEXT PRIMARY KEY,
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      token_hash TEXT NOT NULL UNIQUE,
      status TEXT NOT NULL CHECK(status IN ('started','completed','expired')),
      started_at INTEGER NOT NULL,
      completed_at INTEGER,
      created_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS conversion_records (
      id TEXT PRIMARY KEY,
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      points_amount INTEGER NOT NULL CHECK(points_amount > 0),
      token_amount INTEGER NOT NULL CHECK(token_amount > 0),
      rate_bps INTEGER NOT NULL CHECK(rate_bps > 0),
      idempotency_key TEXT NOT NULL UNIQUE,
      created_at TEXT NOT NULL
    );

    CREATE INDEX IF NOT EXISTS idx_conversion_user_created ON conversion_records(user_id, created_at DESC);

    CREATE TABLE IF NOT EXISTS sessions (
      id TEXT PRIMARY KEY,
      token_hash TEXT NOT NULL UNIQUE,
      user_id TEXT REFERENCES users(id) ON DELETE CASCADE,
      role TEXT NOT NULL CHECK(role IN ('user','admin')),
      expires_at INTEGER NOT NULL,
      created_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS idempotency_responses (
      scope TEXT NOT NULL,
      key TEXT NOT NULL,
      response_json TEXT NOT NULL,
      created_at TEXT NOT NULL,
      PRIMARY KEY(scope, key)
    );

    CREATE TABLE IF NOT EXISTS audit_logs (
      id TEXT PRIMARY KEY,
      actor_type TEXT NOT NULL,
      actor_id TEXT NOT NULL,
      action TEXT NOT NULL,
      target_type TEXT NOT NULL,
      target_id TEXT NOT NULL,
      before_json TEXT,
      after_json TEXT,
      ip TEXT NOT NULL,
      created_at TEXT NOT NULL
    );

    CREATE INDEX IF NOT EXISTS idx_audit_logs_created ON audit_logs(created_at DESC);
  `);
}


function ensureColumn(db, table, column, definition) {
  const columns = db.prepare(`PRAGMA table_info(${table})`).all();
  if (!columns.some((item) => item.name === column)) db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
}

function createPlatformSchema(db) {
  ensureColumn(db, 'users', 'telegram_numeric_id', 'TEXT');
  ensureColumn(db, 'users', 'telegram_phone', "TEXT NOT NULL DEFAULT ''");
  ensureColumn(db, 'users', 'phone_verified_at', 'TEXT');
  ensureColumn(db, 'users', 'login_id', "TEXT NOT NULL DEFAULT ''");
  ensureColumn(db, 'users', 'last_login_at', 'TEXT');
  ensureColumn(db, 'users', 'notes', "TEXT NOT NULL DEFAULT ''");
  ensureColumn(db, 'vip_plans', 'price_usdt_micros', 'INTEGER NOT NULL DEFAULT 0');
  ensureColumn(db, 'vip_plans', 'duration_days', 'INTEGER NOT NULL DEFAULT 30');
  ensureColumn(db, 'user_game_state', 'last_wheel_spin_day', 'TEXT');
  ensureColumn(db, 'user_game_state', 'wheel_spins_used', 'INTEGER NOT NULL DEFAULT 0');
  ensureColumn(db, 'user_game_state', 'last_wheel_spin_at', 'INTEGER NOT NULL DEFAULT 0');
  ensureColumn(db, 'user_game_state', 'last_wheel_segment_id', "TEXT NOT NULL DEFAULT ''");
  ensureColumn(db, 'wheel_segments', 'color', "TEXT NOT NULL DEFAULT '#17140d'");

  db.exec(`
    CREATE UNIQUE INDEX IF NOT EXISTS idx_users_login_id ON users(login_id) WHERE login_id <> '';
    CREATE INDEX IF NOT EXISTS idx_users_telegram_numeric ON users(telegram_numeric_id);
    CREATE INDEX IF NOT EXISTS idx_users_phone ON users(telegram_phone);

    CREATE TABLE IF NOT EXISTS site_pages (
      slug TEXT PRIMARY KEY,
      nav_label TEXT NOT NULL,
      title TEXT NOT NULL,
      hero_title TEXT NOT NULL,
      hero_accent TEXT NOT NULL DEFAULT '',
      hero_subtitle TEXT NOT NULL DEFAULT '',
      hero_description TEXT NOT NULL DEFAULT '',
      primary_cta_label TEXT NOT NULL DEFAULT '',
      primary_cta_url TEXT NOT NULL DEFAULT '',
      secondary_cta_label TEXT NOT NULL DEFAULT '',
      secondary_cta_url TEXT NOT NULL DEFAULT '',
      meta_title TEXT NOT NULL DEFAULT '',
      meta_description TEXT NOT NULL DEFAULT '',
      config_json TEXT NOT NULL DEFAULT '{}',
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      sort_order INTEGER NOT NULL DEFAULT 0,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS site_sections (
      id TEXT PRIMARY KEY,
      page_slug TEXT NOT NULL REFERENCES site_pages(slug) ON DELETE CASCADE,
      section_key TEXT NOT NULL,
      type TEXT NOT NULL,
      title TEXT NOT NULL DEFAULT '',
      subtitle TEXT NOT NULL DEFAULT '',
      content_json TEXT NOT NULL DEFAULT '{}',
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      sort_order INTEGER NOT NULL DEFAULT 0,
      updated_at TEXT NOT NULL,
      UNIQUE(page_slug, section_key)
    );

    CREATE TABLE IF NOT EXISTS token_allocations (
      id TEXT PRIMARY KEY,
      label TEXT NOT NULL,
      percentage_bps INTEGER NOT NULL CHECK(percentage_bps >= 0),
      token_amount INTEGER NOT NULL CHECK(token_amount >= 0),
      description TEXT NOT NULL DEFAULT '',
      vesting TEXT NOT NULL DEFAULT '',
      color TEXT NOT NULL DEFAULT '#d9a928',
      sort_order INTEGER NOT NULL DEFAULT 0,
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS roadmap_phases (
      id TEXT PRIMARY KEY,
      phase_no INTEGER NOT NULL,
      title TEXT NOT NULL,
      subtitle TEXT NOT NULL DEFAULT '',
      status TEXT NOT NULL DEFAULT 'upcoming' CHECK(status IN ('completed','current','upcoming','paused')),
      completion_percent INTEGER NOT NULL DEFAULT 0 CHECK(completion_percent BETWEEN 0 AND 100),
      start_at TEXT,
      end_at TEXT,
      items_json TEXT NOT NULL DEFAULT '[]',
      icon TEXT NOT NULL DEFAULT 'rocket',
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      sort_order INTEGER NOT NULL DEFAULT 0,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS whitepaper_chapters (
      id TEXT PRIMARY KEY,
      chapter_no INTEGER NOT NULL,
      title TEXT NOT NULL,
      summary TEXT NOT NULL DEFAULT '',
      content_html TEXT NOT NULL DEFAULT '',
      icon TEXT NOT NULL DEFAULT 'document',
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      sort_order INTEGER NOT NULL DEFAULT 0,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS presale_stages (
      id TEXT PRIMARY KEY,
      name TEXT NOT NULL,
      stage_no INTEGER NOT NULL,
      price_usdt_micros INTEGER NOT NULL CHECK(price_usdt_micros > 0),
      bonus_bps INTEGER NOT NULL DEFAULT 0 CHECK(bonus_bps >= 0),
      allocation_token_base INTEGER NOT NULL CHECK(allocation_token_base >= 0),
      sold_token_base INTEGER NOT NULL DEFAULT 0 CHECK(sold_token_base >= 0),
      min_usdt_micros INTEGER NOT NULL DEFAULT 10000000,
      max_usdt_micros INTEGER NOT NULL DEFAULT 100000000000,
      starts_at TEXT,
      ends_at TEXT,
      status TEXT NOT NULL DEFAULT 'upcoming' CHECK(status IN ('draft','upcoming','active','completed','paused')),
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      sort_order INTEGER NOT NULL DEFAULT 0,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS payment_orders (
      id TEXT PRIMARY KEY,
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      purpose TEXT NOT NULL CHECK(purpose IN ('vip','presale','deposit')),
      purpose_ref TEXT NOT NULL,
      network TEXT NOT NULL,
      asset TEXT NOT NULL DEFAULT 'USDT',
      amount_usdt_micros INTEGER NOT NULL CHECK(amount_usdt_micros > 0),
      destination_address TEXT NOT NULL DEFAULT '',
      payment_reference TEXT NOT NULL UNIQUE,
      tx_hash TEXT UNIQUE,
      status TEXT NOT NULL DEFAULT 'created' CHECK(status IN ('created','submitted','verifying','paid','rejected','expired','refunded')),
      metadata_json TEXT NOT NULL DEFAULT '{}',
      expires_at TEXT,
      submitted_at TEXT,
      paid_at TEXT,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL
    );
    CREATE INDEX IF NOT EXISTS idx_payment_orders_user ON payment_orders(user_id, created_at DESC);
    CREATE INDEX IF NOT EXISTS idx_payment_orders_status ON payment_orders(status, created_at DESC);

    CREATE TABLE IF NOT EXISTS presale_purchases (
      id TEXT PRIMARY KEY,
      order_id TEXT NOT NULL UNIQUE REFERENCES payment_orders(id) ON DELETE RESTRICT,
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      stage_id TEXT NOT NULL REFERENCES presale_stages(id),
      usdt_micros INTEGER NOT NULL CHECK(usdt_micros > 0),
      token_base INTEGER NOT NULL CHECK(token_base > 0),
      bonus_token_base INTEGER NOT NULL DEFAULT 0 CHECK(bonus_token_base >= 0),
      status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','allocated','cancelled','refunded')),
      created_at TEXT NOT NULL,
      allocated_at TEXT
    );

    CREATE TABLE IF NOT EXISTS deposits (
      id TEXT PRIMARY KEY,
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      asset TEXT NOT NULL CHECK(asset IN ('USDT','OC_TOKEN')),
      network TEXT NOT NULL,
      amount_base INTEGER NOT NULL CHECK(amount_base > 0),
      tx_hash TEXT NOT NULL UNIQUE,
      from_address TEXT NOT NULL DEFAULT '',
      to_address TEXT NOT NULL DEFAULT '',
      confirmations INTEGER NOT NULL DEFAULT 0,
      status TEXT NOT NULL DEFAULT 'submitted' CHECK(status IN ('submitted','verifying','confirmed','credited','rejected','reversed')),
      metadata_json TEXT NOT NULL DEFAULT '{}',
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL,
      credited_at TEXT
    );
    CREATE INDEX IF NOT EXISTS idx_deposits_user ON deposits(user_id, created_at DESC);

    CREATE TABLE IF NOT EXISTS withdrawal_addresses (
      id TEXT PRIMARY KEY,
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      asset TEXT NOT NULL CHECK(asset IN ('USDT','OC_TOKEN')),
      network TEXT NOT NULL,
      address TEXT NOT NULL,
      label TEXT NOT NULL DEFAULT '',
      status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','disabled','review')),
      created_at TEXT NOT NULL,
      UNIQUE(user_id, asset, network, address)
    );

    CREATE TABLE IF NOT EXISTS withdrawals (
      id TEXT PRIMARY KEY,
      user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      address_id TEXT NOT NULL REFERENCES withdrawal_addresses(id),
      asset TEXT NOT NULL CHECK(asset IN ('USDT','OC_TOKEN')),
      network TEXT NOT NULL,
      amount_base INTEGER NOT NULL CHECK(amount_base > 0),
      fee_base INTEGER NOT NULL DEFAULT 0 CHECK(fee_base >= 0),
      tx_hash TEXT UNIQUE,
      status TEXT NOT NULL DEFAULT 'requested' CHECK(status IN ('requested','review','approved','broadcast','confirmed','rejected','cancelled','failed')),
      note TEXT NOT NULL DEFAULT '',
      requested_at TEXT NOT NULL,
      reviewed_at TEXT,
      completed_at TEXT,
      updated_at TEXT NOT NULL
    );
    CREATE INDEX IF NOT EXISTS idx_withdrawals_user ON withdrawals(user_id, requested_at DESC);
    CREATE INDEX IF NOT EXISTS idx_withdrawals_status ON withdrawals(status, requested_at DESC);

    CREATE TABLE IF NOT EXISTS point_transfers (
      id TEXT PRIMARY KEY,
      sender_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      recipient_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      amount_points INTEGER NOT NULL CHECK(amount_points > 0),
      fee_points INTEGER NOT NULL DEFAULT 0 CHECK(fee_points >= 0),
      note TEXT NOT NULL DEFAULT '',
      idempotency_key TEXT NOT NULL UNIQUE,
      status TEXT NOT NULL DEFAULT 'completed' CHECK(status IN ('completed','reversed','review')),
      created_at TEXT NOT NULL,
      CHECK(sender_id <> recipient_id)
    );
    CREATE INDEX IF NOT EXISTS idx_point_transfers_sender ON point_transfers(sender_id, created_at DESC);
    CREATE INDEX IF NOT EXISTS idx_point_transfers_recipient ON point_transfers(recipient_id, created_at DESC);

    CREATE TABLE IF NOT EXISTS telegram_contacts (
      id TEXT PRIMARY KEY,
      telegram_user_id TEXT NOT NULL,
      user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
      phone_number TEXT NOT NULL,
      first_name TEXT NOT NULL DEFAULT '',
      last_name TEXT NOT NULL DEFAULT '',
      verified INTEGER NOT NULL DEFAULT 0 CHECK(verified IN (0,1)),
      update_id TEXT NOT NULL UNIQUE,
      created_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS admin_notifications (
      id TEXT PRIMARY KEY,
      type TEXT NOT NULL,
      title TEXT NOT NULL,
      message TEXT NOT NULL,
      severity TEXT NOT NULL DEFAULT 'info' CHECK(severity IN ('info','success','warning','critical')),
      read_at TEXT,
      created_at TEXT NOT NULL
    );
  `);
}


function createPaymentSchema(db) {
  ensureColumn(db, 'payment_orders', 'provider_id', "TEXT NOT NULL DEFAULT ''");
  ensureColumn(db, 'payment_orders', 'currency_code', "TEXT NOT NULL DEFAULT 'USDT'");
  ensureColumn(db, 'payment_orders', 'amount_minor', 'INTEGER NOT NULL DEFAULT 0');
  ensureColumn(db, 'payment_orders', 'settlement_currency', "TEXT NOT NULL DEFAULT 'USDT'");
  ensureColumn(db, 'payment_orders', 'settlement_amount_minor', 'INTEGER NOT NULL DEFAULT 0');
  ensureColumn(db, 'payment_orders', 'exchange_rate_e8', 'INTEGER NOT NULL DEFAULT 100000000');
  ensureColumn(db, 'payment_orders', 'provider_order_id', "TEXT NOT NULL DEFAULT ''");
  ensureColumn(db, 'payment_orders', 'checkout_url', "TEXT NOT NULL DEFAULT ''");
  ensureColumn(db, 'payment_orders', 'payment_method_type', "TEXT NOT NULL DEFAULT 'crypto_transfer'");

  db.exec(`
    CREATE TABLE IF NOT EXISTS fiat_currencies (
      code TEXT PRIMARY KEY,
      name TEXT NOT NULL,
      symbol TEXT NOT NULL,
      decimals INTEGER NOT NULL DEFAULT 2 CHECK(decimals BETWEEN 0 AND 8),
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      is_base INTEGER NOT NULL DEFAULT 0 CHECK(is_base IN (0,1)),
      sort_order INTEGER NOT NULL DEFAULT 0,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS fx_rates (
      currency_code TEXT PRIMARY KEY REFERENCES fiat_currencies(code) ON DELETE CASCADE,
      rate_to_try_e8 INTEGER NOT NULL CHECK(rate_to_try_e8 > 0),
      source TEXT NOT NULL DEFAULT 'manual',
      is_demo INTEGER NOT NULL DEFAULT 0 CHECK(is_demo IN (0,1)),
      fetched_at TEXT,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS payment_providers (
      id TEXT PRIMARY KEY,
      name TEXT NOT NULL,
      category TEXT NOT NULL CHECK(category IN ('card','bank','wallet','crypto','generic')),
      adapter TEXT NOT NULL,
      description TEXT NOT NULL DEFAULT '',
      enabled INTEGER NOT NULL DEFAULT 0 CHECK(enabled IN (0,1)),
      test_mode INTEGER NOT NULL DEFAULT 1 CHECK(test_mode IN (0,1)),
      sort_order INTEGER NOT NULL DEFAULT 0,
      config_json TEXT NOT NULL DEFAULT '{}',
      secrets_enc TEXT NOT NULL DEFAULT '',
      capabilities_json TEXT NOT NULL DEFAULT '{}',
      callback_path TEXT NOT NULL DEFAULT '',
      status TEXT NOT NULL DEFAULT 'not_configured' CHECK(status IN ('not_configured','configured','verified','error','disabled')),
      last_tested_at TEXT,
      last_error TEXT NOT NULL DEFAULT '',
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS payment_provider_currencies (
      provider_id TEXT NOT NULL REFERENCES payment_providers(id) ON DELETE CASCADE,
      currency_code TEXT NOT NULL,
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      min_amount_minor INTEGER NOT NULL DEFAULT 100,
      max_amount_minor INTEGER NOT NULL DEFAULT 100000000000,
      fee_bps INTEGER NOT NULL DEFAULT 0 CHECK(fee_bps BETWEEN 0 AND 10000),
      fixed_fee_minor INTEGER NOT NULL DEFAULT 0 CHECK(fixed_fee_minor >= 0),
      PRIMARY KEY(provider_id,currency_code)
    );

    CREATE TABLE IF NOT EXISTS bank_accounts (
      id TEXT PRIMARY KEY,
      currency_code TEXT NOT NULL,
      bank_name TEXT NOT NULL,
      account_holder TEXT NOT NULL,
      iban TEXT NOT NULL DEFAULT '',
      swift_bic TEXT NOT NULL DEFAULT '',
      account_number TEXT NOT NULL DEFAULT '',
      branch_name TEXT NOT NULL DEFAULT '',
      branch_code TEXT NOT NULL DEFAULT '',
      country_code TEXT NOT NULL DEFAULT 'TR',
      instructions TEXT NOT NULL DEFAULT '',
      min_amount_minor INTEGER NOT NULL DEFAULT 0,
      max_amount_minor INTEGER NOT NULL DEFAULT 0,
      enabled INTEGER NOT NULL DEFAULT 0 CHECK(enabled IN (0,1)),
      sort_order INTEGER NOT NULL DEFAULT 0,
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS crypto_assets (
      id TEXT PRIMARY KEY,
      symbol TEXT NOT NULL,
      name TEXT NOT NULL,
      network TEXT NOT NULL,
      chain_family TEXT NOT NULL CHECK(chain_family IN ('EVM','BITCOIN','TRON','TON','OTHER')),
      asset_type TEXT NOT NULL CHECK(asset_type IN ('native','token')),
      contract_address TEXT NOT NULL DEFAULT '',
      decimals INTEGER NOT NULL DEFAULT 8 CHECK(decimals BETWEEN 0 AND 30),
      deposit_address TEXT NOT NULL DEFAULT '',
      rpc_url TEXT NOT NULL DEFAULT '',
      explorer_url TEXT NOT NULL DEFAULT '',
      confirmations_required INTEGER NOT NULL DEFAULT 1 CHECK(confirmations_required >= 0),
      manual_price_usd_e8 INTEGER NOT NULL DEFAULT 0 CHECK(manual_price_usd_e8 >= 0),
      price_source TEXT NOT NULL DEFAULT 'manual',
      enabled INTEGER NOT NULL DEFAULT 0 CHECK(enabled IN (0,1)),
      purchase_enabled INTEGER NOT NULL DEFAULT 0 CHECK(purchase_enabled IN (0,1)),
      deposit_enabled INTEGER NOT NULL DEFAULT 0 CHECK(deposit_enabled IN (0,1)),
      withdrawal_enabled INTEGER NOT NULL DEFAULT 0 CHECK(withdrawal_enabled IN (0,1)),
      min_payment_base INTEGER NOT NULL DEFAULT 0,
      max_payment_base INTEGER NOT NULL DEFAULT 0,
      sort_order INTEGER NOT NULL DEFAULT 0,
      metadata_json TEXT NOT NULL DEFAULT '{}',
      updated_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS vip_plan_prices (
      tier INTEGER NOT NULL REFERENCES vip_plans(tier) ON DELETE CASCADE,
      currency_code TEXT NOT NULL,
      amount_minor INTEGER NOT NULL CHECK(amount_minor >= 0),
      enabled INTEGER NOT NULL DEFAULT 1 CHECK(enabled IN (0,1)),
      updated_at TEXT NOT NULL,
      PRIMARY KEY(tier,currency_code)
    );

    CREATE TABLE IF NOT EXISTS payment_checkout_sessions (
      id TEXT PRIMARY KEY,
      order_id TEXT NOT NULL REFERENCES payment_orders(id) ON DELETE CASCADE,
      provider_id TEXT NOT NULL REFERENCES payment_providers(id),
      currency_code TEXT NOT NULL,
      amount_minor INTEGER NOT NULL CHECK(amount_minor > 0),
      provider_reference TEXT NOT NULL DEFAULT '',
      checkout_url TEXT NOT NULL DEFAULT '',
      qr_payload TEXT NOT NULL DEFAULT '',
      instructions_json TEXT NOT NULL DEFAULT '{}',
      status TEXT NOT NULL DEFAULT 'created' CHECK(status IN ('created','ready','pending','paid','failed','expired','cancelled')),
      expires_at TEXT,
      created_at TEXT NOT NULL,
      updated_at TEXT NOT NULL,
      UNIQUE(order_id,provider_id)
    );
    CREATE INDEX IF NOT EXISTS idx_checkout_provider_reference ON payment_checkout_sessions(provider_id,provider_reference);

    CREATE TABLE IF NOT EXISTS payment_webhook_events (
      id TEXT PRIMARY KEY,
      provider_id TEXT NOT NULL,
      provider_event_id TEXT NOT NULL,
      signature_valid INTEGER NOT NULL DEFAULT 0 CHECK(signature_valid IN (0,1)),
      status TEXT NOT NULL DEFAULT 'received' CHECK(status IN ('received','processed','duplicate','rejected','failed')),
      payload_json TEXT NOT NULL DEFAULT '{}',
      error_message TEXT NOT NULL DEFAULT '',
      created_at TEXT NOT NULL,
      processed_at TEXT,
      UNIQUE(provider_id,provider_event_id)
    );
  `);
}

function setDefaults(db) {
  const insertSetting = db.prepare(`INSERT OR IGNORE INTO settings(key, value, updated_at) VALUES(?, ?, ?)`);
  for (const [key, value] of Object.entries(defaultSettings)) {
    insertSetting.run(key, JSON.stringify(value), nowIso());
  }

  const vipSeed = [
    [1, 'VIP 1', 'Başlangıç', 25000, 8999, 12000, 12000, 12000, 1, 11000],
    [2, 'VIP 2', 'Tecrübeli', 60000, 17999, 15000, 14000, 15000, 2, 12000],
    [3, 'VIP 3', 'Uzman', 150000, 34999, 18000, 16000, 18000, 3, 13000],
    [4, 'VIP 4', 'Efsane', 350000, 69999, 22000, 18000, 22000, 4, 14000],
    [5, 'VIP 5', 'Efsanelerin Kralı', 750000, 139999, 30000, 22000, 30000, 5, 15000]
  ];
  const vipInsert = db.prepare(`
    INSERT OR IGNORE INTO vip_plans(
      tier, name, subtitle, price_points, price_try_cents, tap_multiplier_bps,
      energy_multiplier_bps, auto_multiplier_bps, daily_free_spins,
      referral_multiplier_bps, enabled, updated_at
    ) VALUES(?,?,?,?,?,?,?,?,?,?,1,?)
  `);
  for (const row of vipSeed) vipInsert.run(...row, nowIso());
  db.exec(`UPDATE vip_plans SET daily_free_spins=tier WHERE daily_free_spins=tier+1 AND tier BETWEEN 1 AND 5;`);

  const questSeed = [
    ['tap-100', '100 kez dokun', 'Bugün 100 doğrulanmış dokunuş yap.', 'tap', 100, 150, 'daily', 10],
    ['spin-1', 'Çarkı çevir', 'Bugün en az bir kez şans çarkını çevir.', 'spin', 1, 75, 'daily', 20],
    ['referral-1', 'Bir arkadaş davet et', 'Bir arkadaşını davet et ve nitelikli kullanıcı olmasını sağla.', 'referral', 1, 500, 'once', 40],
    ['convert-1', 'İlk dönüşümünü yap', 'OC_POINTS bakiyenden ilk OC_TOKEN dönüşümünü tamamla.', 'convert', 1, 300, 'once', 50]
  ];
  const questInsert = db.prepare(`
    INSERT OR IGNORE INTO quests(id,title,description,event_type,target_count,reward_points,repeat_type,sort_order,enabled,updated_at)
    VALUES(?,?,?,?,?,?,?,?,1,?)
  `);
  for (const row of questSeed) questInsert.run(...row, nowIso());

  const segmentSeed = [
    ['jackpot', '10.000 OC_POINTS', 'points', 10000, 1, 1, '#4a174e'],
    ['points-2500', '2.500 OC_POINTS', 'points', 2500, 5, 2, '#25180b'],
    ['energy-1000', '1.000 Enerji', 'energy', 1000, 10, 3, '#15140f'],
    ['booster-x2', 'x2 Tap / 15 dk', 'booster', 20000, 12, 4, '#26170b'],
    ['points-750', '750 OC_POINTS', 'points', 750, 20, 5, '#15140f'],
    ['vip-trial', 'VIP 1 / 24 Saat', 'vip_trial', 86400, 8, 6, '#24160a'],
    ['energy-500', '500 Enerji', 'energy', 500, 24, 7, '#15140f']
  ];
  const segInsert = db.prepare(`
    INSERT OR IGNORE INTO wheel_segments(id,label,reward_type,reward_value,weight,sort_order,color,enabled,updated_at)
    VALUES(?,?,?,?,?,?,?,1,?)
  `);
  for (const row of segmentSeed) segInsert.run(...row, nowIso());

  const systemAccounts = [
    ['sys-points-reward', null, 'OC_POINTS', 'sys:points:reward', 'Oyun Ödül Havuzu', 1],
    ['sys-points-quest', null, 'OC_POINTS', 'sys:points:quest', 'Görev Ödül Havuzu', 1],
    ['sys-points-referral', null, 'OC_POINTS', 'sys:points:referral', 'Referans Ödül Havuzu', 1],
    ['sys-points-admin', null, 'OC_POINTS', 'sys:points:admin', 'Yönetici Dağıtım Havuzu', 1],
    ['sys-points-sink', null, 'OC_POINTS', 'sys:points:sink', 'Dönüşüm Yakım Havuzu', 1],
    ['sys-points-revenue', null, 'OC_POINTS', 'sys:points:revenue', 'Oyun İçi Harcama Havuzu', 1],
    ['sys-token-issuance', null, 'OC_TOKEN', 'sys:token:issuance', 'Token İhraç Hesabı', 1],
    ['sys-token-treasury', null, 'OC_TOKEN', 'sys:token:treasury', 'Token Dağıtım Hazinesi', 0]
  ];
  const accountInsert = db.prepare(`
    INSERT OR IGNORE INTO ledger_accounts(id,user_id,asset,code,name,allow_negative,balance,created_at)
    VALUES(?,?,?,?,?,?,0,?)
  `);
  for (const row of systemAccounts) accountInsert.run(...row, nowIso());

  // Treasury funding is never fabricated during installation. Real allocations are
  // created only by validated presale finalization, deposit or authorized admin workflows.

}


function seedPlatformDefaults(db) {
  const now = nowIso();

  const vipUsdt = [
    [1, 9900000, 30],
    [2, 19900000, 30],
    [3, 49900000, 30],
    [4, 99900000, 30],
    [5, 199900000, 30]
  ];
  const updateVip = db.prepare('UPDATE vip_plans SET price_usdt_micros=CASE WHEN price_usdt_micros=0 THEN ? ELSE price_usdt_micros END,duration_days=CASE WHEN duration_days=0 THEN ? ELSE duration_days END WHERE tier=?');
  for (const [tier, price, days] of vipUsdt) updateVip.run(price, days, tier);

  const systemAccounts = [
    ['sys-points-transfer-fee', null, 'OC_POINTS', 'sys:points:transfer-fee', 'Point Transfer Fee Pool', 0],
    ['sys-token-presale', null, 'OC_TOKEN', 'sys:token:presale', 'Presale Token Pool', 1],
    ['sys-token-withdrawal-clearing', null, 'OC_TOKEN', 'sys:token:withdrawal-clearing', 'Token Withdrawal Clearing', 0],
    ['sys-token-withdrawal-fee', null, 'OC_TOKEN', 'sys:token:withdrawal-fee', 'Token Withdrawal Fee Pool', 0],
    ['sys-usdt-issuance', null, 'USDT', 'sys:usdt:issuance', 'USDT External Issuance', 1],
    ['sys-usdt-treasury', null, 'USDT', 'sys:usdt:treasury', 'USDT Treasury', 0],
    ['sys-usdt-vip-revenue', null, 'USDT', 'sys:usdt:vip-revenue', 'VIP USDT Revenue', 0],
    ['sys-usdt-presale-revenue', null, 'USDT', 'sys:usdt:presale-revenue', 'Presale USDT Revenue', 0],
    ['sys-usdt-withdrawal-clearing', null, 'USDT', 'sys:usdt:withdrawal-clearing', 'USDT Withdrawal Clearing', 0],
    ['sys-usdt-withdrawal-fee', null, 'USDT', 'sys:usdt:withdrawal-fee', 'USDT Withdrawal Fee Pool', 0]
  ];
  const insertAccount = db.prepare(`INSERT OR IGNORE INTO ledger_accounts(id,user_id,asset,code,name,allow_negative,balance,created_at) VALUES(?,?,?,?,?,?,0,?)`);
  for (const row of systemAccounts) insertAccount.run(...row, now);

  const pages = [
    ['home','Ana Sayfa','OnlyCoin Ana Sayfa','Powering','The Future of Digital Value','OnlyCoin ekosistemine hoş geldiniz.','Hız, güvenlik, topluluk ve gerçek kullanım senaryoları için tasarlanmış yeni nesil dijital değer ekosistemi.','OnlyCoin Al','/presale','Whitepaper','/whitepaper','OnlyCoin — Dijital Değer Ekosistemi','OnlyCoin tap-to-earn, presale, tokenomics ve roadmap platformu',10],
    ['presale','Presale','OnlyCoin Presale','OnlyCoin','Presale Is Live','Lansmandan önce ekosisteme katılın.','Aktif satış aşamasını, fiyatları, bonusları ve topluluk ilerlemesini canlı olarak takip edin.','Presale Katıl','/game/#presale','Nasıl Alınır','#how-to-buy','OnlyCoin Presale','OnlyCoin ön satış aşamaları ve token satın alma bilgileri',20],
    ['tokenomics','Tokenomics','OnlyCoin Tokenomics','OnlyCoin','Tokenomics','Şeffaf dağılım. Sürdürülebilir büyüme.','Toplam arz, tahsisat, vesting ve kullanım alanlarını tek sayfada inceleyin.','Whitepaper','/whitepaper','Presale','/presale','OnlyCoin Tokenomics','OnlyCoin arz, tahsisat ve vesting modeli',30],
    ['roadmap','Roadmap','OnlyCoin Roadmap','OnlyCoin','Roadmap','Bir sonraki kilometre taşına birlikte.','Altyapıdan global benimsemeye kadar tüm geliştirme aşamalarını yöneticiler canlı olarak güncelleyebilir.','Topluluğa Katıl','/game/','Whitepaper','/whitepaper','OnlyCoin Roadmap','OnlyCoin geliştirme yol haritası',40],
    ['whitepaper','Whitepaper','OnlyCoin Whitepaper','OnlyCoin','Whitepaper','Dijital değerin geleceğine yönelik tam rehber.','Vizyon, teknoloji, tokenomics, güvenlik, yönetim ve yol haritası tek belgede.','Whitepaper İndir','#download','Özeti Oku','#chapters','OnlyCoin Whitepaper','OnlyCoin teknik ve ekonomik whitepaper',50]
  ];
  const pageInsert = db.prepare(`INSERT OR IGNORE INTO site_pages(slug,nav_label,title,hero_title,hero_accent,hero_subtitle,hero_description,primary_cta_label,primary_cta_url,secondary_cta_label,secondary_cta_url,meta_title,meta_description,config_json,enabled,sort_order,updated_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,'{}',1,?,?)`);
  for (const row of pages) pageInsert.run(...row, now);

  const sections = [
    ['home-stats','home','stats','stats','Canlı Ekosistem','Sunucu verileri ve yönetim paneli ayarlarıyla güncellenir',JSON.stringify({items:[{key:'price',label:'OnlyCoin Price',value:'$0.0125'},{key:'marketCap',label:'Market Cap',value:'Henüz yayınlanmadı'},{key:'holders',label:'Holders',value:'Canlı Kullanıcılar'},{key:'volume',label:'24H Volume',value:'Henüz yayınlanmadı'}]}),10],
    ['home-features','home','features','cards','Güvenli, Hızlı ve Topluluk Odaklı','',JSON.stringify({items:[{title:'Sunucu Otoriteli',text:'Tap, görev, VIP ve transfer işlemleri istemcide değil sunucuda doğrulanır.'},{title:'Çift Taraflı Ledger',text:'OC_POINTS, OC_TOKEN ve USDT hareketleri denetlenebilir muhasebe kayıtlarıyla tutulur.'},{title:'Telegram Kimliği',text:'Mini App ve web girişi aynı Telegram kullanıcı kimliğini kullanır.'},{title:'Admin Yönetimi',text:'Site içeriği, presale, VIP, sözleşmeler ve üyeler tek panelden yönetilir.'}]}),20],
    ['presale-how','presale','how-to-buy','steps','OnlyCoin Nasıl Alınır?','',JSON.stringify({items:[{title:'Telegram ile Giriş',text:'Telegram hesabınızla güvenli oturum açın.'},{title:'USDT Siparişi Oluşturun',text:'Aktif aşamayı ve almak istediğiniz USDT miktarını seçin.'},{title:'Transferi Doğrulayın',text:'İşlem hashini gönderin; ödeme yalnızca doğrulama sonrasında kabul edilir.'},{title:'Token Tahsisi',text:'Ödeme onaylandığında OC_TOKEN bakiyenize tahsis edilir.'}]}),10],
    ['presale-trust','presale','trust','cards','Güvenli ve Şeffaf Presale','Doğrulanabilir akışlar, açık aşamalar ve yönetilebilir limitler',JSON.stringify({items:[{title:'Sunucu Doğrulaması',text:'Sipariş, ödeme ve tahsis işlemleri istemciye güvenmeden sunucuda doğrulanır.'},{title:'Aşama Bazlı Fiyat',text:'Fiyat, bonus, kota ve tarihler her satış aşaması için ayrı yönetilir.'},{title:'İşlem İzleri',text:'Ödeme, tahsis ve yönetici işlemleri audit ve ledger kayıtlarıyla izlenir.'},{title:'Bölgesel Uyum',text:'Ödeme yöntemleri, KYC ve ülke politikaları yönetim panelinden sınırlandırılabilir.'}]}),5],
    ['presale-faq','presale','faq','faq','Sık Sorulan Sorular','',JSON.stringify({items:[{q:'Presale fiyatı nasıl belirlenir?',a:'Fiyatlar ve bonuslar yönetim panelindeki satış aşamalarından düzenlenir.'},{q:'Hangi ağ kullanılır?',a:'Ağ, USDT kontratı ve hazine adresi yönetim panelinden yapılandırılır.'},{q:'Token ne zaman kullanılabilir?',a:'Lansman ve dönüşüm kilidi yönetim panelindeki sayaç ve politika ayarlarına bağlıdır.'}]}),30],
    ['tokenomics-utility','tokenomics','utility','cards','OC Token Kullanım Alanları','Ekosistem içindeki temel işlevler',JSON.stringify({items:[{title:'Ödemeler ve İşlemler',text:'Desteklenen ürün, hizmet ve ekosistem içi işlemlerde kullanım.'},{title:'Staking ve Ödüller',text:'Uygunluk ve bölgesel politikalara bağlı uzun vadeli katılım teşvikleri.'},{title:'Yönetişim',text:'Topluluk önerileri ve gelecekteki yönetişim kararlarına katılım.'},{title:'Ekosistem Erişimi',text:'VIP özellikleri, kampanyalar ve partner uygulamalarında kullanım.'}]}),10],
    ['tokenomics-why','tokenomics','why','cards','Tokenomics Neden Güçlü?','Uzun vadeli değer ve kontrollü emisyon yaklaşımı',JSON.stringify({items:[{title:'Topluluk Önceliği',text:'Arzın önemli bölümü topluluk ve ekosistem büyümesine ayrılır.'},{title:'Vesting Disiplini',text:'Ekip, danışman ve rezerv tahsisleri zamana yayılan kilitlerle korunur.'},{title:'Likidite Planı',text:'Piyasa derinliği ve sürdürülebilir işlem deneyimi için ayrılmış havuz.'},{title:'Şeffaf Yönetim',text:'Dağılım, kurallar ve değişiklikler yönetim paneli ve audit kayıtlarıyla izlenir.'}]}),20],
    ['roadmap-ecosystem','roadmap','ecosystem','cards','Ekosistem Geliştirme','Ürünün büyümesini taşıyan dört temel alan',JSON.stringify({items:[{title:'Cüzdan Entegrasyonu',text:'Web, Telegram ve mobil istemciler için ortak güvenli cüzdan deneyimi.'},{title:'Staking Platformu',text:'Uyum onayı sonrası yapılandırılabilir staking ve ödül modülleri.'},{title:'Yönetişim Sistemi',text:'Topluluk önerileri, oylama ve denetlenebilir karar akışları.'},{title:'Partner Ağı',text:'Ödeme, borsa, oyun ve Web3 ekosistemiyle stratejik entegrasyonlar.'}]}),10],
    ['whitepaper-summary','whitepaper','summary','text','Executive Summary','',JSON.stringify({text:'OnlyCoin; Telegram Mini App, web, Android ve iOS istemcilerinin aynı sunucu otoriteli ekonomi motorunu kullandığı, OC_POINTS ile OC_TOKEN varlıklarını ayrı ledger hesaplarında yöneten bir dijital ekosistemdir.'}),10],
    ['whitepaper-highlights','whitepaper','highlights','cards','Whitepaper Öne Çıkanlar','Vizyon, teknoloji, utility, güvenlik ve yönetişim',JSON.stringify({items:[{title:'Vizyon',text:'Dijital değeri erişilebilir, şeffaf ve topluluk odaklı hale getiren ekosistem.'},{title:'Teknoloji',text:'Sunucu otoriteli oyun motoru, idempotent işlemler ve çift taraflı ledger.'},{title:'Utility',text:'Oyun, VIP, presale ve gelecekteki partner kullanım alanları.'},{title:'Güvenlik',text:'Doğrulama katmanları, audit kayıtları ve kontrollü finans akışları.'},{title:'Yönetişim',text:'Aşamalı topluluk katılımı ve denetlenebilir karar mekanizmaları.'}]}),20],
    ['whitepaper-technology','whitepaper','technology','cards','Teknoloji Genel Bakış','OnlyCoin altyapısının temel bileşenleri',JSON.stringify({items:[{title:'Akıllı Sözleşmeler',text:'Standart, test edilebilir ve harici denetime hazır sözleşme katmanı.'},{title:'Çoklu Ağ Hazırlığı',text:'EVM, TRON, Bitcoin ve TON sağlayıcı adaptörleri için genişletilebilir mimari.'},{title:'Cüzdan Entegrasyonu',text:'Telegram, web ve mobil istemcilerde ortak kullanıcı kimliği.'},{title:'Staking ve Ödüller',text:'Kural sürümü, bütçe ve eligibility ile yönetilen modüler ödül sistemi.'},{title:'Yönetişim',text:'Gelecekteki DAO ve topluluk oylaması için hazırlanmış veri modeli.'}]}),30],
    ['whitepaper-why','whitepaper','why','cards','Whitepaper Neden Okunmalı?','Karar vermeden önce modelin tamamını inceleyin',JSON.stringify({items:[{title:'Şeffaflık',text:'Ekonomi, dağılım, vesting ve teknik sınırlar açıkça tanımlanır.'},{title:'Uzun Vadeli Strateji',text:'Lansmandan yönetişime kadar aşamalı büyüme planını gösterir.'},{title:'Gerçek Utility',text:'OC_POINTS ve OC_TOKEN ayrımını ve kullanım senaryolarını açıklar.'},{title:'Risk Farkındalığı',text:'Finansal, teknik ve mevzuat gereksinimlerini gerçekçi biçimde ortaya koyar.'}]}),40]
  ];
  const sectionInsert = db.prepare(`INSERT OR IGNORE INTO site_sections(id,page_slug,section_key,type,title,subtitle,content_json,enabled,sort_order,updated_at) VALUES(?,?,?,?,?,?,?,1,?,?)`);
  for (const row of sections) sectionInsert.run(...row, now);

  const allocations = [
    ['community','Community & Ecosystem',4000,4000000000,'Topluluk büyümesi, görevler ve ekosistem teşvikleri','10% TGE, 24 ay lineer','#d6a62b',10],
    ['liquidity','Liquidity',2000,2000000000,'DEX/CEX likiditesi ve piyasa derinliği','TGE planına göre','#f1c75b',20],
    ['team','Team',1500,1500000000,'Çekirdek ekip ve ürün geliştirme','6 ay cliff, 24 ay lineer','#8d8d8d',30],
    ['marketing','Marketing & Partnerships',1000,1000000000,'Küresel büyüme ve stratejik iş birlikleri','10% TGE, 12 ay lineer','#696969',40],
    ['advisors','Advisors',500,500000000,'Danışman ve uzman katkıları','6 ay cliff, 18 ay lineer','#555555',50],
    ['treasury','Treasury',500,500000000,'Uzun vadeli yönetim ve rezerv','3 ay cliff, 24 ay lineer','#444444',60],
    ['staking','Staking Rewards',500,500000000,'Ağ katılımı ve ödül havuzu','36 ay emisyon','#333333',70]
  ];
  const allocationInsert = db.prepare(`INSERT OR IGNORE INTO token_allocations(id,label,percentage_bps,token_amount,description,vesting,color,sort_order,enabled,updated_at) VALUES(?,?,?,?,?,?,?,?,1,?)`);
  for (const row of allocations) allocationInsert.run(...row, now);

  // Earlier builds shipped with a 400B placeholder supply setting while the managed
  // allocation table totals 10B. Migrate only that exact legacy default so
  // administrator-defined supplies remain untouched.
  const legacySupply = db.prepare(`SELECT value FROM settings WHERE key='presale_total_token_base_units'`).get();
  const allocationSupply = Number(db.prepare(`SELECT COALESCE(SUM(token_amount),0) AS total FROM token_allocations WHERE enabled=1`).get()?.total || 0);
  let parsedLegacySupply = 0;
  try { parsedLegacySupply = Number(JSON.parse(legacySupply?.value ?? '0')); } catch { parsedLegacySupply = Number(legacySupply?.value || 0); }
  if (parsedLegacySupply === 400_000_000_000 && allocationSupply === 10_000_000_000) {
    db.prepare(`UPDATE settings SET value=?, updated_at=? WHERE key='presale_total_token_base_units'`).run(JSON.stringify(allocationSupply), now);
  }

  const phases = [
    ['phase-1',1,'Foundation','Marka ve altyapı','completed',100,'["Marka kimliği","Web sitesi","Akıllı sözleşme tasarımı","Topluluk kanalları"]','flag',10],
    ['phase-2',2,'Presale & Audit','Satış ve doğrulama','completed',100,'["Presale altyapısı","KYC planı","Sözleşme denetimi hazırlığı","Telegram Mini App"]','shield',20],
    ['phase-3',3,'Expansion','Token ve oyun büyümesi','current',68,'["Tap-to-earn motoru","VIP ve görevler","USDT ödeme emirleri","Topluluk kampanyaları"]','rocket',30],
    ['phase-4',4,'Adoption','Listeleme ve kullanım','upcoming',0,'["CEX başvuruları","Utility entegrasyonları","Mobil yayın","Global pazarlama"]','chart',40],
    ['phase-5',5,'Ecosystem Dominance','Yönetim ve genişleme','upcoming',0,'["Multi-chain","DAO yönetişimi","dApp ekosistemi","Merchant kullanım"]','crown',50]
  ];
  const phaseInsert = db.prepare(`INSERT OR IGNORE INTO roadmap_phases(id,phase_no,title,subtitle,status,completion_percent,items_json,icon,enabled,sort_order,updated_at) VALUES(?,?,?,?,?,?,?, ?,1,?,?)`);
  for (const row of phases) phaseInsert.run(...row, now);

  const chapters = [
    ['chapter-1',1,'Introduction','Vizyon, misyon ve dijital değer yaklaşımı.','<p>OnlyCoin ekosisteminin amaçlarını, kullanıcı deneyimini ve platform kapsamını açıklar.</p>','rocket',10],
    ['chapter-2',2,'Problem & Solution','Geleneksel ödül sistemlerinin problemleri ve çözüm yaklaşımı.','<p>Şeffaf ledger, sunucu otoriteli oyun motoru ve Telegram kimliğiyle güvenilir kullanıcı deneyimi.</p>','idea',20],
    ['chapter-3',3,'Technology Architecture','Web, Telegram, mobil ve backend mimarisi.','<p>Tek API, bütünlük kontrollü veritabanı, idempotent işlemler ve üretim sağlayıcı katmanları.</p>','blocks',30],
    ['chapter-4',4,'Tokenomics Model','Arz, dağılım, vesting ve OC_POINTS dönüşümü.','<p>OC_POINTS ile OC_TOKEN ayrı varlıklardır; dönüşüm yüzdesi yönetim panelinden ayarlanır.</p>','pie',40],
    ['chapter-5',5,'Roadmap & Growth','Aşamalı lansman ve büyüme planı.','<p>Presale, mobil yayın, listeleme, utility ve yönetişim aşamaları.</p>','chart',50],
    ['chapter-6',6,'Governance & Legal','Yönetim, güvenlik ve uyum çerçevesi.','<p>Gerçek finansal entegrasyonlar için harici denetim, KYC/AML ve yasal onay gereklidir.</p>','scale',60]
  ];
  const chapterInsert = db.prepare(`INSERT OR IGNORE INTO whitepaper_chapters(id,chapter_no,title,summary,content_html,icon,enabled,sort_order,updated_at) VALUES(?,?,?,?,?,?,1,?,?)`);
  for (const row of chapters) chapterInsert.run(...row, now);

  const launchAt = getSetting(db, 'launch_at', new Date(Date.now() + 90 * 86400000).toISOString());
  const start = new Date().toISOString();
  const end = launchAt;
  const stages = [
    ['stage-1','Stage 1',1,10000,1500,100000000,0,10000000,500000000,'upcoming',10],
    ['stage-2','Stage 2',2,11000,1000,100000000,0,10000000,500000000,'upcoming',20],
    ['stage-3','Stage 3',3,12500,500,200000000,0,10000000,1000000000,'upcoming',30],
    ['stage-4','Stage 4',4,15000,0,200000000,0,10000000,1000000000,'upcoming',40]
  ];
  const stageInsert = db.prepare(`INSERT OR IGNORE INTO presale_stages(id,name,stage_no,price_usdt_micros,bonus_bps,allocation_token_base,sold_token_base,min_usdt_micros,max_usdt_micros,starts_at,ends_at,status,enabled,sort_order,updated_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,1,?,?)`);
  for (const row of stages) stageInsert.run(...row.slice(0,9), start, end, row[9], row[10], now);
}


function seedPaymentDefaults(db) {
  const now = nowIso();
  const currencies = [
    ['TRY','Türk Lirası','₺',2,1,1,10,100000000,'manual',0],
    ['USD','ABD Doları','$',2,1,0,20,0,'manual',0],
    ['EUR','Euro','€',2,1,0,30,0,'manual',0],
    ['GBP','İngiliz Sterlini','£',2,1,0,40,0,'manual',0],
    ['RUB','Rus Rublesi','₽',2,0,0,50,0,'manual',0],
    ['CHF','İsviçre Frangı','CHF',2,0,0,60,0,'manual',0],
    ['NOK','Norveç Kronu','kr',2,0,0,70,0,'manual',0],
    ['AED','BAE Dirhemi','د.إ',2,0,0,80,0,'manual',0]
  ];
  const currencyInsert = db.prepare(`INSERT OR IGNORE INTO fiat_currencies(code,name,symbol,decimals,enabled,is_base,sort_order,updated_at) VALUES(?,?,?,?,?,?,?,?)`);
  const rateInsert = db.prepare(`INSERT OR IGNORE INTO fx_rates(currency_code,rate_to_try_e8,source,is_demo,fetched_at,updated_at) VALUES(?,?,?,?,?,?)`);
  for (const [code,name,symbol,decimals,enabled,isBase,sort,rate,source,isDemo] of currencies) {
    currencyInsert.run(code,name,symbol,decimals,enabled,isBase,sort,now);
    rateInsert.run(code,rate,source,isDemo,null,now);
  }

  const providers = [
    ['paytr','PayTR','card','paytr_link','Türkiye merkezli kart, ödeme linki ve çoklu döviz tahsilatı. Merchant sözleşmesi gerekir.',0,0,10,JSON.stringify({maxInstallment:1,lang:'tr',getQr:true}),JSON.stringify({currencies:['TRY','USD','EUR','GBP','RUB'],hosted:true,webhook:true}),'/api/webhooks/paytr'],
    ['iyzico','iyzico','card','iyzico_link','Kart ve iyzico cüzdan tahsilatı için hosted checkout profili. Canlı kullanım için iyzico mağaza hesabı, checkout URL şablonu ve API anahtarları gerekir.',0,0,20,JSON.stringify({locale:'tr',checkoutMode:'hosted',checkoutUrl:'',statusUrl:''}),JSON.stringify({currencies:['TRY','USD','EUR','GBP','CHF','NOK'],hosted:true,webhook:true}),'/api/webhooks/generic/iyzico'],
    ['param','ParamPOS','card','generic_hosted','ParamPOS entegrasyon profili. Desteklenen dövizler mağaza sözleşmesine göre etkinleştirilir.',0,0,30,JSON.stringify({checkoutUrl:'',statusUrl:''}),JSON.stringify({currencies:[],hosted:true,webhook:true}),'/api/webhooks/generic/param'],
    ['sipay','Sipay','card','generic_hosted','Sipay entegrasyon profili. Döviz ve taksit seçenekleri sözleşmeye göre yapılandırılır.',0,0,40,JSON.stringify({checkoutUrl:'',statusUrl:''}),JSON.stringify({currencies:[],hosted:true,webhook:true}),'/api/webhooks/generic/sipay'],
    ['paynet','Paynet','card','generic_hosted','Paynet entegrasyon profili. Merchant API bilgileri girildiğinde etkinleştirilir.',0,0,50,JSON.stringify({checkoutUrl:'',statusUrl:''}),JSON.stringify({currencies:[],hosted:true,webhook:true}),'/api/webhooks/generic/paynet'],
    ['bank_transfer','Banka Havalesi / EFT / SWIFT','bank','manual_bank','TRY, USD, EUR ve diğer döviz hesaplarına manuel banka transferi.',0,0,60,JSON.stringify({requireReference:true,reviewRequired:true}),JSON.stringify({currencies:['TRY','USD','EUR','GBP'],hosted:false,webhook:false}),''],
    ['crypto_direct','Kripto Cüzdan Transferi','crypto','crypto_direct','USDT, BTC ve desteklenen ağlarda doğrudan cüzdan transferi. Bölgesel uyum onayı gerekir.',0,0,70,JSON.stringify({reviewRequired:true,showQr:true}),JSON.stringify({assets:true,hosted:false,webhook:false}),''],
    ['binance_pay','Binance Pay','crypto','generic_hosted','Binance Pay entegrasyon profili. Yasal ve kurumsal uygunluk sonrası etkinleştirilir.',0,0,80,JSON.stringify({checkoutUrl:'',statusUrl:''}),JSON.stringify({currencies:['USDT','BTC','ETH','BNB'],hosted:true,webhook:true}),'/api/webhooks/generic/binance_pay']
  ];
  const providerInsert = db.prepare(`INSERT OR IGNORE INTO payment_providers(id,name,category,adapter,description,enabled,test_mode,sort_order,config_json,secrets_enc,capabilities_json,callback_path,status,last_error,updated_at) VALUES(?,?,?,?,?,?,?,?,?,'',?,?,CASE WHEN ?=1 THEN 'configured' ELSE 'not_configured' END,'',?)`);
  for (const row of providers) providerInsert.run(...row, row[5], now);
  db.prepare("UPDATE payment_providers SET callback_path='/api/webhooks/generic/iyzico' WHERE id='iyzico' AND callback_path='/api/webhooks/iyzico'").run();

  const providerCurrencies = [
    ['paytr','TRY'],['paytr','USD'],['paytr','EUR'],['paytr','GBP'],['paytr','RUB'],
    ['iyzico','TRY'],['iyzico','USD'],['iyzico','EUR'],['iyzico','GBP'],['iyzico','RUB'],['iyzico','CHF'],['iyzico','NOK'],
    ['bank_transfer','TRY'],['bank_transfer','USD'],['bank_transfer','EUR'],['bank_transfer','GBP']
  ];
  const pcInsert = db.prepare(`INSERT OR IGNORE INTO payment_provider_currencies(provider_id,currency_code,enabled,min_amount_minor,max_amount_minor,fee_bps,fixed_fee_minor) VALUES(?,?,1,100,100000000000,0,0)`);
  for (const row of providerCurrencies) pcInsert.run(...row);

  const banks = [];
  const bankInsert = db.prepare(`INSERT OR IGNORE INTO bank_accounts(id,currency_code,bank_name,account_holder,iban,swift_bic,account_number,branch_name,branch_code,country_code,instructions,min_amount_minor,max_amount_minor,enabled,sort_order,updated_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`);
  for (const row of banks) bankInsert.run(...row, now);

  const cryptoAssets = [
    ['usdt-bep20','USDT','Tether USD','BSC (BEP-20)','EVM','token','',18,'','','',15,100000000,'manual',0,0,0,0,1000000,0,10,JSON.stringify({stablecoin:true,legalMode:'presale_deposit_only'})],
    ['usdt-erc20','USDT','Tether USD','Ethereum (ERC-20)','EVM','token','',6,'','','',20,100000000,'manual',0,0,0,0,1000000,0,20,JSON.stringify({stablecoin:true,legalMode:'presale_deposit_only'})],
    ['usdt-trc20','USDT','Tether USD','TRON (TRC-20)','TRON','token','',6,'','','',20,100000000,'manual',0,0,0,0,1000000,0,30,JSON.stringify({stablecoin:true,legalMode:'presale_deposit_only'})],
    ['btc-mainnet','BTC','Bitcoin','Bitcoin Mainnet','BITCOIN','native','',8,'','','',3,10000000000000,'manual',0,0,0,0,1000,0,40,JSON.stringify({legalMode:'presale_deposit_only'})],
    ['eth-mainnet','ETH','Ethereum','Ethereum Mainnet','EVM','native','',18,'','','',20,500000000000,'manual',0,0,0,0,1000000000000000,0,50,JSON.stringify({legalMode:'presale_deposit_only'})],
    ['bnb-bsc','BNB','BNB','BNB Smart Chain','EVM','native','',18,'','','',15,100000000000,'manual',0,0,0,0,1000000000000000,0,60,JSON.stringify({legalMode:'presale_deposit_only'})],
    ['usdc-erc20','USDC','USD Coin','Ethereum (ERC-20)','EVM','token','',6,'','','',20,100000000,'manual',0,0,0,0,1000000,0,70,JSON.stringify({stablecoin:true,legalMode:'presale_deposit_only'})],
    ['trx-mainnet','TRX','TRON','TRON Mainnet','TRON','native','',6,'','','',20,30000000,'manual',0,0,0,0,1000000,0,80,JSON.stringify({legalMode:'presale_deposit_only'})],
    ['ton-mainnet','TON','Toncoin','TON Mainnet','TON','native','',9,'','','',10,500000000,'manual',0,0,0,0,10000000,0,90,JSON.stringify({legalMode:'presale_deposit_only'})]
  ];
  const cryptoInsert = db.prepare(`INSERT OR IGNORE INTO crypto_assets(id,symbol,name,network,chain_family,asset_type,contract_address,decimals,deposit_address,rpc_url,explorer_url,confirmations_required,manual_price_usd_e8,price_source,enabled,purchase_enabled,deposit_enabled,withdrawal_enabled,min_payment_base,max_payment_base,sort_order,metadata_json,updated_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`);
  for (const row of cryptoAssets) cryptoInsert.run(...row, now);

  const vipPrices = [
    [1,'USDT',9900000],[2,'USDT',19900000],[3,'USDT',49900000],[4,'USDT',99900000],[5,'USDT',199900000],
    [1,'USD',990],[2,'USD',1990],[3,'USD',4990],[4,'USD',9990],[5,'USD',19990],
    [1,'EUR',900],[2,'EUR',1800],[3,'EUR',4500],[4,'EUR',9000],[5,'EUR',18000],
    [1,'TRY',47000],[2,'TRY',95000],[3,'TRY',235000],[4,'TRY',470000],[5,'TRY',940000]
  ];
  const vipPriceInsert = db.prepare(`INSERT OR IGNORE INTO vip_plan_prices(tier,currency_code,amount_minor,enabled,updated_at) VALUES(?,?,?,1,?)`);
  for (const row of vipPrices) vipPriceInsert.run(...row, now);
}

export function getDb() {
  if (singleton) return singleton;
  fs.mkdirSync(path.dirname(config.dbPath), { recursive: true });

  const health = inspectDatabaseFile(config.dbPath);
  if (['corrupt', 'unreadable', 'locked'].includes(health.status)) {
    const error = new Error([
      `OnlyCoin database cannot be opened (${health.status}).`,
      health.details || '',
      `Path: ${config.dbPath}`,
      config.isProduction
        ? 'Production data was not modified. Restore a verified backup or perform a controlled SQLite recovery.'
        : 'Close other OnlyCoin processes and restore a verified backup or run VERITABANI-ONAR-WINDOWS.bat for a controlled recovery.'
    ].filter(Boolean).join(' '));
    error.code = health.status === 'locked' ? 'ONLYCOIN_DB_LOCKED' : 'ONLYCOIN_DB_CORRUPT';
    error.health = health;
    throw error;
  }

  try {
    singleton = new DatabaseSync(config.dbPath);
    createSchema(singleton);
    createPlatformSchema(singleton);
    createPaymentSchema(singleton);
    applyMigrations(singleton);
    setDefaults(singleton);
    seedPlatformDefaults(singleton);
    seedPaymentDefaults(singleton);
    return singleton;
  } catch (error) {
    try { singleton?.close(); } catch {}
    singleton = undefined;
    throw error;
  }
}

export function closeDb() {
  if (singleton) singleton.close();
  singleton = undefined;
}

export function resetDbFile() {
  closeDb();
  for (const suffix of ['', '-wal', '-shm', '-journal']) {
    const file = `${config.dbPath}${suffix}`;
    if (fs.existsSync(file)) fs.rmSync(file, { force: true });
  }
}

export function getSetting(db, key, fallback = null) {
  const row = db.prepare('SELECT value FROM settings WHERE key=?').get(key);
  if (!row) return fallback;
  try { return JSON.parse(row.value); } catch { return row.value; }
}

export function getSettings(db) {
  const rows = db.prepare('SELECT key, value, updated_at FROM settings ORDER BY key').all();
  const result = {};
  for (const row of rows) {
    try { result[row.key] = JSON.parse(row.value); } catch { result[row.key] = row.value; }
  }
  return result;
}

export function setSetting(db, key, value) {
  db.prepare(`
    INSERT INTO settings(key,value,updated_at) VALUES(?,?,?)
    ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at
  `).run(key, JSON.stringify(value), nowIso());
}

export function withTransaction(db, fn) {
  db.exec('BEGIN IMMEDIATE');
  try {
    const result = fn();
    db.exec('COMMIT');
    return result;
  } catch (error) {
    db.exec('ROLLBACK');
    throw error;
  }
}

export function audit(db, { actorType, actorId, action, targetType, targetId, before = null, after = null, ip = '' }) {
  db.prepare(`INSERT INTO audit_logs(id,actor_type,actor_id,action,target_type,target_id,before_json,after_json,ip,created_at)
              VALUES(?,?,?,?,?,?,?,?,?,?)`)
    .run(uuid(), actorType, actorId, action, targetType, targetId,
      before == null ? null : JSON.stringify(before),
      after == null ? null : JSON.stringify(after), ip, nowIso());
}

export { defaultSettings };
