{% extends "base.html" %}
{% block title %}{{ t(request, 'page.enterprise') }} — MoE Admin{% endblock %}

{% block content %}
<div class="d-flex align-items-center justify-content-between mb-3">
  <h5 class="mb-0 fw-bold">
    <i class="bi bi-diagram-3 me-2 text-primary"></i>{{ t(request, 'page.enterprise') }}
  </h5>
  <div class="d-flex align-items-center gap-2">
    <span class="text-muted small" id="codex-last-update">{{ t(request, 'lbl.loading') }}</span>
    <button class="btn btn-sm btn-outline-primary" onclick="loadCodex()">
      <i class="bi bi-arrow-clockwise me-1"></i>{{ t(request, 'btn.refresh') }}
    </button>
  </div>
</div>

{# ── Per-service health cards ── #}
<div class="row g-3 mb-4" id="codex-services-row">
  {% set services = [
    ("nifi",    "bi-share-fill",    "NiFi"),
    ("marquez", "bi-link-45deg",    "Marquez"),
    ("lakefs",  "bi-git",           "lakeFS"),
  ] %}
  {% for key, icon, label in services %}
  <div class="col-12 col-md-4">
    <div class="card h-100 border-secondary border-opacity-25" id="ent-card-{{ key }}">
      <div class="card-header d-flex align-items-center justify-content-between bg-body-secondary">
        <span class="fw-semibold">
          <i class="bi {{ icon }} me-2"></i>{{ label }}
        </span>
        <span class="badge bg-secondary" id="ent-status-{{ key }}">–</span>
      </div>
      <div class="card-body py-3">
        <div class="text-muted small mb-1">{{ t(request, 'lbl.url') }}</div>
        <div class="font-monospace small text-truncate mb-2" id="ent-url-{{ key }}">–</div>
        <div class="row g-2 small">
          <div class="col-6">
            <div class="text-muted">{{ t(request, 'lbl.latency') }}</div>
            <div class="fw-bold" id="ent-latency-{{ key }}">–</div>
          </div>
          <div class="col-6">
            <div class="text-muted">{{ t(request, 'lbl.reachable') }}</div>
            <div class="fw-bold" id="ent-ok-{{ key }}">–</div>
          </div>
        </div>
      </div>
    </div>
  </div>
  {% endfor %}
</div>

{# ── Aggregate status banner (when not configured) ── #}
<div class="alert alert-warning d-none" id="codex-disabled-banner" role="alert">
  <i class="bi bi-info-circle me-2"></i>{{ t(request, 'lbl.enterprise_not_configured') }}
</div>

{# ── Marquez run history ── #}
<div class="row g-3 mb-4">
  <div class="col-12">
    <div class="card">
      <div class="card-header d-flex align-items-center justify-content-between bg-primary bg-opacity-10 text-primary-emphasis">
        <span><i class="bi bi-clock-history me-2"></i>{{ t(request, 'section.lineage_runs') }}</span>
        <span class="text-muted small" id="codex-runs-meta">–</span>
      </div>
      <div class="card-body p-0">
        <div class="table-responsive">
          <table class="table table-sm table-hover mb-0">
            <thead class="table-group-divider">
              <tr>
                <th>{{ t(request, 'lbl.job') }}</th>
                <th>{{ t(request, 'lbl.run_id') }}</th>
                <th>{{ t(request, 'lbl.state') }}</th>
                <th>{{ t(request, 'lbl.started_at') }}</th>
                <th class="text-end">{{ t(request, 'lbl.duration') }}</th>
              </tr>
            </thead>
            <tbody id="codex-runs-body">
              <tr>
                <td colspan="5" class="text-muted text-center py-3">
                  <i class="bi bi-hourglass me-1"></i>{{ t(request, 'lbl.loading') }}
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</div>

{# ── NiFi ETL pipeline status (Phase 17) ── #}
<div class="row g-3 mb-4">
  <div class="col-12">
    <div class="card">
      <div class="card-header d-flex align-items-center justify-content-between bg-danger bg-opacity-10 text-danger-emphasis">
        <span><i class="bi bi-share-fill me-2"></i>{{ t(request, 'section.etl_pipeline') }}</span>
        <span class="text-muted small" id="codex-etl-meta">–</span>
      </div>
      <div class="card-body py-3" id="codex-etl-body">
        <span class="text-muted small">{{ t(request, 'lbl.loading') }}</span>
      </div>
    </div>
  </div>
</div>

{# ── Data Health drift events (Phase 23) ── #}
<div class="row g-3 mb-4">
  <div class="col-12">
    <div class="card">
      <div class="card-header d-flex align-items-center justify-content-between bg-warning bg-opacity-10 text-warning-emphasis">
        <span><i class="bi bi-clipboard-pulse me-2"></i>{{ t(request, 'section.data_health') }}</span>
        <span class="text-muted small" id="codex-health-meta">–</span>
      </div>
      <div class="card-body p-0">
        <div class="table-responsive">
          <table class="table table-sm table-hover mb-0">
            <thead class="table-group-divider">
              <tr>
                <th>{{ t(request, 'lbl.severity') }}</th>
                <th>{{ t(request, 'lbl.source_tag') }}</th>
                <th class="text-end">{{ t(request, 'lbl.declared_entities') }}</th>
                <th class="text-end">{{ t(request, 'lbl.delta_entities') }}</th>
                <th class="text-end">{{ t(request, 'lbl.delta_relations') }}</th>
                <th>{{ t(request, 'lbl.flags') }}</th>
                <th>{{ t(request, 'lbl.committed_at') }}</th>
              </tr>
            </thead>
            <tbody id="codex-health-body">
              <tr><td colspan="7" class="text-muted text-center py-3">
                <i class="bi bi-hourglass me-1"></i>{{ t(request, 'lbl.loading') }}
              </td></tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</div>

{# ── lakeFS bundle versioning log (Phase 18) ── #}
<div class="row g-3 mb-4">
  <div class="col-12">
    <div class="card">
      <div class="card-header d-flex align-items-center justify-content-between bg-success bg-opacity-10 text-success-emphasis">
        <span><i class="bi bi-git me-2"></i>{{ t(request, 'section.bundle_versions') }}</span>
        <span class="text-muted small" id="codex-versioning-meta">–</span>
      </div>
      <div class="card-body p-0">
        <div class="table-responsive">
          <table class="table table-sm table-hover mb-0">
            <thead class="table-group-divider">
              <tr>
                <th>{{ t(request, 'lbl.commit') }}</th>
                <th>{{ t(request, 'lbl.message') }}</th>
                <th>{{ t(request, 'lbl.author') }}</th>
                <th>{{ t(request, 'lbl.committed_at') }}</th>
              </tr>
            </thead>
            <tbody id="codex-versioning-body">
              <tr>
                <td colspan="4" class="text-muted text-center py-3">
                  <i class="bi bi-hourglass me-1"></i>{{ t(request, 'lbl.loading') }}
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</div>

<script>
const STATUS_BADGE = {
  healthy:  "bg-success",
  degraded: "bg-warning text-dark",
  down:     "bg-danger",
  disabled: "bg-secondary",
};
const STATUS_LABEL = {
  healthy:  "{{ t(request, 'status.healthy') }}",
  degraded: "{{ t(request, 'status.degraded') }}",
  down:     "{{ t(request, 'status.down') }}",
  disabled: "{{ t(request, 'status.disabled') }}",
};

function fmtMs(ms) {
  if (ms == null || ms < 0) return "–";
  if (ms < 1000) return ms + " ms";
  return (ms / 1000).toFixed(2) + " s";
}

function fmtTs(iso) {
  if (!iso) return "–";
  try {
    const d = new Date(iso);
    return d.toLocaleString();
  } catch (e) { return iso; }
}

async function loadCodexHealth() {
  try {
    const r = await fetch("/api/codex/health");
    const data = await r.json();
    const banner = document.getElementById("codex-disabled-banner");
    if (!data.enabled) {
      banner.classList.remove("d-none");
    } else {
      banner.classList.add("d-none");
    }
    for (const svc of (data.services || [])) {
      const status = svc.status || "down";
      const badge = document.getElementById("ent-status-" + svc.name);
      if (badge) {
        badge.className = "badge " + (STATUS_BADGE[status] || "bg-secondary");
        badge.textContent = STATUS_LABEL[status] || status;
      }
      const urlEl = document.getElementById("ent-url-" + svc.name);
      if (urlEl) urlEl.textContent = svc.url || "—";
      const latEl = document.getElementById("ent-latency-" + svc.name);
      if (latEl) latEl.textContent = fmtMs(svc.latency_ms);
      const okEl = document.getElementById("ent-ok-" + svc.name);
      if (okEl) okEl.textContent = svc.configured ? (svc.ok ? "✅" : "❌") : "—";
    }
  } catch (e) {
    console.error("codex health fetch failed", e);
  }
}

async function loadCodexRuns() {
  try {
    const r = await fetch("/api/codex/runs?limit=25");
    const data = await r.json();
    const body = document.getElementById("codex-runs-body");
    const meta = document.getElementById("codex-runs-meta");
    if (!data.marquez_configured) {
      body.innerHTML = `<tr><td colspan="5" class="text-muted text-center py-3">{{ t(request, 'lbl.marquez_not_configured') }}</td></tr>`;
      meta.textContent = "—";
      return;
    }
    if (data.error) {
      body.innerHTML = `<tr><td colspan="5" class="text-danger text-center py-3"><i class="bi bi-exclamation-triangle me-1"></i>${data.error}</td></tr>`;
      meta.textContent = data.namespace;
      return;
    }
    const runs = data.runs || [];
    if (!runs.length) {
      body.innerHTML = `<tr><td colspan="5" class="text-muted text-center py-3">{{ t(request, 'lbl.no_data') }}</td></tr>`;
      meta.textContent = data.namespace + " — 0";
      return;
    }
    body.innerHTML = runs.map(run => {
      const state = (run.state || "").toUpperCase();
      const stateBadge = state === "COMPLETED" ? "bg-success"
                       : state === "FAILED"    ? "bg-danger"
                       : state === "RUNNING"   ? "bg-info"
                       : "bg-secondary";
      const shortId = (run.runId || "").slice(0, 8);
      return `<tr>
        <td class="font-monospace small">${run.job}</td>
        <td class="font-monospace small text-muted">${shortId}…</td>
        <td><span class="badge ${stateBadge}">${state || "—"}</span></td>
        <td class="small">${fmtTs(run.startedAt)}</td>
        <td class="text-end small">${fmtMs(run.durationMs)}</td>
      </tr>`;
    }).join("");
    meta.textContent = data.namespace + " — " + runs.length;
  } catch (e) {
    console.error("codex runs fetch failed", e);
  }
}

function fmtBytes(n) {
  if (n == null) return "–";
  const num = (typeof n === "string") ? parseFloat(n.replace(/[, ]/g, "")) : n;
  if (isNaN(num)) return n;
  const units = ["B", "KB", "MB", "GB", "TB"];
  let i = 0;
  let v = num;
  while (v >= 1024 && i < units.length - 1) { v /= 1024; i++; }
  return v.toFixed(1) + " " + units[i];
}

async function loadCodexEtl() {
  try {
    const r = await fetch("/api/codex/etl/status");
    const data = await r.json();
    const body = document.getElementById("codex-etl-body");
    const meta = document.getElementById("codex-etl-meta");
    if (!data.available) {
      body.innerHTML = `<span class="text-muted small"><i class="bi bi-info-circle me-1"></i>${data.reason || "—"}</span>`;
      meta.textContent = "—";
      return;
    }
    const ingestPill = data.ingest_configured
      ? `<span class="badge bg-success">{{ t(request, 'status.healthy') }}</span>`
      : `<span class="badge bg-secondary">{{ t(request, 'status.disabled') }}</span>`;
    body.innerHTML = `
      <div class="row g-2 small">
        <div class="col-md-3"><div class="text-muted">{{ t(request, 'lbl.version') }}</div>
          <div class="fw-bold">${data.version || "—"}</div></div>
        <div class="col-md-3"><div class="text-muted">{{ t(request, 'lbl.uptime') }}</div>
          <div class="fw-bold">${data.uptime || "—"}</div></div>
        <div class="col-md-2"><div class="text-muted">{{ t(request, 'lbl.threads') }}</div>
          <div class="fw-bold">${data.total_threads ?? "—"}</div></div>
        <div class="col-md-2"><div class="text-muted">{{ t(request, 'lbl.heap') }}</div>
          <div class="fw-bold">${data.heap_utilization || "—"}</div></div>
        <div class="col-md-2"><div class="text-muted">{{ t(request, 'lbl.ingest') }}</div>
          <div>${ingestPill}</div></div>
      </div>`;
    meta.textContent = data.version ? "v" + data.version : "—";
  } catch (e) {
    console.error("codex etl fetch failed", e);
  }
}

const HEALTH_BADGE = {
  ok:   "bg-success",
  info: "bg-info text-dark",
  warn: "bg-warning text-dark",
  crit: "bg-danger",
};

async function loadCodexHealthEvents() {
  try {
    const r = await fetch("/api/health/events?limit=25");
    const data = await r.json();
    const body = document.getElementById("codex-health-body");
    const meta = document.getElementById("codex-health-meta");
    const events = data.events || [];
    if (!events.length) {
      body.innerHTML = `<tr><td colspan="7" class="text-muted text-center py-3">{{ t(request, 'lbl.no_data') }}</td></tr>`;
      meta.textContent = "0";
      return;
    }
    body.innerHTML = events.map(ev => {
      const sev = ev.severity || "info";
      const flags = (ev.flags || []).join(", ") || "—";
      return `<tr>
        <td><span class="badge ${HEALTH_BADGE[sev] || "bg-secondary"}">${sev}</span></td>
        <td class="font-monospace small">${(ev.source_tag || "").replace(/[<>]/g, "")}</td>
        <td class="text-end small">${ev.declared_entities ?? "–"}</td>
        <td class="text-end small">${ev.delta_entities ?? "–"}</td>
        <td class="text-end small">${ev.delta_relations ?? "–"}</td>
        <td class="small">${flags.replace(/[<>]/g, "")}</td>
        <td class="small">${ev.ts ? new Date(ev.ts * 1000).toLocaleString() : "–"}</td>
      </tr>`;
    }).join("");
    meta.textContent = String(events.length);
  } catch (e) {
    console.error("data-health fetch failed", e);
  }
}

async function loadCodexVersioning() {
  try {
    const r = await fetch("/api/codex/versioning/log?limit=25");
    const data = await r.json();
    const body = document.getElementById("codex-versioning-body");
    const meta = document.getElementById("codex-versioning-meta");
    if (!data.lakefs_configured) {
      body.innerHTML = `<tr><td colspan="4" class="text-muted text-center py-3">{{ t(request, 'lbl.lakefs_not_configured') }}</td></tr>`;
      meta.textContent = "—";
      return;
    }
    if (data.error) {
      body.innerHTML = `<tr><td colspan="4" class="text-warning text-center py-3"><i class="bi bi-info-circle me-1"></i>${data.error}</td></tr>`;
      meta.textContent = data.repo || "moe-knowledge";
      return;
    }
    const commits = data.commits || [];
    if (!commits.length) {
      body.innerHTML = `<tr><td colspan="4" class="text-muted text-center py-3">{{ t(request, 'lbl.no_data') }}</td></tr>`;
      meta.textContent = (data.repo || "moe-knowledge") + " — 0";
      return;
    }
    body.innerHTML = commits.map(c => {
      const shortId = (c.id || "").slice(0, 8);
      const safeMsg = (c.message || "—").replace(/[<>]/g, "");
      const ts = c.creation_date ? new Date(c.creation_date * 1000).toISOString() : null;
      return `<tr>
        <td class="font-monospace small">${shortId}…</td>
        <td class="small">${safeMsg}</td>
        <td class="small text-muted">${c.committer || "—"}</td>
        <td class="small">${fmtTs(ts)}</td>
      </tr>`;
    }).join("");
    meta.textContent = (data.repo || "moe-knowledge") + " — " + commits.length;
  } catch (e) {
    console.error("codex versioning fetch failed", e);
  }
}

async function loadCodex() {
  document.getElementById("codex-last-update").textContent = "{{ t(request, 'lbl.loading') }}";
  await Promise.all([
    loadCodexHealth(),
    loadCodexRuns(),
    loadCodexEtl(),
    loadCodexHealthEvents(),
    loadCodexVersioning(),
  ]);
  document.getElementById("codex-last-update").textContent = new Date().toLocaleTimeString();
}

loadCodex();
setInterval(loadCodex, 30000);
</script>
{% endblock %}
