import { useState, useEffect, useRef, useCallback } from "react";
import { useSpeakWebSocket } from "../../hooks/useSpeakWebSocket";
import {
  discussContract,
  type CreatedContractInfo,
  type ContractToolCallInfo,
  type ChatMessage,
} from "../../lib/api";

interface Message {
  id: string;
  role: "user" | "assistant";
  content: string;
  timestamp: Date;
  toolCalls?: ContractToolCallInfo[];
}

interface DiscussContractModalProps {
  isOpen: boolean;
  onClose: () => void;
  transcriptContext?: string;
  onContractCreated: (contract: CreatedContractInfo) => void;
}

interface ChatBubbleProps {
  message: Message;
  onSpeak: () => void;
  isSpeaking: boolean;
}

function ChatBubble({ message, onSpeak, isSpeaking }: ChatBubbleProps) {
  const isUser = message.role === "user";

  return (
    <div className={`flex ${isUser ? "justify-end" : "justify-start"}`}>
      <div
        className={`max-w-[80%] p-3 font-mono text-sm ${
          isUser
            ? "bg-[#0f3c78] text-[#dbe7ff]"
            : "bg-[#0d1b2d] border border-[rgba(117,170,252,0.25)] text-[#dbe7ff]"
        }`}
      >
        <div className="whitespace-pre-wrap">{message.content}</div>

        {!isUser && (
          <div className="mt-2 flex items-center gap-2">
            <button
              onClick={onSpeak}
              className="text-[10px] text-[#9bc3ff] hover:text-[#dbe7ff] uppercase"
            >
              {isSpeaking ? "[Stop]" : "[Speak]"}
            </button>
          </div>
        )}

        {message.toolCalls && message.toolCalls.length > 0 && (
          <div className="mt-2 pt-2 border-t border-[rgba(117,170,252,0.25)]">
            {message.toolCalls.map((tc, i) => (
              <div key={i} className="text-[10px] text-[#75aafc]">
                {tc.result.success ? "+" : "-"} {tc.name}: {tc.result.message}
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

export function DiscussContractModal({
  isOpen,
  onClose,
  transcriptContext,
  onContractCreated,
}: DiscussContractModalProps) {
  const [messages, setMessages] = useState<Message[]>([]);
  const [input, setInput] = useState("");
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [createdContract, setCreatedContract] = useState<CreatedContractInfo | null>(null);

  const { speak, isSpeaking, cancel } = useSpeakWebSocket();
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const modalRef = useRef<HTMLDivElement>(null);

  // Auto-scroll to bottom on new messages
  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  // Initial greeting when modal opens
  useEffect(() => {
    if (isOpen && messages.length === 0) {
      const greeting = transcriptContext
        ? "I've reviewed your session transcript. What would you like to build based on this discussion?"
        : "Hello! I'm Makima. Tell me about what you'd like to build, and I'll help you create a contract for it.";

      setMessages([{
        id: crypto.randomUUID(),
        role: "assistant",
        content: greeting,
        timestamp: new Date(),
      }]);
    }
  }, [isOpen, transcriptContext, messages.length]);

  // Handle escape key and click outside
  useEffect(() => {
    if (!isOpen) return;

    function handleKeyDown(e: KeyboardEvent) {
      if (e.key === "Escape") {
        onClose();
      }
    }

    function handleClickOutside(e: MouseEvent) {
      if (modalRef.current && !modalRef.current.contains(e.target as Node)) {
        onClose();
      }
    }

    document.addEventListener("keydown", handleKeyDown);
    document.addEventListener("mousedown", handleClickOutside);

    return () => {
      document.removeEventListener("keydown", handleKeyDown);
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [isOpen, onClose]);

  // Reset state when modal closes
  useEffect(() => {
    if (!isOpen) {
      setMessages([]);
      setInput("");
      setIsLoading(false);
      setError(null);
      setCreatedContract(null);
    }
  }, [isOpen]);

  const handleSend = useCallback(async () => {
    if (!input.trim() || isLoading) return;

    const userMessage: Message = {
      id: crypto.randomUUID(),
      role: "user",
      content: input,
      timestamp: new Date(),
    };

    setMessages(prev => [...prev, userMessage]);
    setInput("");
    setIsLoading(true);
    setError(null);

    try {
      // Build history from existing messages (excluding the greeting)
      const history: ChatMessage[] = messages.map(m => ({
        role: m.role,
        content: m.content,
      }));

      const response = await discussContract(
        input,
        undefined, // model
        history,
        transcriptContext
      );

      const assistantMessage: Message = {
        id: crypto.randomUUID(),
        role: "assistant",
        content: response.response,
        timestamp: new Date(),
        toolCalls: response.toolCalls,
      };

      setMessages(prev => [...prev, assistantMessage]);

      if (response.createdContract) {
        setCreatedContract(response.createdContract);
        onContractCreated(response.createdContract);
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to get response");
    } finally {
      setIsLoading(false);
    }
  }, [input, isLoading, messages, transcriptContext, onContractCreated]);

  const handleSpeak = useCallback((text: string) => {
    if (isSpeaking) {
      cancel();
    } else {
      speak(text);
    }
  }, [isSpeaking, cancel, speak]);

  const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      handleSend();
    }
  }, [handleSend]);

  if (!isOpen) return null;

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60">
      <div
        ref={modalRef}
        className="panel w-full max-w-2xl h-[600px] flex flex-col mx-4"
      >
        {/* Header */}
        <div className="flex items-center justify-between p-4 border-b border-[rgba(117,170,252,0.25)]">
          <h2 className="font-mono text-sm text-[#dbe7ff] uppercase tracking-wide">
            Discuss Contract with Makima
          </h2>
          <button
            onClick={onClose}
            className="font-mono text-xs text-[#9bc3ff] hover:text-[#dbe7ff] transition-colors"
          >
            [X]
          </button>
        </div>

        {/* Messages */}
        <div className="flex-1 overflow-y-auto p-4 space-y-4">
          {messages.map((message) => (
            <ChatBubble
              key={message.id}
              message={message}
              onSpeak={() => handleSpeak(message.content)}
              isSpeaking={isSpeaking}
            />
          ))}
          <div ref={messagesEndRef} />

          {isLoading && (
            <div className="flex items-center gap-2 text-[#9bc3ff]">
              <span className="animate-pulse font-mono text-sm">Makima is thinking...</span>
            </div>
          )}

          {error && (
            <div className="font-mono text-xs text-red-400 px-2 py-2 border border-red-400/50 bg-red-400/10">
              {error}
            </div>
          )}
        </div>

        {/* Contract Created Banner */}
        {createdContract && (
          <div className="p-3 bg-green-400/10 border-t border-green-400/50">
            <div className="font-mono text-xs text-green-400">
              Contract "{createdContract.name}" created successfully!
            </div>
          </div>
        )}

        {/* Input */}
        <div className="p-4 border-t border-[rgba(117,170,252,0.25)]">
          <div className="flex gap-2">
            <input
              type="text"
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={handleKeyDown}
              placeholder="Describe your project..."
              disabled={isLoading || !!createdContract}
              className="flex-1 px-3 py-2 bg-[#0d1b2d] border border-[#0f3c78] text-[#dbe7ff] font-mono text-sm focus:border-[#3f6fb3] outline-none disabled:opacity-50"
            />
            <button
              onClick={handleSend}
              disabled={isLoading || !input.trim() || !!createdContract}
              className="px-4 py-2 bg-[#0f3c78] text-[#dbe7ff] font-mono text-xs uppercase hover:bg-[#153667] disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
            >
              Send
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}
