import { useEffect, useRef, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import {
  Bot,
  Brain,
  CheckCircle2,
  CircleStop,
  Database,
  Loader2,
  MessageCircleMore,
  Send,
  Sparkles,
  XCircle,
} from 'lucide-react';
import { get } from '@/lib/api';
import {
  streamPiggyChat,
  type PiggyChatContext,
  type PiggyChatEvent,
  type PiggyChatTurn,
  type PiggyStatus,
} from '@/lib/piggy-chat';
import { Badge, Button, EmptyState, cn } from './ui';
import {
  Drawer,
  DrawerContent,
  DrawerDescription,
  DrawerHeader,
  DrawerTitle,
} from './ui/drawer';
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
} from './ui/sheet';
import { Textarea } from './ui/textarea';

interface ToolStep {
  id: string;
  name: string;
  arguments: unknown;
  state: 'running' | 'succeeded' | 'failed';
  error?: string;
}

interface TranscriptMessage {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  reasoning?: string;
  tools?: ToolStep[];
  error?: string;
  pending?: boolean;
}

export function PiggyAskButton({
  context,
  prompt,
  label = 'Ask Piggy',
  variant = 'outline',
}: {
  context?: PiggyChatContext;
  prompt?: string;
  label?: string;
  variant?: React.ComponentProps<typeof Button>['variant'];
}) {
  const [open, setOpen] = useState(false);
  const status = usePiggyStatus();
  const unavailable = status.data && !status.data.canUse;
  return (
    <>
      <Button
        type="button"
        variant={variant}
        disabled={Boolean(unavailable)}
        title={unavailable ? 'Piggy is disabled or this credential lacks read access.' : undefined}
        onClick={() => setOpen(true)}
      >
        <MessageCircleMore aria-hidden />
        {label}
      </Button>
      <ResponsivePiggyChat
        open={open}
        onOpenChange={setOpen}
        context={context}
        initialPrompt={prompt}
      />
    </>
  );
}

export function PiggyChatWorkspace() {
  const status = usePiggyStatus();
  if (status.isLoading) return <div className="h-96 animate-pulse rounded-xl bg-surface-2" />;
  if (!status.data?.canUse) {
    return (
      <EmptyState
        icon={<Bot />}
        title="Piggy is unavailable"
        description={
          status.data?.enabled
            ? 'This credential does not have read access.'
            : 'An administrator must enable Piggy and connect the internal service.'
        }
      />
    );
  }
  return <PiggyChatPanel className="h-[calc(100dvh-12rem)] min-h-[32rem] rounded-xl border border-border bg-surface" />;
}

function ResponsivePiggyChat({
  open,
  onOpenChange,
  context,
  initialPrompt,
}: {
  open: boolean;
  onOpenChange(open: boolean): void;
  context?: PiggyChatContext;
  initialPrompt?: string;
}) {
  const desktop = useDesktop();
  if (desktop) {
    return (
      <Sheet open={open} onOpenChange={onOpenChange}>
        <SheetContent side="right" className="flex h-dvh w-full flex-col p-0 sm:max-w-xl">
          <SheetHeader className="border-b border-border px-5 py-4">
            <SheetTitle>Ask Piggy</SheetTitle>
            <SheetDescription>{context?.label ? `Working from ${context.label}` : 'Working from your PIG workspace'}</SheetDescription>
          </SheetHeader>
          <PiggyChatPanel context={context} initialPrompt={initialPrompt} className="min-h-0 flex-1" />
        </SheetContent>
      </Sheet>
    );
  }
  return (
    <Drawer open={open} onOpenChange={onOpenChange}>
      <DrawerContent className="h-[92dvh]">
        <DrawerHeader className="border-b border-border px-4 pb-3 pt-2 text-left">
          <DrawerTitle>Ask Piggy</DrawerTitle>
          <DrawerDescription>{context?.label ? `Working from ${context.label}` : 'Working from your PIG workspace'}</DrawerDescription>
        </DrawerHeader>
        <PiggyChatPanel context={context} initialPrompt={initialPrompt} className="min-h-0 flex-1" />
      </DrawerContent>
    </Drawer>
  );
}

function PiggyChatPanel({
  context,
  initialPrompt = '',
  className,
}: {
  context?: PiggyChatContext;
  initialPrompt?: string;
  className?: string;
}) {
  const [messages, setMessages] = useState<TranscriptMessage[]>([]);
  const [draft, setDraft] = useState(initialPrompt);
  const [running, setRunning] = useState(false);
  const abortRef = useRef<AbortController | null>(null);
  const bottomRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => bottomRef.current?.scrollIntoView({ behavior: running ? 'auto' : 'smooth' }), [messages, running]);
  useEffect(() => () => abortRef.current?.abort(), []);

  const send = async () => {
    const message = draft.trim();
    if (!message || running) return;
    const user: TranscriptMessage = { id: crypto.randomUUID(), role: 'user', content: message };
    const assistantId = crypto.randomUUID();
    const history: PiggyChatTurn[] = messages
      .filter((entry) => entry.content.trim())
      .slice(-20)
      .map((entry) => ({ role: entry.role, content: entry.content }));
    setMessages((current) => [
      ...current,
      user,
      { id: assistantId, role: 'assistant', content: '', reasoning: '', tools: [], pending: true },
    ]);
    setDraft('');
    setRunning(true);
    const abort = new AbortController();
    abortRef.current = abort;

    try {
      for await (const event of streamPiggyChat({ message, history, context }, abort.signal)) {
        setMessages((current) =>
          current.map((entry) =>
            entry.id === assistantId ? applyEvent(entry, event) : entry,
          ),
        );
      }
    } catch (error) {
      if (!abort.signal.aborted) {
        setMessages((current) =>
          current.map((entry) =>
            entry.id === assistantId
              ? { ...entry, pending: false, error: error instanceof Error ? error.message : 'Piggy chat failed.' }
              : entry,
          ),
        );
      }
    } finally {
      abortRef.current = null;
      setRunning(false);
    }
  };

  return (
    <div className={cn('flex min-h-0 flex-col', className)}>
      <div className="min-h-0 flex-1 overflow-y-auto px-4 py-5 sm:px-5">
        {messages.length === 0 ? (
          <div className="mx-auto flex h-full max-w-md flex-col items-center justify-center text-center">
            <div className="flex size-12 items-center justify-center rounded-2xl bg-accent-subtle text-accent-fg"><Sparkles aria-hidden /></div>
            <h2 className="mt-4 font-semibold">What should we inspect?</h2>
            <p className="mt-1 text-sm text-muted">Piggy reads only through scoped PIG tools. It has no shell, filesystem or browser access.</p>
            <div className="mt-4 grid w-full gap-2">
              {(context
                ? ['Summarise this record', 'What needs attention?', 'Which terms or dates matter most?']
                : ['What needs attention across the book?', 'Summarise active commitments', 'Which renewals are approaching?']
              ).map((suggestion) => (
                <button key={suggestion} type="button" className="min-h-11 rounded-lg border border-border px-3 text-left text-sm hover:bg-surface-2" onClick={() => setDraft(suggestion)}>{suggestion}</button>
              ))}
            </div>
          </div>
        ) : (
          <div className="flex flex-col gap-4">
            {messages.map((message) => <ChatMessage key={message.id} message={message} />)}
            <div ref={bottomRef} />
          </div>
        )}
      </div>

      <form className="border-t border-border bg-surface p-3 sm:p-4" onSubmit={(event) => { event.preventDefault(); void send(); }}>
        {context ? <Badge className="mb-2 max-w-full truncate"><Database aria-hidden /> {context.label ?? context.type.replaceAll('_', ' ')}</Badge> : null}
        <div className="flex items-end gap-2">
          <Textarea
            value={draft}
            onChange={(event) => setDraft(event.target.value)}
            onKeyDown={(event) => {
              if (event.key === 'Enter' && !event.shiftKey) {
                event.preventDefault();
                void send();
              }
            }}
            className="min-h-11 max-h-36 resize-none"
            placeholder="Ask about capacity, margin, paper or next actions…"
            aria-label="Message Piggy"
          />
          {running ? (
            <Button type="button" size="icon" variant="outline" aria-label="Stop Piggy" onClick={() => abortRef.current?.abort()}><CircleStop aria-hidden /></Button>
          ) : (
            <Button type="submit" size="icon" variant="primary" disabled={!draft.trim()} aria-label="Send message"><Send aria-hidden /></Button>
          )}
        </div>
        <p className="mt-2 text-center text-[11px] text-muted">Check source records before acting on material terms.</p>
      </form>
    </div>
  );
}

function ChatMessage({ message }: { message: TranscriptMessage }) {
  if (message.role === 'user') {
    return <div className="ml-auto max-w-[88%] rounded-2xl rounded-br-md bg-primary px-4 py-3 text-sm text-accent-on"><p className="whitespace-pre-wrap">{message.content}</p></div>;
  }
  return (
    <div className="flex gap-3">
      <div className="flex size-9 shrink-0 items-center justify-center rounded-xl bg-accent-subtle text-accent-fg"><Bot aria-hidden /></div>
      <div className="min-w-0 flex-1">
        {message.reasoning ? (
          <details className="mb-2 rounded-lg bg-surface-2 text-xs text-muted">
            <summary className="flex min-h-11 cursor-pointer items-center gap-2 px-3 py-2 font-medium"><Brain aria-hidden /> Reasoning</summary>
            <p className="whitespace-pre-wrap px-3 pb-3">{message.reasoning}</p>
          </details>
        ) : null}
        {message.tools?.length ? <ToolTimeline tools={message.tools} /> : null}
        {message.content ? <p className="whitespace-pre-wrap text-sm leading-6">{message.content}</p> : null}
        {message.pending && !message.content ? <div className="flex min-h-11 items-center gap-2 text-sm text-muted"><Loader2 className="animate-spin" aria-hidden /> Piggy is checking PIG…</div> : null}
        {message.error ? <div className="mt-2 flex items-start gap-2 rounded-lg bg-danger/10 p-3 text-sm text-danger"><XCircle className="shrink-0" aria-hidden /> {message.error}</div> : null}
      </div>
    </div>
  );
}

function ToolTimeline({ tools }: { tools: ToolStep[] }) {
  return (
    <div className="mb-3 flex flex-col gap-1.5" aria-label="Piggy tool activity">
      {tools.map((tool) => (
        <details key={tool.id} className="rounded-lg border border-border text-xs">
          <summary className="flex min-h-11 cursor-pointer items-center gap-2 px-3 py-2">
            {tool.state === 'running' ? <Loader2 className="animate-spin text-muted" aria-hidden /> : tool.state === 'succeeded' ? <CheckCircle2 className="text-positive" aria-hidden /> : <XCircle className="text-danger" aria-hidden />}
            <span className="font-medium">{toolLabel(tool.name)}</span>
            <span className="ml-auto text-muted">{tool.state === 'running' ? 'Running' : tool.state === 'succeeded' ? 'Complete' : 'Failed'}</span>
          </summary>
          <pre className="overflow-x-auto border-t border-border p-3 text-[11px] text-muted">{tool.error ?? JSON.stringify(tool.arguments, null, 2)}</pre>
        </details>
      ))}
    </div>
  );
}

function applyEvent(message: TranscriptMessage, event: PiggyChatEvent): TranscriptMessage {
  if (event.type === 'content_delta') return { ...message, content: message.content + event.delta };
  if (event.type === 'reasoning_delta') return { ...message, reasoning: (message.reasoning ?? '') + event.delta };
  if (event.type === 'tool_call') return { ...message, tools: [...(message.tools ?? []), { id: event.id, name: event.name, arguments: event.arguments, state: 'running' }] };
  if (event.type === 'tool_result') return { ...message, tools: (message.tools ?? []).map((tool) => tool.id === event.id ? { ...tool, state: event.ok ? 'succeeded' : 'failed', error: event.error } : tool) };
  if (event.type === 'done') return { ...message, pending: false };
  if (event.type === 'error') return { ...message, pending: false, error: event.message };
  return message;
}

function usePiggyStatus() {
  return useQuery({ queryKey: ['piggy', 'status'], queryFn: () => get<PiggyStatus>('/api/piggy/status'), staleTime: 60_000, retry: false });
}

function useDesktop(): boolean {
  const [desktop, setDesktop] = useState(() => typeof window !== 'undefined' && window.matchMedia('(min-width: 768px)').matches);
  useEffect(() => {
    const media = window.matchMedia('(min-width: 768px)');
    const update = () => setDesktop(media.matches);
    media.addEventListener('change', update);
    return () => media.removeEventListener('change', update);
  }, []);
  return desktop;
}

function toolLabel(name: string): string {
  return name.replace(/^pig_/, '').replaceAll('_', ' ').replace(/\b\w/g, (letter) => letter.toUpperCase());
}
