import { getDb } from '../database/database';

/**
 * Get the current timezone from DB config, with fallback.
 */
export function getTimezone(): string {
  try {
    const db = getDb();
    const row = db.prepare('SELECT value FROM system_configs WHERE key = ?').get('timezone') as any;
    return row?.value || 'Asia/Shanghai';
  } catch {
    return 'Asia/Shanghai';
  }
}

/**
 * Returns current local time as an ISO 8601 string with timezone offset.
 * Example: "2026-05-02T14:32:23+08:00"
 * This format is reliably parsed by JavaScript Date() in all browsers.
 */
export function localTimestamp(): string {
  const tz = getTimezone();
  const now = new Date();
  // Format as local time string with timezone offset
  try {
    const parts = new Intl.DateTimeFormat('sv-SE', {
      timeZone: tz,
      year: 'numeric', month: '2-digit', day: '2-digit',
      hour: '2-digit', minute: '2-digit', second: '2-digit',
      hour12: false,
    }).formatToParts(now);
    const get = (type: string) => parts.find(p => p.type === type)?.value || '00';
    const dateStr = `${get('year')}-${get('month')}-${get('day')}T${get('hour')}:${get('minute')}:${get('second')}`;
    // Calculate timezone offset for the configured timezone
    // Use getTimezoneOffset difference between UTC and the target timezone
    const utcMs = now.getTime();
    const localStr = dateStr.replace('T', ' ');
    // Get offset in minutes for the configured timezone
    const formatter = new Intl.DateTimeFormat('sv-SE', {
      timeZone: tz,
      timeZoneName: 'longOffset',
    });
    const tzName = formatter.formatToParts(now).find(p => p.type === 'timeZoneName')?.value || '';
    // tzName is like "GMT+8" or "GMT-05:00"
    let offset = '+00:00';
    if (tzName) {
      const match = tzName.match(/GMT([+-])(\d+)(?::(\d+))?/);
      if (match) {
        const sign = match[1];
        const hours = match[2].padStart(2, '0');
        const mins = (match[3] || '00').padStart(2, '0');
        offset = `${sign}${hours}:${mins}`;
      }
    }
    return dateStr + offset;
  } catch {
    // Fallback: use UTC
    return now.toISOString();
  }
}

/**
 * Returns today's (or given date's) date string in the configured timezone.
 * Example: "2026-05-04"
 */
export function formatLocalDate(date?: Date): string {
  const tz = getTimezone();
  const d = date || new Date();
  try {
    const parts = new Intl.DateTimeFormat('sv-SE', {
      timeZone: tz,
      year: 'numeric', month: '2-digit', day: '2-digit',
    }).formatToParts(d);
    const get = (type: string) => parts.find(p => p.type === type)?.value || '00';
    return `${get('year')}-${get('month')}-${get('day')}`;
  } catch {
    const y = d.getFullYear();
    const m = String(d.getMonth() + 1).padStart(2, '0');
    const day = String(d.getDate()).padStart(2, '0');
    return `${y}-${m}-${day}`;
  }
}

/**
 * Escape SQL LIKE wildcards (% and _) in user input to prevent unintended pattern matching.
 */
export function escapeLike(str: string): string {
  return str.replace(/[%_\\]/g, '\\$&');
}

/**
 * Returns a local datetime string in the configured timezone.
 * Example: "2026-05-04 14:32:23" — intentionally space-separated (no T) for DB compatibility.
 */
export function formatLocalDateTime(date?: Date): string {
  const tz = getTimezone();
  const d = date || new Date();
  try {
    const parts = new Intl.DateTimeFormat('sv-SE', {
      timeZone: tz,
      year: 'numeric', month: '2-digit', day: '2-digit',
      hour: '2-digit', minute: '2-digit', second: '2-digit',
      hour12: false,
    }).formatToParts(d);
    const get = (type: string) => parts.find(p => p.type === type)?.value || '00';
    return `${get('year')}-${get('month')}-${get('day')} ${get('hour')}:${get('minute')}:${get('second')}`;
  } catch {
    const y = d.getFullYear();
    const mo = String(d.getMonth() + 1).padStart(2, '0');
    const da = String(d.getDate()).padStart(2, '0');
    const h = String(d.getHours()).padStart(2, '0');
    const mi = String(d.getMinutes()).padStart(2, '0');
    const s = String(d.getSeconds()).padStart(2, '0');
    return `${y}-${mo}-${da} ${h}:${mi}:${s}`;
  }
}
