import { useState } from "react";
import { invoke, Channel } from "@tauri-apps/api/core";
import { addToLore } from "../lib/lore";
import { useToast } from "./Toast";
import { addGeneration, type Generation } from "../lib/generations";
import { usePrefillEffect } from "../lib/usePrefill";
import { usePersistentState } from "../lib/usePersistentState";

interface Props {
  prefill?: Generation | null;
  onPrefillConsumed?: () => void;
}

export function SessionLogger({ prefill, onPrefillConsumed }: Props = {}) {
  const [notes, setNotes] = useState("");
  const [summary, setSummary] = usePersistentState<string>("session.summary", "");
  const [loading, setLoading] = useState(false);
  // ponytail: streaming state — tokens arrive via the Channel and append to
  // the summary live with a gold cursor. `gotFirstToken` flips the thinking
  // dots to streaming text.
  const [gotFirstToken, setGotFirstToken] = useState(false);
  const [entries, setEntries] = usePersistentState<{ text: string; time: string }[]>("session.entries", []);
  const { addToast } = useToast();

  usePrefillEffect(prefill ?? null, "session", () => onPrefillConsumed?.(), (g) => {
    setSummary(g.data);
    addToast(`Loaded "${g.title}" from history`, "info");
  });

  function addEntry() {
    if (!notes.trim()) return;
    setEntries((prev) => [
      { text: notes.trim(), time: new Date().toLocaleTimeString() },
      ...prev,
    ]);
    setNotes("");
  }

  // ponytail: export the session as a Markdown file the DM can share or
  // paste into Discord. Reverses the entry list so it reads chronologically.
  function exportMarkdown() {
    if (entries.length === 0) return;
    const lines = [...entries].reverse().map((e) => `- [${e.time}] ${e.text}`);
    const md = `# Session ${new Date().toLocaleDateString()}\n\n## Notes\n\n${lines.join("\\n")}\n\n${summary ? `## AI Summary\n\n${summary}` : ""}`;
    const blob = new Blob([md], { type: "text/markdown" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `session-${new Date().toISOString().slice(0, 10)}.md`;
    a.click();
    URL.revokeObjectURL(url);
    addToast("Exported session to Markdown", "success");
  }

  function removeEntry(i: number) {
    setEntries((prev) => prev.filter((_, j) => j !== i));
  }

  async function summarize() {
    if (entries.length === 0) return;
    setLoading(true);
    setSummary("");
    setGotFirstToken(false);
    const sessionText = entries.map((e) => `[${e.time}] ${e.text}`).join("\n");
    // ponytail: stream tokens via the existing generate_stream Channel so the
    // DM sees the summary appear word-by-word instead of staring at a button.
    const channel = new Channel<{ type: string; data: string }>();
    let streamed = "";
    channel.onmessage = (event) => {
      if (event.type === "token") {
        setGotFirstToken(true);
        streamed = streamed + event.data;
        setSummary(streamed);
      } else if (event.type === "done") {
        setGotFirstToken(true);
        streamed = event.data;
        setSummary(streamed);
      } else if (event.type === "error") {
        addToast(`Summary failed: ${event.data}`, "error");
      }
    };
    try {
      await invoke("generate_stream", {
        req: {
          prompt: `Summarize the following D&D session notes and suggest 2-3 hooks for the next session:\n\n${sessionText}`,
          system: "You are a helpful D&D session summarizer. Be concise and creative.",
          temperature: 0.7,
          max_tokens: 512,
        },
        channel,
      });
      addToast("Session summary generated", "success");
      const result = streamed;
      const title = `Session ${new Date().toLocaleDateString()}`;
      void addGeneration({ kind: "session", title, data: result, source: `${entries.length} notes` });
      void addToLore("Session Summary", `Session summary:\n${result}\n\nNotes:\n${sessionText}`);
    } catch (e) {
      addToast(`Summary failed: ${e}`, "error");
    }
    setLoading(false);
  }

  return (
    <div className="flex gap-3 h-full">
      {/* Notes column */}
      <div className="flex flex-col gap-2 flex-1">
        <textarea
          className="flex-1 rounded-lg bg-[var(--color-bg-surface)] border border-[var(--color-border-glass)] p-3 text-[var(--color-text-primary)] placeholder-[var(--color-text-dim)] focus:outline-none focus:border-[var(--color-gold-bright)] text-sm resize-none"
          value={notes}
          onChange={(e) => setNotes(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter" && !e.shiftKey) {
              e.preventDefault();
              addEntry();
            }
          }}
          placeholder="Type a session note, press Enter to add…"
        />
        <div className="flex gap-2">
          <button
            onClick={addEntry}
            className="rounded-lg bg-[var(--color-bg-surface)] border border-[var(--color-border-glass)] text-[var(--color-text-secondary)] px-3 py-1.5 text-xs hover:border-[var(--color-gold-bright)] hover:text-[var(--color-gold-bright)] transition-colors cursor-pointer"
          >
            Add Note
          </button>
          <button
            onClick={summarize}
            disabled={loading || entries.length === 0}
            className="rounded-lg bg-[var(--color-gold-bright)] text-[var(--color-bg-deep)] px-3 py-1.5 text-xs font-semibold hover:bg-[var(--color-gold-muted)] transition-colors cursor-pointer disabled:opacity-50"
          >
            {loading ? "Summarizing…" : "✨ AI Summary"}
          </button>
          <button
            onClick={exportMarkdown}
            disabled={entries.length === 0}
            className="rounded-lg bg-[var(--color-bg-surface)] border border-[var(--color-border-glass)] text-[var(--color-text-dim)] px-3 py-1.5 text-xs hover:text-[var(--color-gold-bright)] hover:border-[var(--color-gold-bright)] transition-colors cursor-pointer disabled:opacity-50"
            title="Export notes + summary to a Markdown file"
          >
            ⬇ Export
          </button>
        </div>
        <div className="flex-1 overflow-y-auto">
          {entries.map((e, i) => (
            <div key={i} className="flex gap-2 py-1 border-b border-[var(--color-border-subtle)] group">
              <span className="text-[var(--color-text-dim)] text-xs font-mono shrink-0">
                {e.time}
              </span>
              <span className="text-[var(--color-text-primary)] text-xs flex-1">{e.text}</span>
              <button
                onClick={() => removeEntry(i)}
                className="text-[var(--color-text-dim)] hover:text-[var(--color-danger)] text-[10px] cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity"
                title="Delete entry"
              >
                ×
              </button>
            </div>
          ))}
        </div>
      </div>

      {/* AI Summary column */}
      <div className="flex-1 flex flex-col">
        <h3 className="text-xs font-medium text-[var(--color-text-secondary)] mb-2">AI Summary</h3>
        <div className="flex-1 rounded-lg bg-[var(--color-bg-surface)] border border-[var(--color-border-glass)] p-3 text-[var(--color-text-primary)] text-sm overflow-y-auto">
          {loading && !gotFirstToken ? (
            <span className="text-[var(--color-gold-bright)] tracking-widest">
              <span className="thinking-dot">•</span>
              <span className="thinking-dot">•</span>
              <span className="thinking-dot">•</span>
            </span>
          ) : summary ? (
            <span>{summary}{loading && <span className="text-[var(--color-gold-bright)]">▍</span>}</span>
          ) : (
            <span className="text-[var(--color-text-dim)] italic">
              Add session notes and click "AI Summary" to generate a recap and next-session hooks.
            </span>
          )}
        </div>
      </div>
    </div>
  );
}