import { useEffect, useRef, useState } from "react";
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import type { AgenticStepType } from "@/controllers/API/queries/agentic";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/utils/utils";
import { getAssistantPlaceholder } from "../assistant-panel.constants";
import type { AssistantModel } from "../assistant-panel.types";
import { getRandomPlaceholderMessage } from "../helpers/messages";
import { ModelSelector } from "./model-selector";

// Steps where the "thinking" animation is showing in the message area
const GENERATING_STEPS: AgenticStepType[] = [
  "generating",
  "generating_component",
];

// Hook for rotating placeholder messages during post-generation processing
function useAnimatedPlaceholder(
  shouldAnimate: boolean,
  intervalMs = 2000,
): string {
  const [currentMessage, setCurrentMessage] = useState(() =>
    getRandomPlaceholderMessage(),
  );

  useEffect(() => {
    if (!shouldAnimate) {
      return;
    }

    // Set initial message when animation starts
    setCurrentMessage(getRandomPlaceholderMessage());

    // Rotate messages at interval
    const interval = setInterval(() => {
      setCurrentMessage(getRandomPlaceholderMessage());
    }, intervalMs);

    return () => clearInterval(interval);
  }, [shouldAnimate, intervalMs]);

  return currentMessage;
}

const ASSISTANT_MODEL_STORAGE_KEY = "langflow-assistant-selected-model";
const MAX_MESSAGE_LENGTH = 500;

interface AssistantInputProps {
  onSend: (message: string, model: AssistantModel | null) => void;
  onStop?: () => void;
  disabled?: boolean;
  isProcessing?: boolean;
  currentStep?: AgenticStepType | null;
  placeholder?: string;
  compact?: boolean;
  autoFocus?: boolean;
  draftMessage?: string;
  onDraftChange?: (draft: string) => void;
}

export function AssistantInput({
  onSend,
  onStop,
  disabled = false,
  isProcessing = false,
  currentStep = null,
  placeholder,
  compact = false,
  autoFocus = false,
  draftMessage = "",
  onDraftChange,
}: AssistantInputProps) {
  const [message, setMessage] = useState(draftMessage);
  const [idlePlaceholder] = useState(getAssistantPlaceholder);

  // Show animated placeholder only during post-generation steps (when thinking animation is done)
  const isPostGenerationStep =
    isProcessing &&
    currentStep !== null &&
    !GENERATING_STEPS.includes(currentStep);
  const animatedPlaceholder = useAnimatedPlaceholder(isPostGenerationStep);
  const [selectedModel, setSelectedModel] = useState<AssistantModel | null>(
    () => {
      // Load from localStorage on init
      try {
        const saved = localStorage.getItem(ASSISTANT_MODEL_STORAGE_KEY);
        if (!saved) return null;

        const parsed = JSON.parse(saved);
        // Validate that model has required fields
        if (parsed && parsed.provider && parsed.name) {
          return parsed as AssistantModel;
        }
        // Invalid model format, clear it
        localStorage.removeItem(ASSISTANT_MODEL_STORAGE_KEY);
        return null;
      } catch {
        // localStorage may be unavailable (private browsing) or corrupted
        localStorage.removeItem(ASSISTANT_MODEL_STORAGE_KEY);
        return null;
      }
    },
  );
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  // Auto-focus textarea when requested
  useEffect(() => {
    if (autoFocus && textareaRef.current && !disabled && !isProcessing) {
      textareaRef.current.focus();
    }
  }, [autoFocus, disabled, isProcessing]);

  // Save to localStorage when model changes
  useEffect(() => {
    if (selectedModel) {
      localStorage.setItem(
        ASSISTANT_MODEL_STORAGE_KEY,
        JSON.stringify(selectedModel),
      );
    }
  }, [selectedModel]);

  const updateMessage = (value: string) => {
    setMessage(value);
    onDraftChange?.(value);
  };

  const handleSend = () => {
    const trimmedMessage = message.trim();
    if (!trimmedMessage || disabled || isProcessing) return;
    onSend(trimmedMessage, selectedModel);
    updateMessage("");
  };

  const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      handleSend();
    }
    if (e.key === "Escape") {
      textareaRef.current?.blur();
    }
  };

  const canSend = message.trim().length > 0 && !disabled;
  const charsRemaining = MAX_MESSAGE_LENGTH - message.length;
  const showCharCount = message.length > MAX_MESSAGE_LENGTH * 0.8;

  return (
    <div className="relative px-2 pb-2">
      {/* Glow effect below input */}
      <div
        className="pointer-events-none absolute -bottom-2 left-1/2 h-16 w-3/4 -translate-x-1/2 rounded-full opacity-60 blur-2xl"
        style={{
          background:
            "linear-gradient(90deg, rgba(186,117,255,0.4) 0%, rgba(255,50,118,0.5) 50%, rgba(186,117,255,0.4) 100%)",
        }}
      />
      <div
        className={cn(
          "relative flex cursor-text flex-col rounded-md border border-border bg-background pb-2.5 transition-colors focus-within:border-muted-foreground shadow-[0_0_15px_rgba(186,117,255,0.12),0_0_30px_rgba(255,50,118,0.08)]",
          compact ? "gap-1" : "gap-4",
        )}
        onClick={() => textareaRef.current?.focus()}
      >
        <div className="relative">
          <Textarea
            ref={textareaRef}
            value={message}
            maxLength={MAX_MESSAGE_LENGTH}
            onChange={(e) => updateMessage(e.target.value)}
            data-testid="assistant-input-textarea"
            onKeyDown={handleKeyDown}
            placeholder={
              isProcessing
                ? isPostGenerationStep
                  ? ""
                  : "Working on it..."
                : (placeholder ?? idlePlaceholder)
            }
            disabled={disabled || isProcessing}
            className={cn(
              "resize-none border-0 bg-transparent px-4 pt-3 text-sm focus-visible:ring-0 disabled:bg-transparent disabled:cursor-not-allowed",
              compact ? "min-h-0" : "min-h-[60px]",
              isProcessing && !isPostGenerationStep && "placeholder:opacity-50",
            )}
            rows={compact ? 1 : 2}
          />
          {isPostGenerationStep && !message && (
            <div className="pointer-events-none absolute left-4 top-3 flex items-center gap-2 text-sm text-muted-foreground">
              <ForwardedIconComponent
                name="Loader2"
                className="h-4 w-4 animate-spin"
              />
              <span className="animate-pulse">{animatedPlaceholder}</span>
            </div>
          )}
        </div>
        <div className="flex items-center justify-between px-3">
          <div className="flex items-center gap-4">
            <ModelSelector
              selectedModel={selectedModel}
              onModelChange={setSelectedModel}
            />
          </div>
          <div className="flex items-center gap-2">
            {showCharCount && (
              <span
                className={cn(
                  "text-xs tabular-nums",
                  charsRemaining <= 20
                    ? "text-destructive"
                    : "text-muted-foreground",
                )}
              >
                {charsRemaining}
              </span>
            )}
            {isProcessing ? (
              <button
                type="button"
                onClick={onStop}
                title="Stop generation"
                data-testid="assistant-stop-button"
                className="flex h-8 w-8 items-center justify-center rounded-lg bg-muted-foreground/15 text-muted-foreground transition-colors hover:bg-muted-foreground/25"
              >
                <ForwardedIconComponent
                  name="Square"
                  className="h-3 w-3 fill-current"
                />
              </button>
            ) : (
              <Button
                size="icon"
                data-testid="assistant-send-button"
                className="h-8 w-8 rounded-lg"
                onClick={handleSend}
                disabled={!canSend}
                title="Send message"
              >
                <ForwardedIconComponent name="ArrowUp" className="h-4 w-4" />
              </Button>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}
