import React, { useCallback, useEffect, useRef, useState } from 'react';
import { DraggableWindow } from './DraggableWindow';
import {
  agentAsk,
  agentNewSession,
  agentSessionHistory,
  type AgentHistoryMessage,
} from '../../api/endpoints';

interface Props {
  id: string;
  zIndex: number;
}

interface ChatMsg {
  role: 'user' | 'assistant' | 'error';
  text: string;
}

const SESSION_KEY = 'overlord_agent_session_id';

/** UUID is preferred but crypto.randomUUID is only available in secure contexts. */
function newUuid(): string {
  if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
    return crypto.randomUUID();
  }
  // RFC4122-ish fallback
  const r = (n: number) => Math.floor(Math.random() * n);
  return `${r(0x100000000).toString(16).padStart(8, '0')}-${r(0x10000).toString(16).padStart(4, '0')}-4${r(0x1000).toString(16).padStart(3, '0')}-${(8 + r(4)).toString(16)}${r(0x1000).toString(16).padStart(3, '0')}-${r(0x1000000000000).toString(16).padStart(12, '0')}`;
}

function loadSessionId(): string {
  try {
    const stored = localStorage.getItem(SESSION_KEY);
    if (stored) return stored;
  } catch { /* ignore */ }
  const fresh = newUuid();
  try { localStorage.setItem(SESSION_KEY, fresh); } catch { /* ignore */ }
  return fresh;
}

export const AgentWindow: React.FC<Props> = ({ id, zIndex }) => {
  const [sessionId, setSessionId] = useState<string>(() => loadSessionId());
  const [messages, setMessages] = useState<ChatMsg[]>([]);
  const [input, setInput] = useState('');
  const [loading, setLoading] = useState(false);
  const [hydrating, setHydrating] = useState(true);
  const scrollRef = useRef<HTMLDivElement>(null);

  // Rehydrate from server-side session JSONL on mount / session change.
  useEffect(() => {
    let cancelled = false;
    setHydrating(true);
    agentSessionHistory(sessionId)
      .then(res => {
        if (cancelled) return;
        const msgs: ChatMsg[] = (res.messages ?? []).map((m: AgentHistoryMessage) => ({
          role: m.role,
          text: m.text,
        }));
        setMessages(msgs);
      })
      .catch(() => {
        if (!cancelled) setMessages([]);
      })
      .finally(() => {
        if (!cancelled) setHydrating(false);
      });
    return () => { cancelled = true; };
  }, [sessionId]);

  // Auto-scroll to bottom on new messages.
  useEffect(() => {
    const el = scrollRef.current;
    if (el) el.scrollTop = el.scrollHeight;
  }, [messages.length, loading]);

  const send = useCallback(async () => {
    const text = input.trim();
    if (!text || loading) return;
    setInput('');
    setMessages(prev => [...prev, { role: 'user', text }]);
    setLoading(true);
    try {
      const res = await agentAsk(text, sessionId);
      setMessages(prev => [
        ...prev,
        { role: res.is_error ? 'error' : 'assistant', text: res.result || '(no response)' },
      ]);
    } catch (err) {
      setMessages(prev => [
        ...prev,
        { role: 'error', text: `Request failed: ${String(err)}` },
      ]);
    } finally {
      setLoading(false);
    }
  }, [input, loading, sessionId]);

  const newChat = useCallback(async () => {
    if (loading) return;
    let fresh = '';
    try {
      const res = await agentNewSession();
      fresh = res.session_id;
    } catch {
      fresh = newUuid();
    }
    try { localStorage.setItem(SESSION_KEY, fresh); } catch { /* ignore */ }
    setSessionId(fresh);
    setMessages([]);
    setInput('');
  }, [loading]);

  const onKeyDown = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      void send();
    }
  }, [send]);

  return (
    <DraggableWindow id={id} title="🤖 Overlord Assistant" zIndex={zIndex} width={520} height={620}>
      <div className="ml-agent">
        <div className="ml-agent-toolbar">
          <button className="ml-agent-btn" onClick={newChat} disabled={loading}>+ New Chat</button>
          <span className="ml-agent-session" title={sessionId}>{sessionId.slice(0, 8)}…</span>
        </div>

        <div className="ml-agent-messages" ref={scrollRef}>
          {hydrating && messages.length === 0 && (
            <div className="ml-agent-empty">Loading conversation…</div>
          )}
          {!hydrating && messages.length === 0 && (
            <div className="ml-agent-empty">
              Ask anything about the live game state — players, kills, inventory,
              suitbuilder, recent rares, etc.
            </div>
          )}
          {messages.map((m, i) => (
            <div key={i} className={`ml-agent-msg ml-agent-${m.role}`}>
              <div className="ml-agent-role">
                {m.role === 'user' ? 'You' : m.role === 'assistant' ? 'Overlord' : 'Error'}
              </div>
              <div className="ml-agent-text">{m.text}</div>
            </div>
          ))}
          {loading && (
            <div className="ml-agent-msg ml-agent-assistant">
              <div className="ml-agent-role">Overlord</div>
              <div className="ml-agent-text ml-agent-thinking">Thinking…</div>
            </div>
          )}
        </div>

        <form
          className="ml-agent-form"
          onSubmit={e => { e.preventDefault(); void send(); }}
        >
          <textarea
            className="ml-agent-input"
            value={input}
            onChange={e => setInput(e.target.value)}
            onKeyDown={onKeyDown}
            placeholder={loading ? 'Waiting for response…' : 'Type a message — Enter to send, Shift+Enter for newline'}
            disabled={loading}
            rows={2}
          />
          <button
            type="submit"
            className="ml-agent-send"
            disabled={loading || !input.trim()}
          >
            Send
          </button>
        </form>
      </div>
    </DraggableWindow>
  );
};
