/**
 * Piggy, docked.
 *
 * The third pane. It is a column rather than a sheet because the point of
 * docking an agent is that you can read the page and the answer at the same
 * time — a sheet that covers the thing you are asking about defeats it.
 *
 * Three surfaces, one panel:
 *
 *   ≥ xl  — this permanent column, remembered between sessions.
 *   ≥ lg  — the existing right-hand Sheet, because 1024px minus a sidebar
 *           minus a 22rem dock leaves the page narrower than a phone.
 *   < lg  — the existing bottom Drawer.
 *
 * The status gate is not optional. `/api/piggy/chat` answers 503 when the
 * runtime is disabled, so a dock that renders its composer without asking
 * first is a permanent third of the window that fails on first use.
 */
import { useState } from 'react';
import { PanelRightClose, Sparkles } from 'lucide-react';
import { useHasDockRoom } from '@/hooks/use-media-query';
import { useLayout } from '@/lib/layout';
import { usePiggyCurrentContext } from '@/lib/piggy-context';
import { PiggyChatPanel, ResponsivePiggyChat, usePiggyStatus } from './PiggyChat';
import { PiggyMark } from './PiggyMark';
import { Button, EmptyState, Skeleton, cn } from './ui';

export function PiggyDock() {
  const { dockOpen, setDockOpen } = useLayout();
  const hasRoom = useHasDockRoom();
  const status = usePiggyStatus();
  const context = usePiggyCurrentContext();

  if (!hasRoom || !dockOpen) return null;

  return (
    <aside
      // `xl:flex` as well as the hook: the media query and the class agree, so
      // there is no frame where the column exists at the wrong width.
      className={cn(
        'hidden w-[--dock-width] shrink-0 flex-col overflow-hidden border-l border-border bg-surface xl:flex',
        'pr-[var(--safe-right)]',
      )}
      style={{
        position: 'sticky',
        top: 'var(--app-header-h)',
        height: 'calc(100dvh - var(--app-header-h))',
      }}
      aria-label="Piggy"
    >
      <div className="flex h-12 shrink-0 items-center gap-2 border-b border-border px-3">
        <PiggyMark className="size-5 shrink-0 text-accent-fg" />
        <span className="min-w-0 truncate text-sm font-semibold">Piggy</span>
        <Button
          type="button"
          variant="ghost"
          size="icon"
          className="ml-auto size-9 min-h-0 min-w-0 text-muted"
          aria-label="Close the Piggy panel"
          onClick={() => setDockOpen(false)}
        >
          <PanelRightClose className="size-4" aria-hidden />
        </Button>
      </div>

      {status.isLoading ? (
        <div className="flex flex-col gap-3 p-3">
          <Skeleton className="h-20 rounded-xl" />
          <Skeleton className="h-12 rounded-xl" />
        </div>
      ) : !status.data?.canUse ? (
        <EmptyState
          icon={<Sparkles />}
          title="Piggy is unavailable"
          description={
            status.data?.enabled
              ? 'This credential does not have read access.'
              : 'An administrator must enable the isolated Piggy runtime.'
          }
        />
      ) : (
        // Remounted per RECORD, so the transcript never carries an answer
        // about one row into a conversation about another. Page contexts all
        // share one key: they change on every navigation, and remounting there
        // threw away the transcript, the composer draft and any in-flight
        // stream (PiggyChat aborts on unmount) — which is the whole point of a
        // pane that stays put while you move around the app. The panel reads
        // `context` at send time, so the page it is asking about still tracks
        // the route without a remount.
        <PiggyChatPanel
          key={context.type === 'page' ? 'page' : JSON.stringify(context)}
          context={context}
          compact
          className="min-h-0 flex-1"
        />
      )}
    </aside>
  );
}

/**
 * The header control for Piggy.
 *
 * Below `xl` there is no column to toggle, so the same button opens the sheet
 * or drawer instead — one affordance in one place, whatever the viewport can
 * accommodate.
 */
export function PiggyDockToggle({ className }: { className?: string }) {
  const { dockOpen, setDockOpen } = useLayout();
  const hasRoom = useHasDockRoom();
  const status = usePiggyStatus();
  const context = usePiggyCurrentContext();
  const [overlayOpen, setOverlayOpen] = useState(false);
  const unavailable = status.data && !status.data.canUse;

  return (
    <>
      <Button
        type="button"
        variant="ghost"
        size="icon"
        className={cn('text-muted', dockOpen && hasRoom && 'bg-accent-subtle text-accent-fg', className)}
        disabled={Boolean(unavailable)}
        aria-pressed={hasRoom ? dockOpen : undefined}
        aria-label={
          unavailable
            ? 'Piggy is unavailable'
            : hasRoom
              ? dockOpen
                ? 'Close the Piggy panel'
                : 'Open the Piggy panel'
              : 'Ask Piggy'
        }
        title={unavailable ? 'Piggy is disabled or this credential lacks read access.' : 'Piggy'}
        onClick={() => (hasRoom ? setDockOpen(!dockOpen) : setOverlayOpen(true))}
      >
        <PiggyMark className="size-5" />
      </Button>
      {hasRoom ? null : (
        <ResponsivePiggyChat open={overlayOpen} onOpenChange={setOverlayOpen} context={context} />
      )}
    </>
  );
}
