<script lang="ts">
  // Phase 3 — Energy tag chip. Cycles a task's energy level through
  // the spec's four states: unset → High → Medium → Zero → unset.
  //
  // Visual discipline: when energy is unset, the chip renders at a
  // muted but still legible opacity so users can discover the affordance
  // without first hovering the row. The previous "0% until hover"
  // behaviour hid the control entirely, which read as broken on first
  // contact. Once set, the chip is always fully visible because the
  // colour IS the signal for the match-my-energy sort.
  //
  // Colour choices borrow the existing design tokens:
  //   High   → accent (warm, on-brand, attention-ready)
  //   Medium → warning (amber, unforced)
  //   Zero   → text-tertiary (low-energy grey, not danger red — the
  //            brief is explicit that this state must not feel
  //            pathologised; the internal enum value remains
  //            `brain_dead` to avoid a DB migration churn)
  //
  // Callers pass the task's current energy and a setter. This component
  // owns no state — the task store is the source of truth.

  import type { EnergyLevel } from "$lib/types/app";
  import { Zap } from "lucide-svelte";

  let {
    energy = null as EnergyLevel | null,
    onSelect,
    size = "sm",
    reduceMotion = false,
  }: {
    energy: EnergyLevel | null;
    onSelect: (next: EnergyLevel | null) => void;
    size?: "sm" | "md";
    reduceMotion?: boolean;
  } = $props();

  // Cycle order lives here so the chip is the single authority on what
  // "next" means. Tap once to tag, tap again to move up, tap past
  // Zero to clear. Keyboard-equivalent via the <button> element.
  const CYCLE: (EnergyLevel | null)[] = [null, "high", "medium", "brain_dead"];

  function next(): EnergyLevel | null {
    const idx = CYCLE.indexOf(energy);
    return CYCLE[(idx + 1) % CYCLE.length];
  }

  function labelFor(level: EnergyLevel | null): string {
    switch (level) {
      case "high": return "High";
      case "medium": return "Medium";
      case "brain_dead": return "Zero";
      default: return "No energy set";
    }
  }

  let tooltip = $derived(
    energy === null
      ? "Tag energy (click to set)"
      : `Energy: ${labelFor(energy)} — click to change`
  );

  // Icon dimensions. `md` is the one used on the Tasks-page main rows;
  // `sm` is for the compact WIP list rows and micro-step children.
  let iconSize = $derived(size === "md" ? 13 : 10);
  let chipSize = $derived(size === "md" ? "h-5" : "h-4");
</script>

<button
  type="button"
  class="energy-chip inline-flex items-center justify-center rounded-md border px-1 {chipSize} text-[10px] font-medium
    {energy === null
      ? 'opacity-60 group-hover:opacity-100 text-text-tertiary border-border-subtle hover:border-accent hover:text-text-secondary'
      : ''}
    {energy === 'high'
      ? 'text-accent border-accent bg-accent/10'
      : ''}
    {energy === 'medium'
      ? 'text-warning border-warning bg-warning/10'
      : ''}
    {energy === 'brain_dead'
      ? 'text-text-tertiary border-border bg-hover'
      : ''}"
  onclick={() => onSelect(next())}
  aria-label={tooltip}
  title={tooltip}
  data-energy={energy ?? 'unset'}
  style={reduceMotion
    ? ''
    : 'transition: opacity var(--duration-ui), color var(--duration-ui), border-color var(--duration-ui), background-color var(--duration-ui)'}
>
  <Zap size={iconSize} aria-hidden="true" />
  {#if energy !== null && size === "md"}
    <span class="ml-1">{labelFor(energy)}</span>
  {/if}
</button>

<style>
  .energy-chip {
    cursor: pointer;
    line-height: 1;
    font-family: var(--font-family-body);
  }

  .energy-chip:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 1px;
  }
</style>
