import { memo, useEffect, useState } from 'react';
import type { AgentRun } from '../../lib/orchestratorApi';
import type { Card } from '../../lib/kanbanApi';

/**
 * Floating "active agents" dock for the implementation board.
 *
 * Pins to the bottom-right and lists every run currently in flight, each a
 * one-click jump to that card's detail modal. Lives below the card modal
 * (z-index 40 < 50): when a modal is open you're focused on one card; the dock
 * is for the common case of scanning the board while agents work in the
 * background. Reads only from the registry (`runs`) + the board's card map, so
 * it needs no backend changes. Re-renders are isolated: a 1 s tick for live
 * elapsed times lives inside this component, never the board page.
 */

interface RunningAgentsBarProps {
  /** Full run list from the registry; only `running` entries are shown. */
  runs: AgentRun[];
  /** Card lookup for titles/categories (empty until the board loads — ids still show). */
  cardById: Map<string, Card>;
  /** Open a card's detail modal. */
  onOpenCard: (cardId: string) => void;
}

/** Tick once a second while anything is active, for live elapsed times. */
function useNow(active: boolean): number {
  const [now, setNow] = useState(() => Date.now());
  useEffect(() => {
    if (!active) return;
    const id = setInterval(() => setNow(Date.now()), 1000);
    return () => clearInterval(id);
  }, [active]);
  return now;
}

function fmtElapsed(startedAtIso: string | null, now: number): string {
  if (!startedAtIso) return '';
  const start = Date.parse(startedAtIso);
  if (!Number.isFinite(start)) return '';
  const s = Math.max(0, Math.floor((now - start) / 1000));
  if (s < 60) return `${s}s`;
  const m = Math.floor(s / 60);
  if (m < 60) return `${m}m ${String(s % 60).padStart(2, '0')}s`;
  const h = Math.floor(m / 60);
  return `${h}h ${String(m % 60).padStart(2, '0')}m`;
}

/** Shorten `agent/u1-bec600e2` → `u1-bec600e2`. */
function shortBranch(branch: string): string {
  const idx = branch.lastIndexOf('/');
  return idx >= 0 ? branch.slice(idx + 1) : branch;
}

export const RunningAgentsBar = memo(function RunningAgentsBar({
  runs,
  cardById,
  onOpenCard,
}: RunningAgentsBarProps) {
  const active = runs.filter((r) => r.status === 'running');
  const [collapsed, setCollapsed] = useState(false);
  const [hovered, setHovered] = useState<string | null>(null);
  const now = useNow(active.length > 0);

  if (active.length === 0) return null;

  const count = active.length;

  return (
    // Wrapper is non-interactive so the empty space around the dock never
    // swallows board clicks; children opt back into pointer events.
    <div style={{ ...wrapStyle, pointerEvents: 'none' }}>
      {!collapsed && (
        <div style={panelStyle}>
          <div style={panelHeaderStyle}>
            <span style={liveDotStyle} />
            <span style={headerTextStyle}>
              {count} agent{count === 1 ? '' : 's'} running
            </span>
          </div>
          <div style={listStyle}>
            {active.map((r) => {
              const card = cardById.get(r.cardId);
              const isHovered = hovered === r.id;
              return (
                <button
                  key={r.id}
                  type="button"
                  onClick={() => onOpenCard(r.cardId)}
                  onMouseEnter={() => setHovered(r.id)}
                  onMouseLeave={() => setHovered(null)}
                  style={{
                    ...rowStyle,
                    background: isHovered ? 'var(--surface-raised)' : 'transparent',
                    borderColor: isHovered ? 'var(--accent)' : 'var(--border)',
                  }}
                  title={`Open ${card?.title ?? r.cardId}`}
                >
                  <span style={rowDotStyle} />
                  <span style={{ minWidth: 0, flex: 1 }}>
                    <span style={titleStyle}>{card?.title ?? r.cardId}</span>
                    <span style={subStyle}>
                      <span style={idStyle}>{r.cardId}</span>
                      {r.branch && (
                        <span style={branchStyle}>⎇ {shortBranch(r.branch)}</span>
                      )}
                    </span>
                  </span>
                  <span style={elapsedStyle}>{fmtElapsed(r.startedAt, now)}</span>
                  <span style={{ ...openGlyphStyle, opacity: isHovered ? 1 : 0.4 }}>↗</span>
                </button>
              );
            })}
          </div>
        </div>
      )}

      <button
        type="button"
        onClick={() => setCollapsed((c) => !c)}
        style={toggleStyle}
        title={collapsed ? 'Show running agents' : 'Hide running agents'}
      >
        <span style={liveDotStyle} />
        <span>{count} running</span>
        <span style={{ marginLeft: '2px', opacity: 0.7 }}>{collapsed ? '▲' : '▼'}</span>
      </button>
    </div>
  );
});

// --- styles ----------------------------------------------------------------

const wrapStyle: React.CSSProperties = {
  position: 'fixed',
  right: 'var(--sp-4)',
  bottom: 'var(--sp-4)',
  zIndex: 40, // below the card modal (50) so an open modal stays focused
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'flex-end',
  gap: 'var(--sp-2)',
  maxWidth: '320px',
};

const panelStyle: React.CSSProperties = {
  pointerEvents: 'auto',
  width: '300px',
  background: 'var(--surface)',
  border: '1px solid var(--border)',
  borderRadius: 'var(--radius-md)',
  boxShadow: '0 8px 28px rgba(0,0,0,0.35)',
  overflow: 'hidden',
};

const panelHeaderStyle: React.CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  gap: '6px',
  padding: '8px 10px',
  borderBottom: '1px solid var(--border)',
  background: 'var(--surface-raised)',
};

const headerTextStyle: React.CSSProperties = {
  fontSize: '0.72rem',
  fontWeight: 600,
  color: 'var(--fg)',
  letterSpacing: '0.02em',
};

const listStyle: React.CSSProperties = {
  display: 'flex',
  flexDirection: 'column',
  maxHeight: '264px',
  overflowY: 'auto',
};

const rowStyle: React.CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  gap: '8px',
  width: '100%',
  padding: '8px 10px',
  textAlign: 'left',
  cursor: 'pointer',
  borderTop: 'none',
  borderLeft: 'none',
  borderRight: 'none',
  borderBottom: '1px solid var(--border)',
  borderRadius: 0,
  transition: 'background 0.12s ease, border-color 0.12s ease',
};

const rowDotStyle: React.CSSProperties = {
  width: '7px',
  height: '7px',
  borderRadius: '50%',
  background: 'var(--accent)',
  boxShadow: '0 0 6px var(--accent)',
  animation: 'vn-pulse 1.1s ease-in-out infinite',
  flexShrink: 0,
};

const titleStyle: React.CSSProperties = {
  display: 'block',
  fontSize: '0.8rem',
  fontWeight: 500,
  color: 'var(--fg)',
  whiteSpace: 'nowrap',
  overflow: 'hidden',
  textOverflow: 'ellipsis',
};

const subStyle: React.CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  gap: '6px',
  marginTop: '2px',
};

const idStyle: React.CSSProperties = {
  fontFamily: 'var(--font-mono)',
  fontSize: '0.62rem',
  color: 'var(--muted)',
  background: 'var(--bg)',
  padding: '1px 5px',
  borderRadius: 'var(--radius-sm)',
};

const branchStyle: React.CSSProperties = {
  fontFamily: 'var(--font-mono)',
  fontSize: '0.6rem',
  color: 'var(--fg-dim)',
  whiteSpace: 'nowrap',
  overflow: 'hidden',
  textOverflow: 'ellipsis',
};

const elapsedStyle: React.CSSProperties = {
  fontFamily: 'var(--font-mono)',
  fontSize: '0.66rem',
  color: 'var(--accent)',
  flexShrink: 0,
  fontVariantNumeric: 'tabular-nums',
};

const openGlyphStyle: React.CSSProperties = {
  fontSize: '0.7rem',
  color: 'var(--fg-dim)',
  flexShrink: 0,
};

const toggleStyle: React.CSSProperties = {
  pointerEvents: 'auto',
  display: 'inline-flex',
  alignItems: 'center',
  gap: '6px',
  padding: '6px 12px',
  fontSize: '0.72rem',
  fontFamily: 'var(--font-mono)',
  color: 'var(--accent)',
  background: 'var(--surface)',
  border: '1px solid var(--border)',
  borderRadius: 'var(--radius-pill)',
  cursor: 'pointer',
  boxShadow: '0 4px 14px rgba(0,0,0,0.3)',
  whiteSpace: 'nowrap',
};

const liveDotStyle: React.CSSProperties = {
  width: '8px',
  height: '8px',
  borderRadius: '50%',
  background: 'var(--accent)',
  boxShadow: '0 0 6px var(--accent)',
  animation: 'vn-pulse 1.1s ease-in-out infinite',
  flexShrink: 0,
};
