import { SendIcon, XIcon } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { getAccessToken } from "@/auth-state";
import Spinner from "@/components/Spinner";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";
import { getClerkSessionToken } from "@/utils/clerk";
import { generateUUID } from "@/utils/uuid";

type ProductSummary = {
  sku?: string;
  name?: string;
  price?: number;
  sale_price?: number | null;
  url?: string;
  thumbnail_image_url?: string;
};

type ChatMessage = {
  id: string;
  role: "user" | "assistant" | "error";
  content: string;
  products?: ProductSummary[];
};

const DEVICE_STORAGE_KEY = "canifa_device_id";

// Call backend directly (bypass Vite proxy).
// Override via VITE_API_BASE_URL, e.g. "http://localhost:5000"
const API_ORIGIN = (import.meta.env.VITE_API_BASE_URL as string | undefined) || "http://localhost:5000";

const getDeviceId = (): string => {
  if (typeof window === "undefined") return "unknown";
  try {
    const cached = localStorage.getItem(DEVICE_STORAGE_KEY);
    if (cached) return cached;
    const next = generateUUID();
    localStorage.setItem(DEVICE_STORAGE_KEY, next);
    return next;
  } catch {
    return "unknown";
  }
};

const extractErrorMessage = (payload: unknown, fallback: string): string => {
  if (!payload || typeof payload !== "object") return fallback;
  if ("detail" in payload && typeof (payload as { detail?: string }).detail === "string") {
    return (payload as { detail: string }).detail;
  }
  if ("message" in payload && typeof (payload as { message?: string }).message === "string") {
    return (payload as { message: string }).message;
  }
  return fallback;
};

const buildProductLabel = (product: ProductSummary): string => {
  return product.sku || product.name || "item";
};

type ChatbotPanelProps = {
  className?: string;
  variant?: "inline" | "widget";
  onClose?: () => void;
};

const ChatbotPanel = ({ className, variant = "inline", onClose }: ChatbotPanelProps) => {
  const [deviceId] = useState(() => getDeviceId());
  const [messages, setMessages] = useState<ChatMessage[]>([]);
  const [input, setInput] = useState("");
  const [isSending, setIsSending] = useState(false);
  const scrollAnchorRef = useRef<HTMLDivElement>(null);
  const isWidget = variant === "widget";

  useEffect(() => {
    scrollAnchorRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
  }, [messages, isSending]);

  const sendMessage = async () => {
    const trimmed = input.trim();
    if (!trimmed || isSending) return;

    const userMessage: ChatMessage = {
      id: generateUUID(),
      role: "user",
      content: trimmed,
    };
    setMessages((prev) => [...prev, userMessage]);
    setInput("");
    setIsSending(true);

    try {
      const headers: HeadersInit = {
        "Content-Type": "application/json",
        device_id: deviceId,
      };
      const token = (await getClerkSessionToken()) || getAccessToken();
      if (token) {
        headers["Authorization"] = `Bearer ${token}`;
      }

      const response = await fetch(`${API_ORIGIN}/api/agent/chat`, {
        method: "POST",
        headers,
        credentials: "include",
        body: JSON.stringify({ user_query: trimmed }),
      });
      const payload = await response.json().catch(() => ({}));

      if (!response.ok) {
        throw new Error(extractErrorMessage(payload, "Chat request failed."));
      }
      if (payload && payload.status !== "success") {
        throw new Error(extractErrorMessage(payload, "Chat request failed."));
      }

      const aiMessage: ChatMessage = {
        id: generateUUID(),
        role: "assistant",
        content: typeof payload.ai_response === "string" ? payload.ai_response : "",
        products: Array.isArray(payload.product_ids) ? payload.product_ids : [],
      };
      setMessages((prev) => [...prev, aiMessage]);
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : "Chat request failed.";
      setMessages((prev) => [
        ...prev,
        {
          id: generateUUID(),
          role: "error",
          content: errorMessage,
        },
      ]);
    } finally {
      setIsSending(false);
    }
  };

  const panelClassName = cn(
    "w-full rounded-2xl border border-border",
    isWidget ? "bg-background shadow-lg" : "bg-muted/30 shadow-sm",
  );
  const messagePaneClassName = cn(
    "flex-1 min-h-0 overflow-y-auto rounded-xl border border-border bg-background/70 p-3",
    isWidget ? "h-full" : "max-h-72",
  );

  return (
    <div className={cn("w-full h-full", className)}>
      <div className={cn(panelClassName, isWidget && "flex h-full flex-col p-3")}>
        {isWidget ? (
          <div className="flex items-center justify-between gap-2 border-b border-border pb-2">
            <div className="flex items-center gap-2">
              <span className="inline-flex size-2 rounded-full bg-emerald-500" />
              <div>
                <p className="text-sm font-semibold leading-none">CiCi Assistant</p>
                <p className="text-xs text-muted-foreground">Notes chat</p>
              </div>
            </div>
            {onClose && (
              <button
                type="button"
                className="rounded-full p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
                onClick={onClose}
                aria-label="Close chat"
              >
                <XIcon className="size-4" />
              </button>
            )}
          </div>
        ) : (
          <div className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
            <div className="space-y-1">
              <h2 className="text-lg font-semibold">Chat Assistant</h2>
              <p className="text-sm text-muted-foreground">Ask about your notes by day or tag.</p>
            </div>
            <Badge variant="secondary">beta</Badge>
          </div>
        )}

        <div className={cn("space-y-3", isWidget ? "mt-3 flex flex-1 flex-col" : "mt-4")}>
          <div className={messagePaneClassName}>
            {messages.length === 0 ? (
              <p className="text-sm text-muted-foreground">No messages yet. Ask about a memo, a day, or a tag.</p>
            ) : (
              <div className="space-y-3">
                {messages.map((message) => (
                  <div
                    key={message.id}
                    className={cn("flex", message.role === "user" ? "justify-end" : "justify-start")}
                  >
                    <div
                      className={cn(
                        "max-w-[85%] rounded-lg px-3 py-2 text-sm whitespace-pre-wrap",
                        message.role === "user" && "bg-primary text-primary-foreground",
                        message.role === "assistant" && "bg-muted text-foreground",
                        message.role === "error" && "bg-destructive/10 text-destructive border border-destructive/30",
                      )}
                    >
                      {message.content || "(empty response)"}
                      {message.products && message.products.length > 0 && (
                        <div className="mt-2 flex flex-wrap gap-1">
                          {message.products.slice(0, 6).map((product, index) => (
                            <Badge key={`${message.id}-product-${index}`} variant="outline">
                              {buildProductLabel(product)}
                            </Badge>
                          ))}
                          {message.products.length > 6 && (
                            <Badge variant="outline">+{message.products.length - 6} more</Badge>
                          )}
                        </div>
                      )}
                    </div>
                  </div>
                ))}
              </div>
            )}
            {isSending && (
              <div className="mt-3 flex items-center gap-2 text-sm text-muted-foreground">
                <Spinner size="sm" />
                Thinking...
              </div>
            )}
            <div ref={scrollAnchorRef} />
          </div>

          <form
            className={cn(
              "flex gap-2",
              isWidget ? "items-end" : "flex-col md:flex-row md:items-end",
            )}
            onSubmit={(event) => {
              event.preventDefault();
              void sendMessage();
            }}
          >
            <Textarea
              value={input}
              onChange={(event) => setInput(event.target.value)}
              onKeyDown={(event) => {
                if (event.key === "Enter" && !event.shiftKey) {
                  event.preventDefault();
                  void sendMessage();
                }
              }}
              placeholder="Type a question. Enter to send."
              className={cn("min-h-12 md:min-h-14", isWidget && "min-h-10 md:min-h-12")}
              disabled={isSending}
            />
            <Button type="submit" disabled={isSending || input.trim().length === 0} size={isWidget ? "icon" : "default"}>
              {isWidget ? <SendIcon className="size-4" /> : "Send"}
            </Button>
          </form>
        </div>
      </div>
    </div>
  );
};

export default ChatbotPanel;
