"use client";

import { useEffect, useRef, useState } from "react";
import type { PersonaInfo } from "./PersonaPicker";
import type { Message } from "./ChatPane";

interface ColumnState {
  messages: Message[];
  sessionId: string | null;
  streaming: boolean;
}

interface Props {
  persona: PersonaInfo;
  apiBase: string;
}

type ProviderKey = "anthropic" | "lmstudio";

const FALLBACK_LABELS: Record<ProviderKey, string> = {
  anthropic: "Frontier",
  lmstudio: "Local",
};

function useColumnState(): ColumnState {
  return { messages: [], sessionId: null, streaming: false };
}

export default function ComparePane({ persona, apiBase }: Props) {
  const [anthropicCol, setAnthropicCol] = useState<ColumnState>(useColumnState());
  const [lmstudioCol, setLmstudioCol] = useState<ColumnState>(useColumnState());
  const [input, setInput] = useState("");
  const [labels, setLabels] = useState<Record<ProviderKey, string>>({
    anthropic: FALLBACK_LABELS.anthropic,
    lmstudio: FALLBACK_LABELS.lmstudio,
  });

  const anthropicBottomRef = useRef<HTMLDivElement>(null);
  const lmstudioBottomRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    fetch(`${apiBase}/api/providers`)
      .then((r) => r.json())
      .then((data) => {
        setLabels({
          anthropic: data.frontier_model ?? FALLBACK_LABELS.anthropic,
          lmstudio: data.local_model ?? FALLBACK_LABELS.lmstudio,
        });
      })
      .catch(() => {});
  }, [apiBase]);

  useEffect(() => {
    anthropicBottomRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [anthropicCol.messages]);

  useEffect(() => {
    lmstudioBottomRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [lmstudioCol.messages]);

  const streamToColumn = async (
    provider: ProviderKey,
    text: string,
    sessionId: string | null,
    setState: React.Dispatch<React.SetStateAction<ColumnState>>,
  ) => {
    try {
      const resp = await fetch(`${apiBase}/api/chat/${persona.slug}`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ message: text, session_id: sessionId, provider }),
      });

      if (!resp.ok || !resp.body) {
        throw new Error(`HTTP ${resp.status}`);
      }

      const reader = resp.body.getReader();
      const decoder = new TextDecoder();
      let buffer = "";

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });

        const lines = buffer.split("\n");
        buffer = lines.pop() ?? "";

        for (const line of lines) {
          if (!line.startsWith("data: ")) continue;
          const payload = JSON.parse(line.slice(6));
          if (payload.type === "session") {
            setState((prev) => ({ ...prev, sessionId: payload.session_id }));
          } else if (payload.type === "text") {
            setState((prev) => {
              const updated = [...prev.messages];
              const last = updated[updated.length - 1];
              if (last.role === "assistant") {
                updated[updated.length - 1] = {
                  ...last,
                  content: last.content + payload.text,
                };
              }
              return { ...prev, messages: updated };
            });
          } else if (payload.type === "done") {
            setState((prev) => {
              const updated = [...prev.messages];
              const last = updated[updated.length - 1];
              if (last.role === "assistant") {
                updated[updated.length - 1] = { ...last, streaming: false };
              }
              return { ...prev, messages: updated, streaming: false };
            });
          }
        }
      }
    } catch (err) {
      setState((prev) => {
        const updated = [...prev.messages];
        const last = updated[updated.length - 1];
        if (last.role === "assistant") {
          updated[updated.length - 1] = {
            ...last,
            content: `[Error: ${String(err)}]`,
            streaming: false,
          };
        }
        return { ...prev, messages: updated, streaming: false };
      });
    }
  };

  const sendToBoth = async () => {
    const text = input.trim();
    if (!text) return;
    const isStreaming = anthropicCol.streaming || lmstudioCol.streaming;
    if (isStreaming) return;
    setInput("");

    const userMsg: Message = { role: "user", content: text };
    const assistantMsg: Message = { role: "assistant", content: "", streaming: true };

    setAnthropicCol((prev) => ({
      ...prev,
      messages: [...prev.messages, userMsg, assistantMsg],
      streaming: true,
    }));
    setLmstudioCol((prev) => ({
      ...prev,
      messages: [...prev.messages, userMsg, assistantMsg],
      streaming: true,
    }));

    void streamToColumn("anthropic", text, anthropicCol.sessionId, setAnthropicCol);
    void streamToColumn("lmstudio", text, lmstudioCol.sessionId, setLmstudioCol);
  };

  const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      sendToBoth();
    }
  };

  const anyStreaming = anthropicCol.streaming || lmstudioCol.streaming;

  const renderColumn = (key: ProviderKey, col: ColumnState, bottomRef: React.RefObject<HTMLDivElement | null>) => (
    <div key={key} style={styles.column}>
      <div style={styles.columnHeader}>
        <span style={styles.columnLabel}>
          {key === "anthropic" ? "Frontier" : "Local"}
        </span>
        <span style={styles.columnModel}>{labels[key]}</span>
      </div>
      <div style={styles.messages}>
        {col.messages.length === 0 && (
          <div style={styles.empty}>
            Send a message to see the {key === "anthropic" ? "frontier" : "local"} response.
          </div>
        )}
        {col.messages.map((msg, i) => (
          <div
            key={i}
            style={{
              ...styles.bubble,
              ...(msg.role === "user" ? styles.userBubble : styles.assistantBubble),
            }}
          >
            <span style={styles.role}>
              {msg.role === "user" ? "You" : labels[key]}
            </span>
            <p style={styles.text}>
              {msg.content}
              {msg.streaming && <span style={styles.cursor}>▌</span>}
            </p>
          </div>
        ))}
        <div ref={bottomRef} />
      </div>
    </div>
  );

  return (
    <div style={styles.container}>
      <div style={styles.columns}>
        {renderColumn("anthropic", anthropicCol, anthropicBottomRef)}
        {renderColumn("lmstudio", lmstudioCol, lmstudioBottomRef)}
      </div>
      <div style={styles.inputRow}>
        <textarea
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={onKeyDown}
          placeholder={`Ask ${persona.display_name}…`}
          disabled={anyStreaming}
          rows={2}
          style={styles.textarea}
        />
        <button
          onClick={sendToBoth}
          disabled={anyStreaming || !input.trim()}
          style={{
            ...styles.sendBtn,
            ...(anyStreaming || !input.trim() ? styles.sendBtnDisabled : {}),
          }}
        >
          Send to both
        </button>
      </div>
    </div>
  );
}

const styles: Record<string, React.CSSProperties> = {
  container: {
    display: "flex",
    flexDirection: "column",
    height: "100%",
    background: "var(--bg)",
  },
  columns: {
    flex: 1,
    display: "flex",
    gap: "1px",
    borderBottom: "1px solid var(--border)",
    overflow: "hidden",
  },
  column: {
    flex: 1,
    display: "flex",
    flexDirection: "column",
    overflow: "hidden",
    background: "var(--surface)",
  },
  columnHeader: {
    padding: "14px 16px",
    borderBottom: "1px solid var(--border)",
    display: "flex",
    alignItems: "baseline",
    gap: "10px",
    background: "var(--surface)",
    flexShrink: 0,
  },
  columnLabel: {
    fontWeight: 700,
    color: "var(--accent)",
    fontSize: "14px",
  },
  columnModel: {
    color: "var(--text-muted)",
    fontSize: "11px",
    fontFamily: "monospace",
  },
  messages: {
    flex: 1,
    overflowY: "auto",
    padding: "16px",
    display: "flex",
    flexDirection: "column",
    gap: "12px",
  },
  empty: {
    color: "var(--text-muted)",
    fontStyle: "italic",
    textAlign: "center",
    marginTop: "40px",
    fontSize: "13px",
  },
  bubble: {
    display: "flex",
    flexDirection: "column",
    gap: "4px",
  },
  userBubble: {
    alignSelf: "flex-end",
    alignItems: "flex-end",
  },
  assistantBubble: {
    alignSelf: "flex-start",
    alignItems: "flex-start",
  },
  role: {
    fontSize: "10px",
    color: "var(--text-muted)",
    fontWeight: 600,
    textTransform: "uppercase",
    letterSpacing: "0.05em",
  },
  text: {
    background: "var(--bg)",
    padding: "8px 12px",
    borderRadius: "var(--radius)",
    lineHeight: 1.65,
    fontSize: "13px",
    border: "1px solid var(--border)",
    whiteSpace: "pre-wrap",
  },
  cursor: {
    animation: "blink 1s step-end infinite",
    color: "var(--accent)",
  },
  inputRow: {
    display: "flex",
    gap: "8px",
    padding: "14px 16px",
    background: "var(--surface)",
    flexShrink: 0,
  },
  textarea: {
    flex: 1,
    padding: "10px 14px",
    borderRadius: "var(--radius)",
    border: "1px solid var(--border)",
    background: "var(--bg)",
    color: "var(--text)",
    resize: "none",
    outline: "none",
  },
  sendBtn: {
    padding: "0 20px",
    background: "var(--accent)",
    color: "#000",
    borderRadius: "var(--radius)",
    fontWeight: 600,
    fontSize: "13px",
    transition: "opacity 0.15s",
  },
  sendBtnDisabled: {
    opacity: 0.4,
    cursor: "default",
  },
};
