import { Show, createMemo, type Component } from "solid-js";
import type { BackendSnapshot, PoolBackendSnapshot } from "../types";
import StatusBadge from "../components/StatusBadge";
import ProbeHeartbeat from "../components/ProbeHeartbeat";
import Flash from "../components/Flash";
import BackendActionsMenu from "../components/BackendActionsMenu";
import { lastTransitionAge, lbBucketsFor, state as appState } from "../stores/state";
import { isAdmin } from "../stores/mode";

type Props = {
  maglevd: string;
  frontend: string;
  pool: string;
  // showPool=true renders the pool name in the first column. Set
  // only on the first backend row of each pool; subsequent rows in
  // the same pool leave the cell blank, giving the "grouped table"
  // look where the pool label appears once above its members.
  showPool: boolean;
  // poolActive=false means every backend in this row's pool has
  // effective_weight=0 right now — a standby fallback or a fully
  // drained primary. The row is rendered dimmer so the operator
  // can scan which pool is actually carrying traffic.
  poolActive: boolean;
  backend: BackendSnapshot;
  poolBackend: PoolBackendSnapshot;
};

const BackendRow: Component<Props> = (props) => {
  const b = () => props.backend;
  // Subscribed lookup: lbBucketsFor reads from the reactive store, so
  // the cell re-renders the moment a "lb-state" SSE event mutates the
  // map. A missing entry (VPP disconnected, backend not yet programmed)
  // renders as an em-dash; an explicit 0 means "in VPP, drained".
  // createMemo guarantees Flash only sees a new value when the leaf
  // actually changed — without it, any spurious upstream re-run (e.g.
  // a sibling backend's transition triggering recomputeDerivedState)
  // would pop the bucket cell on every backend in the table.
  const bucketsLabel = createMemo<number | "—">(() => {
    const v = lbBucketsFor(appState.byName[props.maglevd], props.frontend, b().name);
    return v === undefined ? "—" : v;
  });
  return (
    <tr
      class="backend-row"
      classList={{ "pool-standby": !props.poolActive }}
      data-state={b().state}
    >
      <td class="col-pool">{props.showPool ? props.pool : ""}</td>
      <td class="backend-name">
        <ProbeHeartbeat maglevd={props.maglevd} backend={b().name} state={b().state} />
        <span class="backend-name-text">{b().name}</span>
      </td>
      <td class="backend-address">{b().address}</td>
      <td>
        <Flash value={b().state}>
          <StatusBadge state={b().state} />
        </Flash>
      </td>
      <td class="numeric">
        <Flash value={props.poolBackend.weight} />
      </td>
      <td class="numeric">
        <Flash value={props.poolBackend.effective_weight} />
      </td>
      <td class="numeric">
        <Flash value={bucketsLabel()} />
      </td>
      <td class="age">{lastTransitionAge(b().last_transition)}</td>
      <Show when={isAdmin}>
        <td class="actions">
          <BackendActionsMenu
            maglevd={props.maglevd}
            frontend={props.frontend}
            pool={props.pool}
            backend={b().name}
            state={b().state}
            configuredWeight={props.poolBackend.weight}
          />
        </td>
      </Show>
    </tr>
  );
};

export default BackendRow;
