import { mkdirSync } from 'node:fs';

import Database from 'better-sqlite3';
import { dirname, join } from 'pathe';

const dbFile = join(process.cwd(), 'storage', 'finance.db');

mkdirSync(dirname(dbFile), { recursive: true });

const database = new Database(dbFile);

function assertIdentifier(name: string) {
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
    throw new Error(`Invalid identifier: ${name}`);
  }
  return name;
}

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

database.pragma('journal_mode = WAL');

database.exec(`
  CREATE TABLE IF NOT EXISTS finance_currencies (
    code TEXT PRIMARY KEY,
    name TEXT NOT NULL,
    symbol TEXT NOT NULL,
    is_base INTEGER NOT NULL DEFAULT 0,
    is_active INTEGER NOT NULL DEFAULT 1
  );
`);

database.exec(`
  CREATE TABLE IF NOT EXISTS finance_exchange_rates (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    from_currency TEXT NOT NULL,
    to_currency TEXT NOT NULL,
    rate REAL NOT NULL,
    date TEXT NOT NULL,
    source TEXT DEFAULT 'manual'
  );
`);

database.exec(`
  CREATE TABLE IF NOT EXISTS finance_accounts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    currency TEXT NOT NULL,
    type TEXT DEFAULT 'cash',
    icon TEXT,
    color TEXT,
    user_id INTEGER DEFAULT 1,
    is_active INTEGER DEFAULT 1
  );
`);

database.exec(`
  CREATE TABLE IF NOT EXISTS finance_categories (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    type TEXT NOT NULL,
    icon TEXT,
    color TEXT,
    user_id INTEGER DEFAULT 1,
    is_active INTEGER DEFAULT 1
  );
`);

database.exec(`
  CREATE TABLE IF NOT EXISTS finance_transactions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    type TEXT NOT NULL,
    amount REAL NOT NULL,
    currency TEXT NOT NULL,
    exchange_rate_to_base REAL NOT NULL,
    amount_in_base REAL NOT NULL,
    category_id INTEGER,
    account_id INTEGER,
    transaction_date TEXT NOT NULL,
    description TEXT,
    project TEXT,
    memo TEXT,
    created_at TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'approved',
    status_updated_at TEXT,
    reimbursement_batch TEXT,
    review_notes TEXT,
    submitted_by TEXT,
    approved_by TEXT,
    approved_at TEXT,
    is_deleted INTEGER NOT NULL DEFAULT 0,
    deleted_at TEXT,
    FOREIGN KEY (currency) REFERENCES finance_currencies(code),
    FOREIGN KEY (category_id) REFERENCES finance_categories(id),
    FOREIGN KEY (account_id) REFERENCES finance_accounts(id)
  );
`);

ensureColumn(
  'finance_transactions',
  'status',
  "status TEXT NOT NULL DEFAULT 'approved'",
);
ensureColumn('finance_transactions', 'status_updated_at', 'status_updated_at TEXT');
ensureColumn(
  'finance_transactions',
  'reimbursement_batch',
  'reimbursement_batch TEXT',
);
ensureColumn('finance_transactions', 'review_notes', 'review_notes TEXT');
ensureColumn('finance_transactions', 'submitted_by', 'submitted_by TEXT');
ensureColumn('finance_transactions', 'approved_by', 'approved_by TEXT');
ensureColumn('finance_transactions', 'approved_at', 'approved_at TEXT');

database.exec(`
  CREATE TABLE IF NOT EXISTS finance_media_messages (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    chat_id INTEGER NOT NULL,
    message_id INTEGER NOT NULL,
    user_id INTEGER NOT NULL,
    username TEXT,
    display_name TEXT,
    file_type TEXT NOT NULL,
    file_id TEXT NOT NULL,
    file_unique_id TEXT,
    caption TEXT,
    file_name TEXT,
    file_path TEXT NOT NULL,
    file_size INTEGER,
    mime_type TEXT,
    duration INTEGER,
    width INTEGER,
    height INTEGER,
    forwarded_to INTEGER,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(chat_id, message_id)
  );
`);

database.exec(`
  CREATE INDEX IF NOT EXISTS idx_finance_media_messages_created_at
  ON finance_media_messages (created_at DESC);
`);

database.exec(`
  CREATE INDEX IF NOT EXISTS idx_finance_media_messages_user_id
  ON finance_media_messages (user_id);
`);

// Telegram通知配置表
database.exec(`
  CREATE TABLE IF NOT EXISTS telegram_notification_configs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    bot_token TEXT NOT NULL,
    chat_id TEXT NOT NULL,
    notification_types TEXT NOT NULL,
    is_enabled INTEGER NOT NULL DEFAULT 1,
    priority TEXT DEFAULT 'normal',
    rate_limit_seconds INTEGER DEFAULT 0,
    batch_enabled INTEGER DEFAULT 0,
    batch_interval_minutes INTEGER DEFAULT 60,
    retry_enabled INTEGER DEFAULT 1,
    retry_max_attempts INTEGER DEFAULT 3,
    created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
  );
`);

database.exec(`
  CREATE INDEX IF NOT EXISTS idx_telegram_notification_configs_enabled
  ON telegram_notification_configs (is_enabled);
`);

// 通知发送历史表（用于频率控制和去重）
database.exec(`
  CREATE TABLE IF NOT EXISTS telegram_notification_history (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    config_id INTEGER NOT NULL,
    notification_type TEXT NOT NULL,
    content_hash TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending',
    retry_count INTEGER DEFAULT 0,
    sent_at TEXT,
    error_message TEXT,
    created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (config_id) REFERENCES telegram_notification_configs(id)
  );
`);

database.exec(`
  CREATE INDEX IF NOT EXISTS idx_telegram_notification_history_config
  ON telegram_notification_history (config_id, created_at DESC);
`);

database.exec(`
  CREATE INDEX IF NOT EXISTS idx_telegram_notification_history_hash
  ON telegram_notification_history (content_hash, created_at DESC);
`);

database.exec(`
  CREATE INDEX IF NOT EXISTS idx_telegram_notification_history_status
  ON telegram_notification_history (status, retry_count);
`);

// 确保添加新列到已存在的表
ensureColumn(
  'telegram_notification_configs',
  'priority',
  "priority TEXT DEFAULT 'normal'",
);
ensureColumn(
  'telegram_notification_configs',
  'rate_limit_seconds',
  'rate_limit_seconds INTEGER DEFAULT 0',
);
ensureColumn(
  'telegram_notification_configs',
  'batch_enabled',
  'batch_enabled INTEGER DEFAULT 0',
);
ensureColumn(
  'telegram_notification_configs',
  'batch_interval_minutes',
  'batch_interval_minutes INTEGER DEFAULT 60',
);
ensureColumn(
  'telegram_notification_configs',
  'retry_enabled',
  'retry_enabled INTEGER DEFAULT 1',
);
ensureColumn(
  'telegram_notification_configs',
  'retry_max_attempts',
  'retry_max_attempts INTEGER DEFAULT 3',
);

export default database;
