import type { ZabbixItem } from './zabbix-types';

export const ZABBIX_STATUS_KEYS = ['agent.ping', 'system.uptime'] as const;
export const DEFAULT_DETAIL_VIEW = 'core_network';
export const CORE_VIEW = 'core';
export const CORE_NETWORK_VIEW = 'core_network';
export const ALL_VIEW = 'all';

const CORE_NAME_KEYWORDS = [
  'cpu',
  'processor',
  'memory',
  'free memory',
  'total memory',
  'disk',
  'drive time',
  'free disk space',
  'read queue',
  'write queue',
  'uptime',
  'agent ping',
];

const CORE_KEY_KEYWORDS = [
  'agent.ping',
  'system.uptime',
  'system.cpu',
  'perf_counter["\\processor',
  'perf_counter["\\memory',
  'vfs.fs.size',
  'vfs.fs.free',
  'vfs.fs.used',
];

const NETWORK_NAME_KEYWORDS = [
  'network',
  'traffic',
  'received',
  'sent',
  'netmon',
  '네트워크',
  '트래픽',
  '수신',
  '송신',
];

const NETWORK_KEY_KEYWORDS = ['net.if', 'net.tcp', 'net.udp'];

export function formatKstIso(epochSeconds?: string): string | null {
  const parsed = epochSeconds ? Number(epochSeconds) : NaN;
  if (!Number.isFinite(parsed)) return null;
  const date = new Date(parsed * 1000);
  return (
    new Intl.DateTimeFormat('sv-SE', {
      timeZone: 'Asia/Seoul',
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
    }).format(date).replace(' ', 'T') + '+09:00'
  );
}

export function formatDuration(seconds?: string): string | null {
  const total = seconds ? Number(seconds) : NaN;
  if (!Number.isFinite(total)) return null;
  const s = Math.max(0, Math.floor(total));
  const days = Math.floor(s / 86400);
  const hours = Math.floor((s % 86400) / 3600);
  const minutes = Math.floor((s % 3600) / 60);
  const secs = s % 60;
  const pad = (n: number) => n.toString().padStart(2, '0');
  return `${days}d ${pad(hours)}:${pad(minutes)}:${pad(secs)}`;
}

export function formatAgeSeconds(epochSeconds?: string): string | null {
  const parsed = epochSeconds ? Number(epochSeconds) : NaN;
  if (!Number.isFinite(parsed)) return null;
  const nowSec = Math.floor(Date.now() / 1000);
  const diff = Math.max(0, nowSec - parsed);
  if (diff < 60) return `${diff}s ago`;
  if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
  if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
  return `${Math.floor(diff / 86400)}d ago`;
}

export function normalize(value?: string): string {
  return (value || '').toLowerCase();
}

export function includesAny(value: string, keywords: string[]): boolean {
  return keywords.some((keyword) => value.includes(keyword));
}

export function parseEpochSeconds(value?: string, fallback?: number): number {
  if (!value) return fallback ?? Math.floor(Date.now() / 1000);
  const numeric = Number(value);
  if (Number.isFinite(numeric)) {
    if (numeric > 1e12) return Math.floor(numeric / 1000);
    if (numeric > 1e9) return Math.floor(numeric);
  }
  const parsed = Date.parse(value);
  if (!Number.isNaN(parsed)) {
    return Math.floor(parsed / 1000);
  }
  return fallback ?? Math.floor(Date.now() / 1000);
}

export function parseMetricNameFromDisk(label: string): string {
  const match = label.match(/on\s+([A-Za-z]:)/);
  if (match && match[1]) {
    return `Disk ${match[1].toUpperCase()} Used %`;
  }
  return 'Disk Used %';
}

export function parseNumeric(value?: string): number | null {
  if (value == null) return null;
  const num = Number(value);
  return Number.isFinite(num) ? num : null;
}

export function matchesCore(item: ZabbixItem): boolean {
  const name = normalize(item.name);
  const key = normalize(item.key_);
  return includesAny(name, CORE_NAME_KEYWORDS) || includesAny(key, CORE_KEY_KEYWORDS);
}

export function matchesNetwork(item: ZabbixItem): boolean {
  const name = normalize(item.name);
  const key = normalize(item.key_);
  return includesAny(name, NETWORK_NAME_KEYWORDS) || includesAny(key, NETWORK_KEY_KEYWORDS);
}
