import { useState, useCallback, useRef, useEffect } from "react";
import {
  type LlmModel,
  type UserQuestion,
  type UserAnswer,
  type MeshChatContext,
} from "../../lib/api";
import { useMeshChatHistory } from "../../hooks/useMeshChatHistory";
import { SimpleMarkdown } from "../SimpleMarkdown";

interface UnifiedMeshChatInputProps {
  context: MeshChatContext;
  onUpdate?: () => void;
}

const MODEL_OPTIONS: { value: LlmModel; label: string }[] = [
  { value: "claude-opus", label: "Claude Opus" },
  { value: "claude-sonnet", label: "Claude Sonnet" },
  { value: "groq", label: "Groq Kimi" },
];

const DEFAULT_MODEL: LlmModel = "claude-opus";

// LocalStorage keys
const STORAGE_KEY_MODEL = "makima-mesh-chat-model";
const STORAGE_KEY_CMD_HISTORY = "makima-mesh-chat-cmd-history";
const MAX_CMD_HISTORY = 100;

function loadModel(): LlmModel {
  try {
    const modelStr = localStorage.getItem(STORAGE_KEY_MODEL);
    return (modelStr as LlmModel) || DEFAULT_MODEL;
  } catch {
    return DEFAULT_MODEL;
  }
}

function saveModel(model: LlmModel): void {
  try {
    localStorage.setItem(STORAGE_KEY_MODEL, model);
  } catch {
    // Ignore storage errors
  }
}

function loadCommandHistory(): string[] {
  try {
    const historyJson = localStorage.getItem(STORAGE_KEY_CMD_HISTORY);
    return historyJson ? JSON.parse(historyJson) : [];
  } catch {
    return [];
  }
}

function saveCommandHistory(history: string[]): void {
  try {
    localStorage.setItem(
      STORAGE_KEY_CMD_HISTORY,
      JSON.stringify(history.slice(-MAX_CMD_HISTORY))
    );
  } catch {
    // Ignore storage errors
  }
}

function getPlaceholder(context: MeshChatContext): string {
  switch (context.type) {
    case "mesh":
      return "Create task, list tasks, check status...";
    case "task":
      return "Create subtask, run task, check status...";
    case "subtask":
      return "Update plan, check siblings, merge...";
    default:
      return "Ask anything...";
  }
}

function getContextLabel(context: MeshChatContext): string {
  switch (context.type) {
    case "mesh":
      return "mesh";
    case "task":
      return `task:${context.taskId?.slice(0, 8)}`;
    case "subtask":
      return `subtask:${context.taskId?.slice(0, 8)}`;
    default:
      return "chat";
  }
}

export function UnifiedMeshChatInput({
  context,
  onUpdate,
}: UnifiedMeshChatInputProps) {
  const {
    messages,
    loading: historyLoading,
    error: historyError,
    sending,
    clearHistory,
    sendMessage,
  } = useMeshChatHistory();

  const [input, setInput] = useState("");
  const [expanded, setExpanded] = useState(false);
  const [model, setModel] = useState<LlmModel>(DEFAULT_MODEL);

  // Pending questions state
  const [pendingQuestions, setPendingQuestions] = useState<
    UserQuestion[] | null
  >(null);
  const [userAnswers, setUserAnswers] = useState<Map<string, string[]>>(
    new Map()
  );
  const [customInputs, setCustomInputs] = useState<Map<string, string>>(
    new Map()
  );

  // Command history for arrow key navigation
  const [commandHistory, setCommandHistory] = useState<string[]>([]);
  const [historyIndex, setHistoryIndex] = useState(-1);
  const [savedInput, setSavedInput] = useState("");

  const inputRef = useRef<HTMLInputElement>(null);
  const messagesRef = useRef<HTMLDivElement>(null);

  // Load model preference on mount
  useEffect(() => {
    setModel(loadModel());
    setCommandHistory(loadCommandHistory());
  }, []);

  // Expand when messages exist
  useEffect(() => {
    if (messages.length > 0) {
      setExpanded(true);
    }
  }, [messages.length]);

  // Auto-scroll to bottom when messages change
  useEffect(() => {
    if (messagesRef.current) {
      messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
    }
  }, [messages]);

  // Handle model change
  const handleModelChange = useCallback((newModel: LlmModel) => {
    setModel(newModel);
    saveModel(newModel);
  }, []);

  // Handle keyboard navigation for command history
  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === "ArrowUp") {
        e.preventDefault();
        if (commandHistory.length === 0) return;

        if (historyIndex === -1) {
          setSavedInput(input);
          setHistoryIndex(commandHistory.length - 1);
          setInput(commandHistory[commandHistory.length - 1]);
        } else if (historyIndex > 0) {
          setHistoryIndex(historyIndex - 1);
          setInput(commandHistory[historyIndex - 1]);
        }
      } else if (e.key === "ArrowDown") {
        e.preventDefault();
        if (historyIndex === -1) return;

        if (historyIndex < commandHistory.length - 1) {
          setHistoryIndex(historyIndex + 1);
          setInput(commandHistory[historyIndex + 1]);
        } else {
          setHistoryIndex(-1);
          setInput(savedInput);
        }
      }
    },
    [commandHistory, historyIndex, input, savedInput]
  );

  const handleSubmit = useCallback(
    async (e: React.FormEvent) => {
      e.preventDefault();
      if (!input.trim() || sending) return;

      const userMessage = input.trim();

      // Update command history
      const newHistory =
        commandHistory[commandHistory.length - 1] !== userMessage
          ? [...commandHistory, userMessage]
          : commandHistory;
      setCommandHistory(newHistory);
      saveCommandHistory(newHistory);

      // Reset navigation state
      setHistoryIndex(-1);
      setSavedInput("");

      setInput("");
      setExpanded(true);

      // Send message via hook (uses DB-persisted history)
      const response = await sendMessage(userMessage, context, model);

      if (response) {
        // Handle pending questions
        if (response.pendingQuestions?.length) {
          setPendingQuestions(response.pendingQuestions);
          const initialAnswers = new Map<string, string[]>();
          response.pendingQuestions.forEach((q) => {
            initialAnswers.set(q.id, []);
          });
          setUserAnswers(initialAnswers);
          setCustomInputs(new Map());
        }

        // Notify parent that something may have been updated
        // Always refresh when tool calls were made (state may have changed)
        if (response.toolCalls && response.toolCalls.length > 0) {
          onUpdate?.();
        }
      }

      inputRef.current?.focus();
    },
    [input, sending, context, model, sendMessage, onUpdate, commandHistory]
  );

  // Handle option selection for a question
  const handleOptionToggle = useCallback(
    (questionId: string, option: string, allowMultiple: boolean) => {
      setUserAnswers((prev) => {
        const newMap = new Map(prev);
        const currentAnswers = newMap.get(questionId) || [];

        if (allowMultiple) {
          if (currentAnswers.includes(option)) {
            newMap.set(
              questionId,
              currentAnswers.filter((a) => a !== option)
            );
          } else {
            newMap.set(questionId, [...currentAnswers, option]);
          }
        } else {
          newMap.set(questionId, [option]);
        }

        return newMap;
      });
    },
    []
  );

  // Handle custom input change
  const handleCustomInputChange = useCallback(
    (questionId: string, value: string) => {
      setCustomInputs((prev) => {
        const newMap = new Map(prev);
        newMap.set(questionId, value);
        return newMap;
      });
    },
    []
  );

  // Submit answers to questions
  const handleSubmitAnswers = useCallback(async () => {
    if (!pendingQuestions || sending) return;

    // Build answers array
    const answers: UserAnswer[] = pendingQuestions.map((q) => {
      const selectedOptions = userAnswers.get(q.id) || [];
      const customInput = customInputs.get(q.id)?.trim();
      const finalAnswers = customInput
        ? [...selectedOptions, customInput]
        : selectedOptions;

      return {
        id: q.id,
        answers: finalAnswers,
      };
    });

    // Format answers as a message
    const answerText = answers
      .map((a) => {
        const question = pendingQuestions.find((q) => q.id === a.id);
        return `${question?.question || a.id}: ${a.answers.join(", ")}`;
      })
      .join("\n");

    // Clear pending questions
    setPendingQuestions(null);
    setUserAnswers(new Map());
    setCustomInputs(new Map());

    // Send answers as the next message
    const response = await sendMessage(answerText, context, model);

    if (response) {
      // Handle more pending questions
      if (response.pendingQuestions?.length) {
        setPendingQuestions(response.pendingQuestions);
        const initialAnswers = new Map<string, string[]>();
        response.pendingQuestions.forEach((q) => {
          initialAnswers.set(q.id, []);
        });
        setUserAnswers(initialAnswers);
        setCustomInputs(new Map());
      }

      // Notify parent that something may have been updated
      if (response.toolCalls && response.toolCalls.length > 0) {
        onUpdate?.();
      }
    }
  }, [
    pendingQuestions,
    userAnswers,
    customInputs,
    sending,
    context,
    model,
    sendMessage,
    onUpdate,
  ]);

  // Cancel answering questions
  const handleCancelQuestions = useCallback(() => {
    setPendingQuestions(null);
    setUserAnswers(new Map());
    setCustomInputs(new Map());
  }, []);

  const handleClearHistory = useCallback(async () => {
    await clearHistory();
    setPendingQuestions(null);
    setUserAnswers(new Map());
    setCustomInputs(new Map());
  }, [clearHistory]);

  const loading = sending || historyLoading;

  return (
    <div className="border-t border-[rgba(117,170,252,0.35)] bg-[#0d1b2d]">
      {/* Error Display */}
      {historyError && (
        <div className="px-3 py-2 bg-red-900/20 text-red-400 text-xs font-mono">
          {historyError}
        </div>
      )}

      {/* Messages Panel (expandable) */}
      {expanded && messages.length > 0 && (
        <div
          ref={messagesRef}
          className="max-h-48 overflow-y-auto p-3 space-y-2 border-b border-[rgba(117,170,252,0.2)]"
        >
          {messages.map((msg) => (
            <div key={msg.id} className="font-mono text-xs">
              {msg.role === "user" && (
                <div className="flex gap-2">
                  <span className="text-[#9bc3ff]">&gt;</span>
                  <span className="text-white/80 whitespace-pre-wrap">
                    {msg.content}
                  </span>
                  {msg.contextType !== "mesh" && (
                    <span className="text-[#555] text-[10px]">
                      [{msg.contextType}]
                    </span>
                  )}
                </div>
              )}
              {msg.role === "assistant" && (
                <div className="pl-4 space-y-1">
                  <SimpleMarkdown
                    content={msg.content}
                    className="text-[#75aafc]"
                  />
                  {msg.toolCalls && msg.toolCalls.length > 0 && (
                    <div className="text-[#555] text-[10px] space-y-0.5">
                      {msg.toolCalls.map((tc, i) => (
                        <div key={i}>
                          <span
                            className={
                              tc.result.success
                                ? "text-green-500"
                                : "text-red-400"
                            }
                          >
                            {tc.result.success ? "+" : "x"}
                          </span>{" "}
                          {tc.name}: {tc.result.message}
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              )}
              {msg.role === "error" && (
                <div className="pl-4 text-red-400">{msg.content}</div>
              )}
            </div>
          ))}
        </div>
      )}

      {/* Pending Questions UI */}
      {pendingQuestions && pendingQuestions.length > 0 && (
        <div className="p-3 border-b border-[rgba(117,170,252,0.2)] space-y-3">
          <div className="text-[#9bc3ff] font-mono text-xs uppercase tracking-wide">
            Questions from AI
          </div>
          {pendingQuestions.map((q) => (
            <div key={q.id} className="space-y-2">
              <div className="text-white/90 font-mono text-sm">
                {q.question}
              </div>
              <div className="flex flex-wrap gap-2">
                {q.options.map((option) => {
                  const isSelected = (userAnswers.get(q.id) || []).includes(
                    option
                  );
                  return (
                    <button
                      key={option}
                      type="button"
                      onClick={() =>
                        handleOptionToggle(q.id, option, q.allowMultiple)
                      }
                      className={`px-2 py-1 font-mono text-xs border transition-colors ${
                        isSelected
                          ? "bg-[#3f6fb3] border-[#75aafc] text-white"
                          : "bg-transparent border-[rgba(117,170,252,0.25)] text-[#9bc3ff] hover:border-[#3f6fb3]"
                      }`}
                    >
                      {q.allowMultiple && (
                        <span className="mr-1">{isSelected ? "+" : "-"}</span>
                      )}
                      {option}
                    </button>
                  );
                })}
              </div>
              {q.allowCustom && (
                <input
                  type="text"
                  value={customInputs.get(q.id) || ""}
                  onChange={(e) => handleCustomInputChange(q.id, e.target.value)}
                  placeholder="Or type a custom answer..."
                  className="w-full bg-transparent border border-[rgba(117,170,252,0.25)] text-white font-mono text-xs px-2 py-1 outline-none focus:border-[#3f6fb3] placeholder-[#555]"
                />
              )}
            </div>
          ))}
          <div className="flex gap-2 pt-2">
            <button
              type="button"
              onClick={handleSubmitAnswers}
              disabled={loading}
              className="px-3 py-1 font-mono text-xs text-[#9bc3ff] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] disabled:opacity-50 disabled:cursor-not-allowed transition-colors uppercase"
            >
              {loading ? "..." : "Submit Answers"}
            </button>
            <button
              type="button"
              onClick={handleCancelQuestions}
              disabled={loading}
              className="px-3 py-1 font-mono text-xs text-[#555] hover:text-[#9bc3ff] transition-colors"
            >
              Cancel
            </button>
          </div>
        </div>
      )}

      {/* Input Bar */}
      <form onSubmit={handleSubmit} className="flex items-center gap-2 p-3">
        <select
          value={model}
          onChange={(e) => handleModelChange(e.target.value as LlmModel)}
          disabled={loading || !!pendingQuestions}
          className="bg-[#0d1b2d] border border-[rgba(117,170,252,0.25)] text-[#9bc3ff] font-mono text-xs px-2 py-1 rounded-none outline-none focus:border-[#3f6fb3] disabled:opacity-50"
        >
          {MODEL_OPTIONS.map((opt) => (
            <option key={opt.value} value={opt.value}>
              {opt.label}
            </option>
          ))}
        </select>
        <span className="text-[#555] font-mono text-[10px]">
          [{getContextLabel(context)}]
        </span>
        <span className="text-[#9bc3ff] font-mono text-sm">&gt;</span>
        <input
          ref={inputRef}
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={handleKeyDown}
          placeholder={
            loading
              ? "Processing..."
              : pendingQuestions
              ? "Answer questions above first..."
              : getPlaceholder(context)
          }
          disabled={loading || !!pendingQuestions}
          className="flex-1 bg-transparent border-none outline-none font-mono text-sm text-white placeholder-[#555]"
        />
        {messages.length > 0 && (
          <button
            type="button"
            onClick={handleClearHistory}
            className="text-[#555] hover:text-[#9bc3ff] font-mono text-xs transition-colors"
          >
            clear
          </button>
        )}
        <button
          type="submit"
          disabled={loading || !input.trim() || !!pendingQuestions}
          className="px-3 py-1 font-mono text-xs text-[#9bc3ff] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] disabled:opacity-50 disabled:cursor-not-allowed transition-colors uppercase"
        >
          {loading ? "..." : "Send"}
        </button>
      </form>
    </div>
  );
}
