import type { MonitoringView, ServiceHealthView } from "@batch-cooking/shared";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { adminApiClient } from "../../api/client";
import "../admin-page.scss";
import "./monitoring-page.scss";
import { clockTime, POLL_INTERVAL_MS, statusModifier } from "./monitoring";

type MonitoringState =
  | { status: "loading" }
  | { status: "loaded"; data: MonitoringView }
  | { status: "error" };

/**
 * Microservice health board. Fetches `GET /admin/monitoring` on mount and
 * re-polls every {@link POLL_INTERVAL_MS} ms. One card per probed target
 * (Postgres, API, intent-service, LLM worker), coloured by status.
 */
export function MonitoringPage() {
  const { t } = useTranslation();
  const [state, setState] = useState<MonitoringState>({ status: "loading" });

  useEffect(() => {
    let cancelled = false;

    function load() {
      adminApiClient
        .getMonitoring()
        .then((data) => {
          if (!cancelled) setState({ status: "loaded", data });
        })
        .catch(() => {
          if (!cancelled)
            setState((prev) => (prev.status === "loaded" ? prev : { status: "error" }));
        });
    }

    load();
    const timer = setInterval(load, POLL_INTERVAL_MS);
    return () => {
      cancelled = true;
      clearInterval(timer);
    };
  }, []);

  return (
    <div className="admin-page">
      <h1 className="admin-page__title">{t("admin.monitoring.title")}</h1>
      <p className="admin-page__lead">{t("admin.monitoring.lead")}</p>

      {state.status === "loading" && (
        <p className="admin-page__placeholder">{t("admin.common.loading")}</p>
      )}
      {state.status === "error" && (
        <p className="admin-page__placeholder">{t("admin.common.loadError")}</p>
      )}
      {state.status === "loaded" && (
        <>
          <p className="monitoring-checked">
            {t("admin.monitoring.lastChecked", { time: clockTime(state.data.generatedAt) })}
          </p>
          <div className="monitoring-grid">
            {state.data.services.map((service) => (
              <ServiceCard key={service.key} service={service} />
            ))}
          </div>
        </>
      )}
    </div>
  );
}

function ServiceCard({ service }: { service: ServiceHealthView }) {
  const { t } = useTranslation();
  return (
    <article className={`monitoring-card monitoring-card--${statusModifier(service.status)}`}>
      <header className="monitoring-card__head">
        <span className="monitoring-card__dot" aria-hidden="true" />
        <h2>{t(`admin.monitoring.service.${service.key}`, { defaultValue: service.key })}</h2>
        <span className="monitoring-card__status">
          {t(`admin.monitoring.status.${service.status}`)}
        </span>
      </header>
      <dl className="monitoring-card__meta">
        {service.latencyMs !== null && (
          <div>
            <dt>{t("admin.monitoring.latency")}</dt>
            <dd>{service.latencyMs} ms</dd>
          </div>
        )}
        {service.detail && (
          <div>
            <dt>{t("admin.monitoring.detail")}</dt>
            <dd>{service.detail}</dd>
          </div>
        )}
        {service.lastRunAt !== undefined && (
          <div>
            <dt>{t("admin.monitoring.lastRun")}</dt>
            <dd>
              {service.lastRunAt ? clockTime(service.lastRunAt) : t("admin.monitoring.never")}
              {service.lastResult?.job ? ` · ${service.lastResult.job}` : ""}
              {service.lastResult?.ok === false ? ` · ${t("admin.monitoring.jobFailed")}` : ""}
            </dd>
          </div>
        )}
      </dl>
    </article>
  );
}
