/**
 * ChatPage — ask a question, receive a streamed encyclopedic response with citations.
 *
 * Uses SSE streaming via api/chat.ts to display tokens in real-time.
 * Citation markers [N] in the streamed text become superscript links to
 * the source list rendered below the response.
 */

import React, { useState, useRef, useCallback, useEffect } from "react";
import { Link } from "react-router-dom";
import { streamChat, type ChatSource } from "../api/chat";
import { useDocumentTitle } from "../hooks/useDocumentTitle";
import styles from "./ChatPage.module.css";

// Matches [1], [2,3], [1,2,3] etc. — same regex as utils/citations.tsx
const CITATION_RE = /\[(\d+(?:,\s*\d+)*)\]/g;

/**
 * Parse text containing [N] markers into React nodes with citation links.
 * Links scroll to the source list item and reference ChatSource metadata.
 */
function parseChatCitations(
  text: string,
  sources: ChatSource[],
): React.ReactNode[] {
  const nodes: React.ReactNode[] = [];
  let lastIndex = 0;

  for (const match of text.matchAll(CITATION_RE)) {
    const matchStart = match.index ?? 0;
    if (matchStart > lastIndex) {
      nodes.push(text.slice(lastIndex, matchStart));
    }

    const rawGroup = match[1];
    if (!rawGroup) continue;
    const indices = rawGroup.split(",").map((s) => parseInt(s.trim(), 10));
    const links: React.ReactNode[] = [];

    for (let i = 0; i < indices.length; i++) {
      const idx = indices[i]!;
      const source = sources[idx - 1]; // 1-based
      if (source) {
        if (i > 0) links.push(", ");
        const href = source.section_anchor
          ? `/techniques/${source.slug}#${source.section_anchor}`
          : `/techniques/${source.slug}`;
        links.push(
          <Link
            key={`${matchStart}-${idx}`}
            to={href}
            className={styles.citationLink}
            title={`${source.title}${source.section_heading ? ` — ${source.section_heading}` : ""}`}
          >
            {idx}
          </Link>,
        );
      } else {
        if (i > 0) links.push(", ");
        links.push(String(idx));
      }
    }

    nodes.push(
      <sup key={`cite-${matchStart}`} className={styles.citationGroup}>
        [{links}]
      </sup>,
    );

    lastIndex = matchStart + match[0].length;
  }

  if (lastIndex < text.length) {
    nodes.push(text.slice(lastIndex));
  }

  return nodes.length > 0 ? nodes : [text];
}

export default function ChatPage() {
  useDocumentTitle("Chat — Chrysopedia");

  const [query, setQuery] = useState("");
  const [sources, setSources] = useState<ChatSource[]>([]);
  const [responseText, setResponseText] = useState("");
  const [streaming, setStreaming] = useState(false);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [done, setDone] = useState(false);

  const abortRef = useRef<AbortController | null>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      abortRef.current?.abort();
    };
  }, []);

  const handleSubmit = useCallback(
    (e: React.FormEvent) => {
      e.preventDefault();
      const q = query.trim();
      if (!q || streaming) return;

      // Reset state
      abortRef.current?.abort();
      setSources([]);
      setResponseText("");
      setError(null);
      setDone(false);
      setLoading(true);
      setStreaming(true);

      abortRef.current = streamChat(q, {
        onSources: (s) => {
          setSources(s);
          setLoading(false);
        },
        onToken: (text) => {
          setResponseText((prev) => prev + text);
        },
        onDone: () => {
          setStreaming(false);
          setDone(true);
        },
        onError: (msg) => {
          setError(msg);
          setStreaming(false);
          setLoading(false);
        },
      });
    },
    [query, streaming],
  );

  const hasResponse = responseText.length > 0 || sources.length > 0;

  return (
    <div className={styles.container}>
      <h1 className={styles.title}>Ask Chrysopedia</h1>

      <form onSubmit={handleSubmit} className={styles.inputRow}>
        <input
          ref={inputRef}
          type="text"
          className={styles.input}
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Ask about music production techniques…"
          disabled={streaming}
          autoFocus
        />
        <button
          type="submit"
          className={styles.submitBtn}
          disabled={!query.trim() || streaming}
        >
          {streaming ? "Streaming…" : "Ask"}
        </button>
      </form>

      {error && <div className={styles.error}>{error}</div>}

      {loading && (
        <div className={styles.loading}>
          <div className={styles.spinner} />
          Searching for sources…
        </div>
      )}

      {hasResponse && (
        <div className={styles.responseArea}>
          <div className={styles.responseText}>
            {parseChatCitations(responseText, sources)}
            {streaming && <span className={styles.cursor} />}
          </div>

          {sources.length > 0 && (done || !streaming) && (
            <div className={styles.sourcesSection}>
              <h2 className={styles.sourcesTitle}>Sources</h2>
              <ol className={styles.sourceList}>
                {sources.map((src) => {
                  const href = src.section_anchor
                    ? `/techniques/${src.slug}#${src.section_anchor}`
                    : `/techniques/${src.slug}`;
                  return (
                    <li key={src.number} className={styles.sourceItem}>
                      <span className={styles.sourceNumber}>{src.number}</span>
                      <div>
                        <Link to={href} className={styles.sourceLink}>
                          {src.title}
                          {src.section_heading ? ` — ${src.section_heading}` : ""}
                        </Link>
                        {src.creator_name && (
                          <span className={styles.sourceMeta}>
                            {" "}· {src.creator_name}
                          </span>
                        )}
                      </div>
                    </li>
                  );
                })}
              </ol>
            </div>
          )}
        </div>
      )}

      {!hasResponse && !loading && !error && (
        <div className={styles.placeholder}>
          <span className={styles.placeholderIcon}>💬</span>
          <p>Ask any question about music production techniques.</p>
          <p>Responses include citations linking to source pages and videos.</p>
        </div>
      )}
    </div>
  );
}
