'use client';

import Link from 'next/link';
import { Suspense, useEffect, useMemo, useState, useTransition } from 'react';
import { useSearchParams } from 'next/navigation';
import { useQueryClient } from '@tanstack/react-query';
import { BrainCircuit, ExternalLink, Search as SearchIcon } from 'lucide-react';
import { AppShell } from '@/components/shell/app-shell';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Panel } from '@/components/ui/panel';
import { useAuthGuard } from '@/hooks/use-auth-guard';
import { ensureTickerAutomation, getSearchAnswer } from '@/lib/api';
import { searchQueryOptions } from '@/lib/query/options';
import type { SearchAnswerResponse, SearchResult, SearchSource } from '@/lib/types';

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

function parseSourceParams(value: string | null) {
  if (!value) {
    return ['documents', 'filings', 'research'] as SearchSource[];
  }

  const normalized = value
    .split(',')
    .map((entry) => entry.trim().toLowerCase())
    .filter((entry): entry is SearchSource => entry === 'documents' || entry === 'filings' || entry === 'research');

  return normalized.length > 0 ? [...new Set(normalized)] : ['documents', 'filings', 'research'] as SearchSource[];
}

export default function SearchPage() {
  return (
    <Suspense fallback={<div className="flex min-h-screen items-center justify-center text-sm text-[color:var(--terminal-muted)]">Loading search desk...</div>}>
      <SearchPageContent />
    </Suspense>
  );
}

function SearchPageContent() {
  const { isPending, isAuthenticated } = useAuthGuard();
  const searchParams = useSearchParams();
  const queryClient = useQueryClient();

  const initialQuery = searchParams.get('q')?.trim() ?? '';
  const initialTicker = searchParams.get('ticker')?.trim().toUpperCase() ?? '';
  const initialSources = useMemo(() => parseSourceParams(searchParams.get('sources')), [searchParams]);

  const [queryInput, setQueryInput] = useState(initialQuery);
  const [query, setQuery] = useState(initialQuery);
  const [tickerInput, setTickerInput] = useState(initialTicker);
  const [ticker, setTicker] = useState(initialTicker);
  const [sources, setSources] = useState<SearchSource[]>(initialSources);
  const [results, setResults] = useState<SearchResult[]>([]);
  const [answer, setAnswer] = useState<SearchAnswerResponse | null>(null);
  const [loading, setLoading] = useState(false);
  const [answerLoading, startAnswerTransition] = useTransition();
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    setQueryInput(initialQuery);
    setQuery(initialQuery);
    setTickerInput(initialTicker);
    setTicker(initialTicker);
    setSources(initialSources);
  }, [initialQuery, initialTicker, initialSources]);

  useEffect(() => {
    if (!query.trim() || !isAuthenticated) {
      setResults([]);
      return;
    }

    let cancelled = false;
    setLoading(true);
    setError(null);

    queryClient.fetchQuery(searchQueryOptions({
      query,
      ticker: ticker || undefined,
      sources,
      limit: 10
    })).then((response) => {
      if (!cancelled) {
        setResults(response.results);
      }
    }).catch((err) => {
      if (!cancelled) {
        setError(err instanceof Error ? err.message : 'Unable to search indexed sources');
        setResults([]);
      }
    }).finally(() => {
      if (!cancelled) {
        setLoading(false);
      }
    });

    return () => {
      cancelled = true;
    };
  }, [isAuthenticated, query, queryClient, sources, ticker]);

  if (isPending || !isAuthenticated) {
    return <div className="flex min-h-screen items-center justify-center text-sm text-[color:var(--terminal-muted)]">Loading search desk...</div>;
  }

  const runAnswer = () => {
    if (!query.trim()) {
      return;
    }

    if (ticker.trim()) {
      void ensureTickerAutomation({
        ticker,
        source: 'search'
      });
    }

    startAnswerTransition(() => {
      setError(null);
      getSearchAnswer({
        query,
        ticker: ticker || undefined,
        sources,
        limit: 10
      }).then((response) => {
        setAnswer(response);
      }).catch((err) => {
        setError(err instanceof Error ? err.message : 'Unable to generate cited answer');
        setAnswer(null);
      });
    });
  };

  return (
    <AppShell
      title="Search"
      subtitle="Hybrid semantic + lexical retrieval across primary filings, filing briefs, and private research notes."
      activeTicker={ticker || null}
    >
      <div className="grid grid-cols-1 gap-6 xl:grid-cols-[1.2fr_0.8fr]">
        <Panel title="Search Query" subtitle="Run semantic search with an optional ticker filter and source selection.">
          <form
            className="space-y-3"
            onSubmit={(event) => {
              event.preventDefault();
              const normalizedTicker = tickerInput.trim().toUpperCase();
              if (normalizedTicker) {
                void ensureTickerAutomation({
                  ticker: normalizedTicker,
                  source: 'search'
                });
              }
              setQuery(queryInput.trim());
              setTicker(normalizedTicker);
              setAnswer(null);
            }}
          >
            <Input
              value={queryInput}
              onChange={(event) => setQueryInput(event.target.value)}
              placeholder="Ask about margin drivers, segment commentary, risks, or your notes..."
            />
            <div className="flex flex-col gap-3 sm:flex-row">
              <Input
                value={tickerInput}
                onChange={(event) => setTickerInput(event.target.value.toUpperCase())}
                placeholder="Ticker filter (optional)"
                className="sm:max-w-xs"
              />
              <div className="flex flex-wrap gap-2">
                {SOURCE_OPTIONS.map((option) => {
                  const selected = sources.includes(option.value);
                  return (
                    <Button
                      key={option.value}
                      type="button"
                      variant={selected ? 'primary' : 'ghost'}
                      className="px-2 py-1 text-xs"
                      onClick={() => {
                        setSources((current) => {
                          if (selected && current.length > 1) {
                            return current.filter((entry) => entry !== option.value);
                          }

                          return selected ? current : [...current, option.value];
                        });
                      }}
                    >
                      {option.label}
                    </Button>
                  );
                })}
              </div>
            </div>
            <div className="flex flex-wrap gap-2">
              <Button type="submit" className="w-full sm:w-auto">
                <SearchIcon className="size-4" />
                Search
              </Button>
              <Button type="button" variant="secondary" className="w-full sm:w-auto" onClick={runAnswer} disabled={!query.trim() || answerLoading}>
                <BrainCircuit className="size-4" />
                {answerLoading ? 'Answering...' : 'Cited answer'}
              </Button>
            </div>
          </form>
        </Panel>

        <Panel title="Cited Answer" subtitle="Single-turn answer grounded only in retrieved evidence." variant="surface">
          {answer ? (
            <div className="space-y-3">
              <p className="whitespace-pre-wrap text-sm leading-7 text-[color:var(--terminal-bright)]">{answer.answer}</p>
              {answer.citations.length > 0 ? (
                <div className="space-y-2">
                  {answer.citations.map((citation) => (
                    <Link
                      key={`${citation.chunkId}-${citation.index}`}
                      href={citation.href}
                      className="flex items-center justify-between rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] transition hover:border-[color:var(--line-strong)]"
                    >
                      <span>[{citation.index}] {citation.label}</span>
                      <ExternalLink className="size-3.5 text-[color:var(--accent)]" />
                    </Link>
                  ))}
                </div>
              ) : (
                <p className="text-sm text-[color:var(--terminal-muted)]">No supporting citations were strong enough to answer.</p>
              )}
            </div>
          ) : (
            <p className="text-sm text-[color:var(--terminal-muted)]">Ask a question to synthesize the top retrieved passages into a cited answer.</p>
          )}
        </Panel>
      </div>

      <Panel
        title="Semantic Search"
        subtitle={query ? `${results.length} results${ticker ? ` for ${ticker}` : ''}.` : 'Search results will appear here.'}
        variant="surface"
      >
        {error ? <p className="text-sm text-[#ffb5b5]">{error}</p> : null}
        {loading ? (
          <p className="text-sm text-[color:var(--terminal-muted)]">Searching indexed sources...</p>
        ) : !query ? (
          <p className="text-sm text-[color:var(--terminal-muted)]">Enter a question or topic to search the local RAG index.</p>
        ) : results.length === 0 ? (
          <p className="text-sm text-[color:var(--terminal-muted)]">No indexed evidence matched this query.</p>
        ) : (
          <div className="space-y-3">
            {results.map((result) => (
              <article key={result.chunkId} className="rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4">
                <div className="flex flex-wrap items-start justify-between gap-3">
                  <div>
                    <p className="text-xs uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">
                      {result.source} {result.ticker ? `· ${result.ticker}` : ''} {result.filingDate ? `· ${result.filingDate}` : ''}
                    </p>
                    <h3 className="mt-1 text-sm font-semibold text-[color:var(--terminal-bright)]">{result.title ?? result.citationLabel}</h3>
                    <p className="mt-1 text-xs text-[color:var(--accent)]">{result.citationLabel}</p>
                  </div>
                  <Link
                    href={result.href}
                    className="inline-flex items-center gap-1 rounded-md border border-[color:var(--line-weak)] px-2 py-1 text-xs text-[color:var(--accent)] transition hover:border-[color:var(--line-strong)] hover:text-[color:var(--accent-strong)]"
                  >
                    Open source
                    <ExternalLink className="size-3" />
                  </Link>
                </div>
                {result.headingPath ? (
                  <p className="mt-3 text-xs uppercase tracking-[0.12em] text-[color:var(--terminal-muted)]">{result.headingPath}</p>
                ) : null}
                <p className="mt-3 text-sm leading-6 text-[color:var(--terminal-bright)]">{result.snippet}</p>
              </article>
            ))}
          </div>
        )}
      </Panel>
    </AppShell>
  );
}
