// Shrink recommendation panel: the primary immediate recommendation, the
// conditional opportunity (separate, never counted as realizable), and
// manual-review alternatives — the §9 tab over the schema-3
// ShrinkEvaluation artifact.

import type {
  ShrinkEvaluation,
  ShrinkScenario,
  ShrinkStatus,
} from "@/engine/types";
import type { WorkloadRow } from "@/engine/classify";
import { money, moneyDelta, num, deltaTone } from "@/lib/fmt";
import { Badge } from "@/components/ui/Badge";
import { Empty } from "@/components/ui/Empty";
import { PrerequisiteTable } from "@/components/regions/PrerequisiteTable";

const STATUS_LABEL: Record<ShrinkStatus, string> = {
  reviewRequired: "needs manual verification",
  blocked: "blocked",
  insufficientData: "insufficient data",
};

function statusTone(status: ShrinkStatus): "warn" | "bad" | "info" {
  if (status === "blocked") return "bad";
  if (status === "insufficientData") return "info";
  return "warn";
}

function changeText(c: ShrinkScenario["changes"][number]): string {
  const type =
    c.fromType === c.toType ? c.fromType : `${c.fromType} → ${c.toType}`;
  return `${c.nodeGroup} @ ${c.zone}: ${c.fromCount} → ${c.toCount} × ${type}`;
}

function ScenarioCard({
  scenario,
  streak,
  workloads,
}: {
  scenario: ShrinkScenario;
  streak: number | null;
  workloads: WorkloadRow[];
}) {
  return (
    <div className="space-y-2 rounded border border-border bg-surface-1 p-3">
      <div className="flex flex-wrap items-center gap-2">
        <span className="font-medium">
          {scenario.action === "remove" ? "Remove nodes" : "Resize to adjacent smaller SKU"}
        </span>
        <Badge tone={statusTone(scenario.status)}>{STATUS_LABEL[scenario.status]}</Badge>
        {scenario.mode === "conditional" ? <Badge tone="info">conditional</Badge> : null}
        {streak !== null ? (
          <Badge tone={streak >= 3 ? "good" : "info"}>
            stability {streak}/3
          </Badge>
        ) : null}
      </div>
      <ul className="text-sm text-text-muted">
        {scenario.changes.map((c, i) => (
          <li key={i}>{changeText(c)}</li>
        ))}
        <li>
          nodes {num(scenario.nodeCountBefore)} → {num(scenario.nodeCountAfter)}
        </li>
        <li>
          list-price compute {money(scenario.computeMonthlyCostUsd)} ·{" "}
          <span className={deltaTone(scenario.computeMonthlySavingsUsd, true)}>
            {moneyDelta(scenario.computeMonthlySavingsUsd)}/mo savings
          </span>
          {scenario.computeSavingsPercent !== null
            ? ` (${scenario.computeSavingsPercent.toFixed(1)}%)`
            : null}
        </li>
        <li>
          utilization req {scenario.utilization.requestCpuPct.toFixed(0)}%/{scenario.utilization.requestMemPct.toFixed(0)}% ·
          safe demand {scenario.utilization.safeDemandCpuPct.toFixed(0)}%/{scenario.utilization.safeDemandMemPct.toFixed(0)}% (cpu/mem)
        </li>
        <li>
          disruption: {num(scenario.disruption.nodesRemoved)} nodes removed ·{" "}
          {num(scenario.disruption.nodesReplaced)} replaced ·{" "}
          {num(scenario.disruption.statefulPodsAffected)} stateful /{" "}
          {num(scenario.disruption.criticalPodsAffected)} critical pods affected
        </li>
        {scenario.prerequisites.length > 0 ? (
          <li>prerequisites — the worklist below must be applied first</li>
        ) : null}
        <li>
          manual checks: {scenario.manualChecks.join(", ")} · apply one node at
          a time, re-evaluate between steps
        </li>
      </ul>
      {scenario.prerequisites.length > 0 ? (
        <PrerequisiteTable prerequisites={scenario.prerequisites} workloads={workloads} />
      ) : null}
    </div>
  );
}

export function ScenarioComparison({
  evaluation,
  streak,
  workloads,
}: {
  /** Legacy v1 artifacts ({ scenarios: [...] }) render as absent. */
  evaluation: ShrinkEvaluation | undefined;
  streak: number | null;
  /** the run's workload rows — joined with prerequisite strings to show
   *  current -> target requests (UI-layer join; no artifact change). */
  workloads: WorkloadRow[];
}) {
  const isSchema3 = evaluation?.schemaVersion === 3;
  if (!isSchema3) {
    return <Empty>No shrink evaluation on record for this run.</Empty>;
  }
  const primary = evaluation.primary;
  const conditional = evaluation.conditional;
  const alternatives = evaluation.alternatives ?? [];
  return (
    <div className="space-y-4">
      {primary ? (
        <ScenarioCard scenario={primary} streak={streak} workloads={workloads} />
      ) : (
        <Empty>
          No immediate recommendation. Nothing should change without
          re-review.
        </Empty>
      )}

      {conditional ? (
        <div className="space-y-2">
          <div className="text-sm font-medium text-text-muted">
            Conditional opportunity — requires workload changes first, never
            counted as realizable savings
          </div>
          <ScenarioCard scenario={conditional} streak={null} workloads={workloads} />
        </div>
      ) : null}

      {alternatives.length > 0 ? (
        <div>
          <div className="mb-1 text-sm font-medium text-text-muted">
            Manual-review alternatives (newer generation / cross-family)
          </div>
          <ul className="text-sm text-text-muted">
            {alternatives.map((a) => (
              <li key={`${a.fromInstanceType}->${a.toInstanceType}`}>
                {a.fromInstanceType} → {a.toInstanceType} ·{" "}
                {a.pricePerNodeUsd === null ? "price unknown" : `${money(a.pricePerNodeUsd)}/node/mo`}
              </li>
            ))}
          </ul>
        </div>
      ) : null}

      {!evaluation.searchComplete ? (
        <div className="text-xs text-text-muted">
          Evaluation hit the combination cap; the shown result is the best
          evaluated candidate, not an exhaustive optimum.
        </div>
      ) : null}
    </div>
  );
}
