import prisma from "../config/database"; interface SystemSettings { break_threshold_hours: number; break_duration_short: number; break_duration_long: number; clock_rounding_minutes: number; invoice_alert_email: string; leave_notify_email: string; max_login_attempts: number; lockout_minutes: number; max_requests_per_minute: number; default_currency: string; default_vat_rate: number; available_vat_rates: number[]; available_currencies: string[]; smtp_from: string; smtp_from_name: string; } const DEFAULTS: SystemSettings = { break_threshold_hours: 6, break_duration_short: 15, break_duration_long: 30, clock_rounding_minutes: 15, invoice_alert_email: "", leave_notify_email: "", max_login_attempts: 5, lockout_minutes: 15, max_requests_per_minute: 300, default_currency: "CZK", default_vat_rate: 21, available_vat_rates: [0, 10, 12, 15, 21], available_currencies: ["CZK", "EUR", "USD", "GBP"], smtp_from: "", smtp_from_name: "", }; let cache: SystemSettings | null = null; let cacheTime = 0; const CACHE_TTL = 60_000; // 60 seconds export async function getSystemSettings(): Promise { if (cache && Date.now() - cacheTime < CACHE_TTL) return cache; const row = await prisma.company_settings.findFirst(); if (!row) { cache = { ...DEFAULTS }; cacheTime = Date.now(); return cache; } let vatRates = DEFAULTS.available_vat_rates; let currencies = DEFAULTS.available_currencies; try { if (row.available_vat_rates) { const parsed = JSON.parse(row.available_vat_rates); // Shape guard: must be an array of finite numbers, else keep default. if (Array.isArray(parsed) && parsed.every((n) => Number.isFinite(n))) { vatRates = parsed; } } } catch { /* malformed JSON — keep default (expected-condition catch) */ } try { if (row.available_currencies) { const parsed = JSON.parse(row.available_currencies); // Shape guard: must be an array of strings, else keep default. if (Array.isArray(parsed) && parsed.every((c) => typeof c === "string")) { currencies = parsed; } } } catch { /* malformed JSON — keep default (expected-condition catch) */ } cache = { break_threshold_hours: Number( row.break_threshold_hours ?? DEFAULTS.break_threshold_hours, ), break_duration_short: row.break_duration_short ?? DEFAULTS.break_duration_short, break_duration_long: row.break_duration_long ?? DEFAULTS.break_duration_long, clock_rounding_minutes: row.clock_rounding_minutes ?? DEFAULTS.clock_rounding_minutes, invoice_alert_email: row.invoice_alert_email || "", leave_notify_email: row.leave_notify_email || "", max_login_attempts: row.max_login_attempts ?? DEFAULTS.max_login_attempts, lockout_minutes: row.lockout_minutes ?? DEFAULTS.lockout_minutes, max_requests_per_minute: row.max_requests_per_minute ?? DEFAULTS.max_requests_per_minute, default_currency: row.default_currency || DEFAULTS.default_currency, default_vat_rate: Number(row.default_vat_rate ?? DEFAULTS.default_vat_rate), available_vat_rates: vatRates, available_currencies: currencies, smtp_from: row.smtp_from || "", smtp_from_name: row.smtp_from_name || DEFAULTS.smtp_from_name, }; cacheTime = Date.now(); return cache; } export function invalidateSettingsCache(): void { cache = null; cacheTime = 0; }