'use client';

import { useEffect, useMemo, useRef, useState } from 'react';
import {
  BrainCircuit,
  ExternalLink,
  FileText,
  Link2,
  LoaderCircle,
  Pin,
  PinOff,
  Sparkles
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Panel } from '@/components/ui/panel';
import { Input } from '@/components/ui/input';
import { queueResearchCopilotJob, runResearchCopilotTurn } from '@/lib/api';
import type {
  ResearchCopilotCitation,
  ResearchCopilotSession,
  ResearchCopilotSuggestedAction,
  ResearchMemoSection,
  SearchSource
} from '@/lib/types';

type ResearchCopilotPanelProps = {
  ticker: string;
  companyName: string | null;
  session: ResearchCopilotSession | null;
  targetSection: ResearchMemoSection;
  variant?: 'docked' | 'focus';
  onSessionChange: (session: ResearchCopilotSession) => void;
  onDraftNote: (input: { title: string; summary: string; bodyMarkdown: string }) => void;
  onDraftMemoSection: (section: ResearchMemoSection, contentMarkdown: string) => void;
  onAttachCitation: (citation: ResearchCopilotCitation, section: ResearchMemoSection) => Promise<void>;
  onNotice: (message: string) => void;
  onError: (message: string) => void;
};

const DEFAULT_SOURCES: SearchSource[] = ['documents', 'filings', 'research'];
const SOURCE_OPTIONS: Array<{ value: SearchSource; label: string }> = [
  { value: 'documents', label: 'Documents' },
  { value: 'filings', label: 'Filing briefs' },
  { value: 'research', label: 'Research notes' }
];

type OptimisticMessage = {
  id: string;
  role: 'user';
  content_markdown: string;
};

function draftStorageKey(ticker: string) {
  return `research-copilot-draft:${ticker}`;
}

function toSummary(markdown: string) {
  const normalized = markdown.replace(/\s+/g, ' ').trim();
  return normalized.length > 180 ? `${normalized.slice(0, 177).trimEnd()}...` : normalized;
}

function buildSuggestedPrompts(companyName: string | null, ticker: string) {
  const label = companyName ?? ticker;
  return [
    `What changed in the latest evidence set for ${label}?`,
    `Draft a thesis update for ${ticker} with the strongest citations.`,
    `What evidence most directly challenges the current bull case?`
  ];
}

export function ResearchCopilotPanel({
  ticker,
  companyName,
  session,
  targetSection,
  variant = 'docked',
  onSessionChange,
  onDraftNote,
  onDraftMemoSection,
  onAttachCitation,
  onNotice,
  onError
}: ResearchCopilotPanelProps) {
  const scrollRef = useRef<HTMLDivElement | null>(null);
  const [prompt, setPrompt] = useState('');
  const [selectedSources, setSelectedSources] = useState<SearchSource[]>(session?.selected_sources ?? DEFAULT_SOURCES);
  const [pinnedArtifactIds, setPinnedArtifactIds] = useState<number[]>(session?.pinned_artifact_ids ?? []);
  const [optimisticMessages, setOptimisticMessages] = useState<OptimisticMessage[]>([]);
  const [submitting, setSubmitting] = useState(false);
  const [queueing, setQueueing] = useState(false);

  useEffect(() => {
    setSelectedSources(session?.selected_sources ?? DEFAULT_SOURCES);
    setPinnedArtifactIds(session?.pinned_artifact_ids ?? []);
  }, [session?.id, session?.updated_at]);

  useEffect(() => {
    const saved = typeof window === 'undefined' ? null : window.localStorage.getItem(draftStorageKey(ticker));
    setPrompt(saved ?? '');
  }, [ticker]);

  useEffect(() => {
    if (typeof window === 'undefined') {
      return;
    }

    const timeout = window.setTimeout(() => {
      window.localStorage.setItem(draftStorageKey(ticker), prompt);
    }, 250);

    return () => window.clearTimeout(timeout);
  }, [prompt, ticker]);

  useEffect(() => {
    if (!scrollRef.current) {
      return;
    }

    scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [session?.updated_at, optimisticMessages.length, submitting]);

  const messages = useMemo(() => {
    const persisted = session?.messages ?? [];
    const optimistic = optimisticMessages.map((message) => ({
      id: -1,
      session_id: session?.id ?? 0,
      user_id: '',
      role: message.role,
      content_markdown: message.content_markdown,
      citations: [],
      follow_ups: [],
      suggested_actions: [],
      selected_sources: selectedSources,
      pinned_artifact_ids: pinnedArtifactIds,
      memo_section: targetSection,
      created_at: new Date().toISOString()
    }));

    return [...persisted, ...optimistic];
  }, [optimisticMessages, pinnedArtifactIds, selectedSources, session, targetSection]);

  const sendTurn = async () => {
    const query = prompt.trim();
    if (!query || submitting) {
      return;
    }

    const optimisticMessage: OptimisticMessage = {
      id: `${Date.now()}`,
      role: 'user',
      content_markdown: query
    };
    setOptimisticMessages((current) => [...current, optimisticMessage]);
    setSubmitting(true);

    try {
      const response = await runResearchCopilotTurn({
        ticker,
        query,
        sources: selectedSources,
        pinnedArtifactIds,
        memoSection: targetSection
      });
      setPrompt('');
      setOptimisticMessages([]);
      if (typeof window !== 'undefined') {
        window.localStorage.removeItem(draftStorageKey(ticker));
      }
      onSessionChange(response.session);
    } catch (error) {
      setOptimisticMessages([]);
      onError(error instanceof Error ? error.message : 'Unable to run copilot turn');
    } finally {
      setSubmitting(false);
    }
  };

  const queueBrief = async (queryOverride?: string | null) => {
    const query = queryOverride?.trim() || prompt.trim();
    if (!query || queueing) {
      return;
    }

    setQueueing(true);
    try {
      await queueResearchCopilotJob({
        ticker,
        query,
        sources: selectedSources
      });
      onNotice('Queued research brief. Track progress in notifications.');
    } catch (error) {
      onError(error instanceof Error ? error.message : 'Unable to queue research brief');
    } finally {
      setQueueing(false);
    }
  };

  const applySuggestedAction = async (action: ResearchCopilotSuggestedAction) => {
    if (action.type === 'draft_note' && action.content_markdown) {
      onDraftNote({
        title: action.title ?? `${ticker} copilot draft`,
        summary: toSummary(action.content_markdown),
        bodyMarkdown: action.content_markdown
      });
      return;
    }

    if (action.type === 'draft_memo_section' && action.section && action.content_markdown) {
      onDraftMemoSection(action.section, action.content_markdown);
      return;
    }

    if (action.type === 'queue_research_brief') {
      await queueBrief(action.query);
    }
  };

  const suggestedPrompts = buildSuggestedPrompts(companyName, ticker);
  const panelClassName = variant === 'focus'
    ? 'min-h-[70vh]'
    : 'xl:sticky xl:top-6 self-start';

  return (
    <Panel
      className={panelClassName}
      title={variant === 'focus' ? 'Copilot Focus' : 'Research Copilot'}
      subtitle="Cited answers, follow-up questions, and draft actions tied directly to the current company workspace."
      actions={<BrainCircuit className="size-4 text-[color:var(--accent)]" />}
    >
      <div className="space-y-4">
        <div className="flex flex-wrap items-center gap-2">
          <span className="rounded-full border border-[color:var(--line-strong)] bg-[color:var(--panel)] px-2 py-1 text-[10px] uppercase tracking-[0.16em] text-[color:var(--accent)]">
            {ticker}
          </span>
          <span className="rounded-full border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-2 py-1 text-[10px] uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">
            Target: {targetSection.replace('_', ' ')}
          </span>
          {pinnedArtifactIds.length > 0 ? (
            <span className="rounded-full border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-2 py-1 text-[10px] uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">
              {pinnedArtifactIds.length} pinned
            </span>
          ) : null}
        </div>

        <div className="flex flex-wrap gap-2">
          {SOURCE_OPTIONS.map((option) => {
            const selected = selectedSources.includes(option.value);
            return (
              <Button
                key={option.value}
                type="button"
                variant={selected ? 'primary' : 'ghost'}
                className="px-2 py-1 text-xs"
                onClick={() => {
                  setSelectedSources((current) => {
                    if (selected && current.length > 1) {
                      return current.filter((entry) => entry !== option.value);
                    }

                    return selected ? current : [...current, option.value];
                  });
                }}
              >
                {option.label}
              </Button>
            );
          })}
        </div>

        <div
          ref={scrollRef}
          className={variant === 'focus'
            ? 'max-h-[52vh] overflow-y-auto rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4'
            : 'max-h-[36rem] overflow-y-auto rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4'
          }
        >
          {messages.length === 0 ? (
            <div className="space-y-3">
              <p className="text-sm text-[color:var(--terminal-muted)]">
                Ask for cited thesis changes, memo updates, risk summaries, or evidence gaps. This copilot uses the existing search index and current research context.
              </p>
              <div className="flex flex-wrap gap-2">
                {suggestedPrompts.map((suggestion) => (
                  <button
                    key={suggestion}
                    type="button"
                    className="rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] px-3 py-2 text-left text-xs text-[color:var(--terminal-muted)] transition hover:border-[color:var(--line-strong)] hover:text-[color:var(--terminal-bright)]"
                    onClick={() => setPrompt(suggestion)}
                  >
                    {suggestion}
                  </button>
                ))}
              </div>
            </div>
          ) : (
            <div className="space-y-4">
              {messages.map((message, index) => (
                <article
                  key={`${message.role}-${message.created_at}-${index}`}
                  className={message.role === 'assistant'
                    ? 'rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] p-4'
                    : 'rounded-2xl border border-[color:var(--line-weak)] bg-[rgba(255,255,255,0.03)] p-4'
                  }
                >
                  <div className="flex items-center justify-between gap-2">
                    <p className="text-[11px] uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">
                      {message.role === 'assistant' ? 'Copilot' : 'You'}
                    </p>
                    {message.role === 'assistant' ? <Sparkles className="size-4 text-[color:var(--accent)]" /> : null}
                  </div>
                  <p className="mt-3 whitespace-pre-wrap text-sm leading-7 text-[color:var(--terminal-bright)]">
                    {message.content_markdown}
                  </p>

                  {message.citations.length > 0 ? (
                    <div className="mt-4 space-y-2">
                      {message.citations.map((citation) => {
                        const pinned = citation.artifactId !== null && pinnedArtifactIds.includes(citation.artifactId);

                        return (
                          <div key={`${message.id}-${citation.index}`} className="rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-3">
                            <div className="flex flex-wrap items-start justify-between gap-2">
                              <div>
                                <p className="text-xs text-[color:var(--accent)]">[{citation.index}] {citation.label}</p>
                                <p className="mt-1 text-xs text-[color:var(--terminal-muted)]">{citation.excerpt}</p>
                              </div>
                              <div className="flex flex-wrap gap-2">
                                <a
                                  href={citation.href}
                                  className="inline-flex items-center gap-1 rounded-lg border border-[color:var(--line-weak)] px-2 py-1 text-xs text-[color:var(--accent)] transition hover:border-[color:var(--line-strong)]"
                                >
                                  Open
                                  <ExternalLink className="size-3" />
                                </a>
                                {citation.artifactId ? (
                                  <Button
                                    variant="ghost"
                                    className="px-2 py-1 text-xs"
                                    onClick={() => {
                                      setPinnedArtifactIds((current) => pinned
                                        ? current.filter((entry) => entry !== citation.artifactId)
                                        : [...current, citation.artifactId!]);
                                    }}
                                  >
                                    {pinned ? <PinOff className="size-3" /> : <Pin className="size-3" />}
                                    {pinned ? 'Unpin' : 'Pin'}
                                  </Button>
                                ) : null}
                                <Button
                                  variant="ghost"
                                  className="px-2 py-1 text-xs"
                                  onClick={() => {
                                    void onAttachCitation(citation, targetSection);
                                  }}
                                  disabled={!citation.artifactId}
                                >
                                  <Link2 className="size-3" />
                                  Attach
                                </Button>
                              </div>
                            </div>
                          </div>
                        );
                      })}
                    </div>
                  ) : null}

                  {message.role === 'assistant' && message.suggested_actions.length > 0 ? (
                    <div className="mt-4 flex flex-wrap gap-2">
                      {message.suggested_actions.map((action) => (
                        <Button
                          key={action.id}
                          variant={action.type === 'queue_research_brief' ? 'secondary' : 'ghost'}
                          className="px-2 py-1 text-xs"
                          onClick={() => {
                            void applySuggestedAction(action);
                          }}
                        >
                          {action.type === 'draft_note' ? <NotebookIcon /> : action.type === 'draft_memo_section' ? <FileText className="size-3" /> : <Sparkles className="size-3" />}
                          {action.label}
                        </Button>
                      ))}
                    </div>
                  ) : null}

                  {message.role === 'assistant' && message.follow_ups.length > 0 ? (
                    <div className="mt-4 flex flex-wrap gap-2">
                      {message.follow_ups.map((followUp) => (
                        <button
                          key={followUp}
                          type="button"
                          className="rounded-full border border-[color:var(--line-weak)] px-2 py-1 text-[11px] text-[color:var(--terminal-muted)] transition hover:border-[color:var(--line-strong)] hover:text-[color:var(--terminal-bright)]"
                          onClick={() => setPrompt(followUp)}
                        >
                          {followUp}
                        </button>
                      ))}
                    </div>
                  ) : null}
                </article>
              ))}
            </div>
          )}
          {submitting ? (
            <div className="mt-3 flex items-center gap-2 text-xs text-[color:var(--terminal-muted)]">
              <LoaderCircle className="size-3.5 animate-spin" />
              Running cited research turn...
            </div>
          ) : null}
        </div>

        <div className="space-y-3 rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4">
          <Input
            aria-label="Research copilot prompt"
            value={prompt}
            onChange={(event) => setPrompt(event.target.value)}
            placeholder="Ask for evidence-backed thesis updates, risk summaries, or draft memo language..."
            onKeyDown={(event) => {
              if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {
                event.preventDefault();
                void sendTurn();
              }
            }}
          />
          <div className="flex flex-wrap gap-2">
            <Button onClick={() => void sendTurn()} disabled={!prompt.trim() || submitting}>
              <BrainCircuit className="size-4" />
              {submitting ? 'Thinking...' : 'Ask copilot'}
            </Button>
            <Button variant="secondary" onClick={() => void queueBrief()} disabled={!prompt.trim() || queueing}>
              <Sparkles className="size-4" />
              {queueing ? 'Queueing...' : 'Queue brief'}
            </Button>
          </div>
        </div>
      </div>
    </Panel>
  );
}

function NotebookIcon() {
  return <FileText className="size-3" />;
}
