/**
 * ChatPage — multi-turn chat with streamed encyclopedic responses and 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. Conversations are threaded
 * via conversation_id backed by Redis history on the server.
 */

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

interface Message {
  role: "user" | "assistant";
  text: string;
  sources: ChatSource[];
  done: boolean;
  error?: string;
}

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

  const [messages, setMessages] = useState<Message[]>([]);
  const [input, setInput] = useState("");
  const [streaming, setStreaming] = useState(false);
  const [conversationId, setConversationId] = useState<string | undefined>(
    undefined,
  );

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

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

  // Scroll to bottom when messages update
  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  const sendMessage = useCallback(
    (text: string) => {
      const q = text.trim();
      if (!q || streaming) return;

      abortRef.current?.abort();

      // Generate conversation_id on first message
      const cid = conversationId ?? generateUUID();
      if (!conversationId) setConversationId(cid);

      const userMsg: Message = {
        role: "user",
        text: q,
        sources: [],
        done: true,
      };
      const assistantMsg: Message = {
        role: "assistant",
        text: "",
        sources: [],
        done: false,
      };
      const newMessages = [...messages, userMsg, assistantMsg];
      setMessages(newMessages);
      setInput("");
      setStreaming(true);

      const assistantIndex = newMessages.length - 1;

      abortRef.current = streamChat(
        q,
        {
          onSources: (sources) => {
            setMessages((prev) =>
              prev.map((m, i) =>
                i === assistantIndex ? { ...m, sources } : m,
              ),
            );
          },
          onToken: (token) => {
            setMessages((prev) =>
              prev.map((m, i) =>
                i === assistantIndex ? { ...m, text: m.text + token } : m,
              ),
            );
          },
          onDone: (meta) => {
            setConversationId(meta.conversation_id);
            setMessages((prev) =>
              prev.map((m, i) =>
                i === assistantIndex ? { ...m, done: true } : m,
              ),
            );
            setStreaming(false);
          },
          onError: (msg) => {
            setMessages((prev) =>
              prev.map((m, i) =>
                i === assistantIndex ? { ...m, done: true, error: msg } : m,
              ),
            );
            setStreaming(false);
          },
        },
        undefined, // no creator scope on the main chat page
        cid,
      );
    },
    [messages, streaming, conversationId],
  );

  const handleSubmit = useCallback(
    (e: React.FormEvent) => {
      e.preventDefault();
      sendMessage(input);
    },
    [input, sendMessage],
  );

  const handleNewConversation = useCallback(() => {
    abortRef.current?.abort();
    setMessages([]);
    setInput("");
    setStreaming(false);
    setConversationId(undefined);
    inputRef.current?.focus();
  }, []);

  const hasMessages = messages.length > 0;

  return (
    <div className={styles.container}>
      <div className={styles.headerRow}>
        <h1 className={styles.title}>Ask Chrysopedia</h1>
        {hasMessages && (
          <button
            className={styles.newConversationBtn}
            onClick={handleNewConversation}
            title="Start a new conversation"
          >
            + New conversation
          </button>
        )}
      </div>

      {!hasMessages && !streaming && (
        <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>
      )}

      {hasMessages && (
        <div className={styles.messagesArea}>
          {messages.map((msg, i) => {
            if (msg.role === "user") {
              return (
                <div key={i} className={styles.userMsg}>
                  {msg.text}
                </div>
              );
            }

            // Assistant message
            return (
              <div key={i} className={styles.assistantMsg}>
                {msg.error ? (
                  <div className={styles.error}>{msg.error}</div>
                ) : (
                  <>
                    <div className={styles.responseText}>
                      {parseChatCitations(msg.text, msg.sources, styles)}
                      {!msg.done && <span className={styles.cursor} />}
                    </div>
                    {msg.done && msg.sources.length > 0 && (
                      <div className={styles.sourcesSection}>
                        <h3 className={styles.sourcesTitle}>Sources</h3>
                        <ol className={styles.sourceList}>
                          {msg.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.start_time != null && src.source_video_id && (
                                    <Link
                                      to={`/watch/${src.source_video_id}?t=${Math.floor(src.start_time)}`}
                                      className={styles.timestampBadge}
                                      title="Jump to video timestamp"
                                    >
                                      ▶ {formatTime(src.start_time)}
                                      {src.end_time != null && `–${formatTime(src.end_time)}`}
                                    </Link>
                                  )}
                                  {src.creator_name && (
                                    <span className={styles.sourceMeta}>
                                      {" "}
                                      · {src.creator_name}
                                    </span>
                                  )}
                                  {src.video_filename && (
                                    <span className={styles.videoMeta}>
                                      {" "}
                                      · {src.video_filename}
                                    </span>
                                  )}
                                </div>
                              </li>
                            );
                          })}
                        </ol>
                      </div>
                    )}
                  </>
                )}
              </div>
            );
          })}

          {/* Typing indicator — before first token arrives */}
          {streaming &&
            messages.length > 0 &&
            messages[messages.length - 1]?.role === "assistant" &&
            messages[messages.length - 1]?.text === "" &&
            !messages[messages.length - 1]?.error && (
              <div className={styles.loading}>
                <div className={styles.spinner} />
                Thinking…
              </div>
            )}

          <div ref={messagesEndRef} />
        </div>
      )}

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