import type {
  HostStatus,
  ServiceStatus,
  NetworkStatus,
  SiteStatus,
  StatusSnapshot,
  StatusSummary,
  AlertItem,
} from "./types.js";

const hosts: Map<string, HostStatus> = new Map();
const services: Map<string, ServiceStatus> = new Map();
const network: Map<string, NetworkStatus> = new Map();
const sites: Map<string, SiteStatus> = new Map();
let lastUpdated = new Date().toISOString();

export function setHost(status: HostStatus): void {
  hosts.set(status.id, status);
  lastUpdated = new Date().toISOString();
}

export function setService(status: ServiceStatus): void {
  services.set(status.id, status);
  lastUpdated = new Date().toISOString();
}

export function setNetwork(status: NetworkStatus): void {
  network.set(status.id, status);
  lastUpdated = new Date().toISOString();
}

export function setSite(status: SiteStatus): void {
  sites.set(status.id, status);
  lastUpdated = new Date().toISOString();
}

export function clearSites(): void {
  sites.clear();
}

export function getSnapshot(): StatusSnapshot {
  return {
    hosts: Array.from(hosts.values()),
    services: Array.from(services.values()),
    network: Array.from(network.values()),
    sites: Array.from(sites.values()),
    last_updated: lastUpdated,
  };
}

export function getHosts(): HostStatus[] {
  return Array.from(hosts.values());
}

export function getHost(id: string): HostStatus | undefined {
  return hosts.get(id);
}

export function getServices(): ServiceStatus[] {
  return Array.from(services.values());
}

export function getService(id: string): ServiceStatus | undefined {
  return services.get(id);
}

export function getNetworkStatuses(): NetworkStatus[] {
  return Array.from(network.values());
}

export function getSites(): SiteStatus[] {
  return Array.from(sites.values());
}

export function getSite(id: string): SiteStatus | undefined {
  return sites.get(id);
}

export function getAlerts(): AlertItem[] {
  const alerts: AlertItem[] = [];

  for (const h of hosts.values()) {
    if (h.status === "offline") {
      alerts.push({ category: "host", id: h.id, name: h.name, severity: "red", message: "Host unreachable", last_checked: h.last_checked });
    } else if (h.status === "degraded") {
      const reasons: string[] = [];
      if (h.cpu_percent > 80) reasons.push(`CPU ${h.cpu_percent.toFixed(0)}%`);
      if (h.memory_total_bytes > 0 && h.memory_used_bytes / h.memory_total_bytes > 0.85) reasons.push("Memory high");
      if (h.disk_total_bytes > 0 && h.disk_used_bytes / h.disk_total_bytes > 0.8) reasons.push("Disk high");
      if (h.pending_security_updates > 0) reasons.push(`${h.pending_security_updates} security updates`);
      const severity = h.cpu_percent > 95 || (h.memory_total_bytes > 0 && h.memory_used_bytes / h.memory_total_bytes > 0.95) || (h.disk_total_bytes > 0 && h.disk_used_bytes / h.disk_total_bytes > 0.9) ? "red" as const : "amber" as const;
      alerts.push({ category: "host", id: h.id, name: h.name, severity, message: reasons.join(", "), last_checked: h.last_checked });
    }
  }

  for (const s of services.values()) {
    if (s.status !== "running") {
      alerts.push({ category: "service", id: s.id, name: s.name, severity: "red", message: `Service ${s.status}`, last_checked: s.last_checked });
    }
  }

  for (const n of network.values()) {
    if (n.status === "offline") {
      alerts.push({ category: "network", id: n.id, name: n.name, severity: "red", message: "Connection down", last_checked: n.last_checked });
    }
  }

  for (const s of sites.values()) {
    if (s.status === "down") {
      alerts.push({ category: "site", id: s.id, name: s.name, severity: "red", message: `HTTP ${s.http_status_code}`, last_checked: s.last_checked });
    } else if (s.status === "degraded") {
      const reasons: string[] = [];
      if (s.response_time_ms > 2000) reasons.push(`${s.response_time_ms}ms response`);
      if (s.ssl_days_remaining !== null && s.ssl_days_remaining < 30) reasons.push(`SSL expires in ${s.ssl_days_remaining}d`);
      const severity = s.response_time_ms > 5000 || (s.ssl_days_remaining !== null && s.ssl_days_remaining < 7) ? "red" as const : "amber" as const;
      alerts.push({ category: "site", id: s.id, name: s.name, severity, message: reasons.join(", "), last_checked: s.last_checked });
    }
  }

  return alerts.sort((a, b) => (a.severity === "red" ? 0 : 1) - (b.severity === "red" ? 0 : 1));
}

export function getSummary(): StatusSummary {
  const countStatus = <T extends { status: string }>(items: T[], greenValues: string[], redValues: string[]) => {
    let green = 0, amber = 0, red = 0;
    for (const item of items) {
      if (greenValues.includes(item.status)) green++;
      else if (redValues.includes(item.status)) red++;
      else amber++;
    }
    return { green, amber, red };
  };

  const h = countStatus(Array.from(hosts.values()), ["online"], ["offline"]);
  const s = countStatus(Array.from(services.values()), ["running"], ["stopped", "errored"]);
  const n = countStatus(Array.from(network.values()), ["online"], ["offline"]);
  const si = countStatus(Array.from(sites.values()), ["up"], ["down"]);

  const totalRed = h.red + s.red + n.red + si.red;
  const totalAmber = h.amber + s.amber + n.amber + si.amber;
  const overall = totalRed > 0 ? "critical" : totalAmber > 0 ? "degraded" : "healthy";

  return { hosts: h, services: s, network: n, sites: si, overall };
}
