import { For, Show, type Component } from "solid-js";
import type { FrontendSnapshot, StateSnapshot } from "../types";
import BackendRow from "./BackendRow";
import StatusBadge from "../components/StatusBadge";
import Flash from "../components/Flash";
import Zippy from "../components/Zippy";
import { isAdmin } from "../stores/mode";
import { formatVIPAddress } from "../stores/state";

type Props = {
  snap: StateSnapshot;
  frontend: FrontendSnapshot;
};

// FrontendCard is rendered as a Zippy so a deployment with many VIPs
// can collapse the frontends it doesn't care about. The title line
// carries the frontend name, a live state badge, address:port, the
// protocol, the sticky marker, and (when set) the description.
//
// The body renders a single consolidated backend table with one row
// per (pool, backend). The first column holds the pool name, shown
// only on the first row of each pool and blank on subsequent rows —
// a classic grouped-table layout that keeps rows dense while still
// making pool grouping instantly scannable.
const FrontendCard: Component<Props> = (props) => {
  const backendByName = () => Object.fromEntries(props.snap.backends.map((b) => [b.name, b]));
  const fe = () => props.frontend;

  const title = (
    <span class="frontend-title">
      <span class="frontend-title-name">{fe().name}</span>
      <Flash value={fe().state ?? "unknown"}>
        <StatusBadge state={fe().state ?? "unknown"} />
      </Flash>
      <span class="frontend-title-addr">{formatVIPAddress(fe().address, fe().port)}</span>
      <span class="frontend-title-proto">{fe().protocol.toUpperCase()}</span>
      {fe().src_ip_sticky && <span class="tag">sticky</span>}
      {fe().description && <span class="frontend-title-desc">{fe().description}</span>}
    </span>
  );

  return (
    <Zippy title={title} open>
      <table class="backend-table">
        <thead>
          <tr>
            <th class="col-pool">pool</th>
            <th class="col-name">backend</th>
            <th class="col-address">address</th>
            <th class="col-state">state</th>
            <th class="col-weight numeric">weight</th>
            <th class="col-effective numeric">effective</th>
            <th class="col-age">last transition</th>
            <Show when={isAdmin}>
              <th class="col-actions actions" />
            </Show>
          </tr>
        </thead>
        <tbody>
          <For each={fe().pools}>
            {(pool) => {
              // A pool is "active" when at least one of its backends
              // is currently serving traffic (effective_weight > 0).
              // Inactive pools — standby fallbacks, fully-drained
              // primaries — have every row rendered dimmer so the
              // operator can see at a glance which pool is actually
              // carrying traffic right now.
              const poolActive = () => pool.backends.some((pb) => pb.effective_weight > 0);
              return (
                <For each={pool.backends}>
                  {(pb, idx) => {
                    const backend = backendByName()[pb.name];
                    if (!backend) return null;
                    return (
                      <BackendRow
                        maglevd={props.snap.maglevd.name}
                        frontend={fe().name}
                        pool={pool.name}
                        showPool={idx() === 0}
                        poolActive={poolActive()}
                        backend={backend}
                        poolBackend={pb}
                      />
                    );
                  }}
                </For>
              );
            }}
          </For>
        </tbody>
      </table>
    </Zippy>
  );
};

export default FrontendCard;
