// src/components/Chatbot/Chatbot.tsx
import { useRef as useRef5 } from "react";

// src/components/Chatbot/ChatbotFab.tsx
import { ChatCircleDotsIcon } from "@phosphor-icons/react";

// src/components/Button/Button.tsx
import { forwardRef } from "react";

// src/utils/utils.ts
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
function cn(...inputs) {
  return twMerge(clsx(inputs));
}

// src/components/Button/Button.tsx
import { jsx, jsxs } from "react/jsx-runtime";
var VARIANT_ACTION_CLASSES = {
  solid: {
    primary: "bg-primary-950 text-text border border-primary-950 hover:bg-primary-800 hover:border-primary-800 focus-visible:outline-none focus-visible:bg-primary-950 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-primary-700 active:border-primary-700 disabled:bg-primary-500 disabled:border-primary-500 disabled:opacity-40 disabled:cursor-not-allowed",
    secondary: "bg-text-950 text-text border border-text-800 hover:bg-text-800 hover:border-text-950 focus-visible:outline-none focus-visible:bg-text-900 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-text-700 active:border-text-700 disabled:bg-text-500 disabled:border-text-500 disabled:opacity-40 disabled:cursor-not-allowed",
    positive: "bg-success-500 text-text border border-success-500 hover:bg-success-600 hover:border-success-600 focus-visible:outline-none focus-visible:bg-success-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-success-700 active:border-success-700 disabled:bg-success-500 disabled:border-success-500 disabled:opacity-40 disabled:cursor-not-allowed",
    negative: "bg-error-500 text-text border border-error-500 hover:bg-error-600 hover:border-error-600 focus-visible:outline-none focus-visible:bg-error-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-error-700 active:border-error-700 disabled:bg-error-500 disabled:border-error-500 disabled:opacity-40 disabled:cursor-not-allowed"
  },
  outline: {
    primary: "bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed",
    secondary: "bg-transparent text-text-950 border border-text-800 hover:bg-background-50 hover:text-text-700 hover:border-text-700 focus-visible:border-0 focus-visible:outline-none focus-visible:text-text-900 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-text-700 active:border-text-700 disabled:opacity-40 disabled:cursor-not-allowed",
    positive: "bg-transparent text-success-500 border border-success-300 hover:bg-background-50 hover:text-success-400 hover:border-success-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 active:border-success-700 disabled:opacity-40 disabled:cursor-not-allowed",
    negative: "bg-transparent text-error-500 border border-error-300 hover:bg-background-50 hover:text-error-400 hover:border-error-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 active:border-error-700 disabled:opacity-40 disabled:cursor-not-allowed"
  },
  link: {
    primary: "bg-transparent text-primary-950 hover:text-primary-400 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 disabled:opacity-40 disabled:cursor-not-allowed",
    secondary: "bg-transparent text-text-950 hover:text-text-800 focus-visible:outline-none focus-visible:text-text-900 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-text-700 disabled:opacity-40 disabled:cursor-not-allowed",
    positive: "bg-transparent text-success-500 hover:text-success-400 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 disabled:opacity-40 disabled:cursor-not-allowed",
    negative: "bg-transparent text-error-500 hover:text-error-400 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 disabled:opacity-40 disabled:cursor-not-allowed"
  }
};
var SIZE_CLASSES = {
  "extra-small": "text-xs px-3.5 py-2",
  small: "text-sm px-4 py-2.5",
  medium: "text-md px-5 py-2.5",
  large: "text-lg px-6 py-3",
  "extra-large": "text-lg px-7 py-3.5"
};
var Button = forwardRef(
  ({
    children,
    iconLeft,
    iconRight,
    size = "medium",
    variant = "solid",
    action = "primary",
    className = "",
    disabled,
    type = "button",
    ...props
  }, ref) => {
    if (variant === "raw") {
      return /* @__PURE__ */ jsxs(
        "button",
        {
          ref,
          className,
          disabled,
          type,
          ...props,
          children: [
            iconLeft && /* @__PURE__ */ jsx("span", { className: "mr-2 flex items-center", children: iconLeft }),
            children,
            iconRight && /* @__PURE__ */ jsx("span", { className: "ml-2 flex items-center", children: iconRight })
          ]
        }
      );
    }
    const sizeClasses = SIZE_CLASSES[size];
    const variantClasses = VARIANT_ACTION_CLASSES[variant][action];
    const baseClasses = "inline-flex items-center justify-center rounded-full cursor-pointer font-medium";
    return /* @__PURE__ */ jsxs(
      "button",
      {
        ref,
        className: cn(baseClasses, variantClasses, sizeClasses, className),
        disabled,
        type,
        ...props,
        children: [
          iconLeft && /* @__PURE__ */ jsx("span", { className: "mr-2 flex items-center", children: iconLeft }),
          children,
          iconRight && /* @__PURE__ */ jsx("span", { className: "ml-2 flex items-center", children: iconRight })
        ]
      }
    );
  }
);
Button.displayName = "Button";
var Button_default = Button;

// src/components/Text/Text.tsx
import { jsx as jsx2 } from "react/jsx-runtime";
var Text = ({
  children,
  size = "md",
  weight = "normal",
  color = "text-text-950",
  as,
  className = "",
  ...props
}) => {
  let sizeClasses;
  let weightClasses;
  const sizeClassMap = {
    "2xs": "text-2xs",
    xs: "text-xs",
    sm: "text-sm",
    md: "text-md",
    lg: "text-lg",
    xl: "text-xl",
    "2xl": "text-2xl",
    "3xl": "text-3xl",
    "4xl": "text-4xl",
    "5xl": "text-5xl",
    "6xl": "text-6xl"
  };
  sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;
  const weightClassMap = {
    hairline: "font-hairline",
    light: "font-light",
    normal: "font-normal",
    medium: "font-medium",
    semibold: "font-semibold",
    bold: "font-bold",
    extrabold: "font-extrabold",
    black: "font-black"
  };
  weightClasses = weightClassMap[weight] ?? weightClassMap.normal;
  const baseClasses = "font-primary";
  const Component = as ?? "p";
  return /* @__PURE__ */ jsx2(
    Component,
    {
      className: cn(baseClasses, sizeClasses, weightClasses, color, className),
      ...props,
      children
    }
  );
};
var Text_default = Text;

// src/components/Chatbot/ChatbotFab.tsx
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
function ChatbotFab({
  onClick,
  isOpen = false,
  unreadCount = 0,
  className
}) {
  const noun = unreadCount === 1 ? "mensagem n\xE3o lida" : "mensagens n\xE3o lidas";
  let badgeLabel;
  if (unreadCount > 9) {
    badgeLabel = "Mais de 9 mensagens n\xE3o lidas";
  } else {
    badgeLabel = `${unreadCount} ${noun}`;
  }
  const baseAriaLabel = isOpen ? "Fechar assistente" : "Abrir assistente de estudos";
  const ariaLabel = unreadCount > 0 ? `${baseAriaLabel} (${badgeLabel})` : baseAriaLabel;
  return /* @__PURE__ */ jsxs2(
    Button_default,
    {
      variant: "raw",
      onClick,
      "aria-label": ariaLabel,
      "aria-expanded": isOpen,
      className: cn(
        "fixed bottom-6 right-6 z-40",
        "flex h-14 w-14 items-center justify-center rounded-full",
        "bg-primary-500 text-white shadow-lg",
        "transition-all hover:bg-primary-600 active:scale-95",
        "focus:outline-none focus:ring-2 focus:ring-primary-300",
        className
      ),
      children: [
        /* @__PURE__ */ jsx3(ChatCircleDotsIcon, { size: 26, weight: "fill" }),
        unreadCount > 0 && /* @__PURE__ */ jsx3(
          Text_default,
          {
            as: "span",
            size: "xs",
            weight: "bold",
            color: "text-white",
            "data-testid": "chatbot-fab-badge",
            "aria-live": "polite",
            "aria-label": badgeLabel,
            className: "absolute -top-1 -right-1 flex h-5 min-w-5 items-center justify-center rounded-full bg-error-500 px-1",
            children: unreadCount > 9 ? "9+" : unreadCount
          }
        )
      ]
    }
  );
}

// src/components/Chatbot/ChatbotPanel.tsx
import { useEffect, useRef, useState } from "react";
import {
  CaretUpIcon,
  ListIcon,
  MinusIcon,
  PlusIcon,
  RobotIcon,
  XIcon
} from "@phosphor-icons/react";

// src/components/IconButton/IconButton.tsx
import { forwardRef as forwardRef2 } from "react";
import { jsx as jsx4 } from "react/jsx-runtime";
var IconButton = forwardRef2(
  ({ icon, size = "md", active = false, className = "", disabled, ...props }, ref) => {
    const baseClasses = [
      "inline-flex",
      "items-center",
      "justify-center",
      "rounded-lg",
      "font-medium",
      "bg-transparent",
      "text-text-950",
      "cursor-pointer",
      "hover:bg-primary-600",
      "hover:text-text",
      "focus-visible:outline-none",
      "focus-visible:ring-2",
      "focus-visible:ring-offset-0",
      "focus-visible:ring-indicator-info",
      "disabled:opacity-50",
      "disabled:cursor-not-allowed",
      "disabled:pointer-events-none"
    ];
    const sizeClasses = {
      sm: ["w-6", "h-6", "text-sm"],
      md: ["w-10", "h-10", "text-base"]
    };
    const activeClasses = active ? ["!bg-primary-50", "!text-primary-950", "hover:!bg-primary-100"] : [];
    const allClasses = [
      ...baseClasses,
      ...sizeClasses[size],
      ...activeClasses
    ].join(" ");
    const ariaLabel = props["aria-label"] ?? "Bot\xE3o de a\xE7\xE3o";
    return /* @__PURE__ */ jsx4(
      "button",
      {
        ref,
        type: "button",
        className: cn(allClasses, className),
        disabled,
        "aria-pressed": active,
        "aria-label": ariaLabel,
        ...props,
        children: /* @__PURE__ */ jsx4("span", { className: "flex items-center justify-center", children: icon })
      }
    );
  }
);
IconButton.displayName = "IconButton";
var IconButton_default = IconButton;

// src/components/Chatbot/ChatbotPanel.tsx
import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
var HEADER_ICON_BUTTON_CLASSES = "!text-white hover:!bg-white/15 hover:!text-white focus-visible:!ring-white/60";
function ChatbotPanel({
  isOpen,
  onClose,
  onStartNew,
  historySlot,
  messagesSlot,
  inputSlot,
  errorMessage,
  className
}) {
  const [showHistory, setShowHistory] = useState(false);
  const [isMinimized, setIsMinimized] = useState(false);
  const closeButtonRef = useRef(null);
  const previouslyFocusedRef = useRef(null);
  const previousErrorRef = useRef(errorMessage);
  useEffect(() => {
    if (isOpen) {
      setIsMinimized(false);
    }
  }, [isOpen]);
  useEffect(() => {
    const previous = previousErrorRef.current;
    if (errorMessage && errorMessage !== previous) {
      setIsMinimized(false);
    }
    previousErrorRef.current = errorMessage;
  }, [errorMessage]);
  useEffect(() => {
    if (!isOpen) return;
    previouslyFocusedRef.current = document.activeElement;
    closeButtonRef.current?.focus();
    const handleKeyDown = (event) => {
      if (event.key === "Escape") {
        event.stopPropagation();
        onClose();
      }
    };
    globalThis.addEventListener("keydown", handleKeyDown);
    return () => {
      globalThis.removeEventListener("keydown", handleKeyDown);
      const previous = previouslyFocusedRef.current;
      if (previous && typeof previous.focus === "function") {
        previous.focus();
      }
    };
  }, [isOpen, onClose]);
  if (!isOpen) return null;
  return /* @__PURE__ */ jsxs3(
    "dialog",
    {
      open: true,
      "aria-label": "Assistente de estudos",
      style: isMinimized ? void 0 : { height: "min(720px, calc(100vh - 3rem))" },
      className: cn(
        // `<dialog open>` comes with `margin: auto` by default; `m-0`
        // resets that so the `fixed` positioning below pins the panel
        // to the bottom-right as intended. The panel sits at the same
        // bottom-right corner as the FAB (the FAB is hidden while the
        // panel is open to avoid stacking).
        "fixed bottom-6 right-6 z-40 m-0",
        // Responsive sizing: fills small viewports without overflowing,
        // yet caps at the intended desktop footprint on larger screens.
        // The panel widens when the history sidebar is visible so the
        // main chat column keeps enough horizontal room for messages.
        "flex w-[calc(100vw-3rem)] flex-col overflow-hidden rounded-2xl p-0",
        showHistory ? "max-w-[620px] sm:max-w-[640px]" : "max-w-[400px] sm:max-w-[420px]",
        "border border-background-200 bg-background shadow-2xl",
        className
      ),
      children: [
        /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between gap-2 bg-primary-500 px-4 py-3 text-white", children: [
          /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-3", children: [
            /* @__PURE__ */ jsx5(
              "div",
              {
                "aria-hidden": "true",
                className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full bg-white/15 text-white",
                children: /* @__PURE__ */ jsx5(RobotIcon, { size: 20, weight: "fill" })
              }
            ),
            /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 flex-col", children: [
              /* @__PURE__ */ jsx5(
                Text_default,
                {
                  size: "md",
                  weight: "semibold",
                  className: "truncate leading-tight text-white",
                  children: "Assistente de estudos"
                }
              ),
              /* @__PURE__ */ jsx5(Text_default, { size: "2xs", className: "truncate leading-tight text-white/80", children: "Tire d\xFAvidas enquanto estuda" })
            ] })
          ] }),
          /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
            !isMinimized && /* @__PURE__ */ jsxs3(Fragment, { children: [
              /* @__PURE__ */ jsx5(
                IconButton_default,
                {
                  size: "sm",
                  "aria-label": showHistory ? "Ocultar hist\xF3rico" : "Mostrar hist\xF3rico",
                  onClick: () => setShowHistory((v) => !v),
                  icon: /* @__PURE__ */ jsx5(ListIcon, { size: 18 }),
                  className: HEADER_ICON_BUTTON_CLASSES
                }
              ),
              /* @__PURE__ */ jsx5(
                IconButton_default,
                {
                  size: "sm",
                  "aria-label": "Nova conversa",
                  onClick: onStartNew,
                  icon: /* @__PURE__ */ jsx5(PlusIcon, { size: 18 }),
                  className: HEADER_ICON_BUTTON_CLASSES
                }
              )
            ] }),
            /* @__PURE__ */ jsx5(
              IconButton_default,
              {
                size: "sm",
                "aria-label": isMinimized ? "Expandir assistente" : "Minimizar assistente",
                "aria-expanded": !isMinimized,
                onClick: () => setIsMinimized((v) => !v),
                icon: isMinimized ? /* @__PURE__ */ jsx5(CaretUpIcon, { size: 18 }) : /* @__PURE__ */ jsx5(MinusIcon, { size: 18 }),
                className: HEADER_ICON_BUTTON_CLASSES
              }
            ),
            /* @__PURE__ */ jsx5(
              IconButton_default,
              {
                ref: closeButtonRef,
                size: "sm",
                "aria-label": "Fechar assistente",
                onClick: onClose,
                icon: /* @__PURE__ */ jsx5(XIcon, { size: 18 }),
                className: HEADER_ICON_BUTTON_CLASSES
              }
            )
          ] })
        ] }),
        !isMinimized && /* @__PURE__ */ jsxs3("div", { className: "flex flex-1 overflow-hidden border-t border-background-200", children: [
          showHistory && /* @__PURE__ */ jsx5("div", { className: "w-44 shrink-0 border-r border-background-200", children: historySlot }),
          /* @__PURE__ */ jsxs3("div", { className: "flex flex-1 flex-col", children: [
            messagesSlot,
            errorMessage && /* @__PURE__ */ jsx5(
              "div",
              {
                role: "alert",
                "aria-live": "assertive",
                className: "border-t border-error-200 bg-error-50 px-3 py-2",
                children: /* @__PURE__ */ jsx5(Text_default, { size: "xs", className: "text-error-700", children: errorMessage })
              }
            ),
            inputSlot
          ] })
        ] })
      ]
    }
  );
}

// src/components/Chatbot/ChatbotMessageList.tsx
import { useEffect as useEffect2, useRef as useRef2 } from "react";

// src/components/Chatbot/ChatbotMessage.tsx
import { RobotIcon as RobotIcon2, UserIcon } from "@phosphor-icons/react";

// src/components/Chatbot/ChatbotContentRenderer.tsx
import ReactMarkdown2 from "react-markdown";
import remarkGfm2 from "remark-gfm";

// src/components/HtmlMathRenderer/HtmlMathRenderer.tsx
import { forwardRef as forwardRef4, memo as memo2 } from "react";
import "katex/dist/katex.min.css";

// src/components/HtmlMathRenderer/KatexMath.tsx
import katex from "katex";
import { Fragment as Fragment2, jsx as jsx6 } from "react/jsx-runtime";
var KatexMath = ({
  math,
  displayMode = false,
  renderError
}) => {
  let html;
  try {
    html = katex.renderToString(math, {
      displayMode,
      throwOnError: true
    });
  } catch (error_) {
    return /* @__PURE__ */ jsx6(Fragment2, { children: renderError ? renderError(error_) : null });
  }
  const Tag = displayMode ? "div" : "span";
  return /* @__PURE__ */ jsx6(
    Tag,
    {
      "data-testid": "react-katex",
      dangerouslySetInnerHTML: { __html: html }
    }
  );
};

// src/components/MarkdownMathRenderer/MarkdownMathRenderer.tsx
import { forwardRef as forwardRef3, memo } from "react";
import "katex/dist/katex.min.css";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import rehypeKatex from "rehype-katex";

// src/components/HtmlMathRenderer/utils.ts
var generateSecureRandomId = () => {
  return crypto.randomUUID();
};
var cleanLatex = (str) => {
  return str.replaceAll(/[\u200B-\u200D\uFEFF]/g, "").replaceAll(/&amp;lt;|&lt;/gi, String.raw`\lt `).replaceAll(/&amp;gt;|&gt;/gi, String.raw`\gt `).replaceAll(/&amp;amp;|&amp;/gi, "&").trim();
};
var looksLikeLatex = (str) => {
  if (/[\\^_{}]/.test(str)) return true;
  const words = str.match(/[a-zA-Z]{3,}/g);
  if (words && words.length >= 2) return false;
  return true;
};
var HTML_TAG_NAMES = /* @__PURE__ */ new Set([
  "p",
  "div",
  "span",
  "br",
  "b",
  "strong",
  "i",
  "em",
  "u",
  "s",
  "ul",
  "ol",
  "li",
  "h1",
  "h2",
  "h3",
  "h4",
  "h5",
  "h6",
  "a",
  "img",
  "table",
  "thead",
  "tbody",
  "tfoot",
  "tr",
  "td",
  "th",
  "blockquote",
  "pre",
  "code",
  "sub",
  "sup",
  "font",
  "latex"
]);
var containsHtmlTag = (content) => {
  for (const match of content.matchAll(/<\/?([a-z][a-z0-9]*)/gi)) {
    if (HTML_TAG_NAMES.has(match[1].toLowerCase())) return true;
  }
  return false;
};
var isLikelyMarkdown = (content) => {
  if (!content) return false;
  if (containsHtmlTag(content)) return false;
  const MARKDOWN_SIGNALS = [
    /^#{1,6}[ \t]+\S/m,
    // ATX heading (#, ##, ... ######)
    /\*\*[^*\n]+\*\*/,
    // bold
    /__[^_\n]+__/,
    // bold (underscore)
    /^[ \t]*[-*+][ \t]+\S/m,
    // bullet list
    /^[ \t]*\d+\.[ \t]+\S/m,
    // ordered list
    /\|[ \t]*:?-+:?[ \t]*\|/,
    // GFM table delimiter row (|---|---|)
    /\n\n/
    // paragraph break (only reached when no HTML tag is present)
  ];
  return MARKDOWN_SIGNALS.some((pattern) => pattern.test(content));
};
var recoverFromKatexErrorSpans = (htmlContent) => {
  if (typeof document === "undefined" || !/class="[^"]*katex-error/i.test(htmlContent)) {
    return htmlContent;
  }
  const tempContainer = document.createElement("div");
  tempContainer.innerHTML = htmlContent;
  const sanitizeRecoveredLatex = (raw) => raw.replaceAll(/[\u0300-\u036F]/g, "").replaceAll(/<\/?[a-zA-Z][a-zA-Z0-9]*\s*>?$/g, "").replaceAll(/&amp;lt;|&lt;|</gi, String.raw`\lt `).replaceAll(/&amp;gt;|&gt;|>/gi, String.raw`\gt `).replaceAll(/&amp;amp;|&amp;/gi, "&").trim();
  Array.from(tempContainer.querySelectorAll(".katex-error")).forEach(
    (errorNode) => {
      if (!tempContainer.contains(errorNode)) return;
      const title = errorNode.getAttribute("title") || "";
      const positionMatch = /at position\s+\d+:(.+)$/.exec(title);
      let recovered = positionMatch ? positionMatch[1] : "";
      if (!recovered) {
        const parts = [];
        const walk = (n) => {
          if (n.nodeType === Node.TEXT_NODE) {
            parts.push(n.textContent || "");
            return;
          }
          if (n.nodeType !== Node.ELEMENT_NODE) return;
          const el = n;
          if (el.tagName.toLowerCase() === "annotation") {
            parts.push(el.textContent || "");
            return;
          }
          if (el.classList.contains("katex-html")) return;
          Array.from(el.childNodes).forEach(walk);
        };
        Array.from(errorNode.childNodes).forEach(walk);
        recovered = parts.join(" ");
      }
      recovered = sanitizeRecoveredLatex(recovered);
      if (recovered) {
        errorNode.replaceWith(document.createTextNode(`$${recovered}$`));
      } else {
        errorNode.remove();
      }
    }
  );
  return tempContainer.innerHTML;
};
var decodeDollarEscapes = (text) => text.replaceAll(String.raw`\$`, "$");
var DANGEROUS_ATTRIBUTES = /* @__PURE__ */ new Set([
  "contenteditable",
  "srcdoc",
  "formaction",
  "xlink:href"
]);
var DANGEROUS_URI_PATTERN = /^\s*(javascript|vbscript|data):/i;
var sanitizeHtmlForDisplay = (htmlContent) => {
  if (!htmlContent) return htmlContent;
  if (typeof document === "undefined") {
    let sanitized = htmlContent;
    sanitized = sanitized.replaceAll(
      /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
      ""
    );
    sanitized = sanitized.replaceAll(
      /<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,
      ""
    );
    sanitized = sanitized.replaceAll(/ on[a-z]+="[^"]*"/gi, "");
    sanitized = sanitized.replaceAll(/ on[a-z]+='[^']*'/gi, "");
    sanitized = sanitized.replaceAll(/ on[a-z]+=[^\s>"']+/gi, "");
    sanitized = sanitized.replaceAll(
      / href="(?:javascript|vbscript|data):[^"]*"/gi,
      ""
    );
    sanitized = sanitized.replaceAll(
      / href='(?:javascript|vbscript|data):[^']*'/gi,
      ""
    );
    sanitized = sanitized.replaceAll(
      / src="(?:javascript|vbscript|data):[^"]*"/gi,
      ""
    );
    sanitized = sanitized.replaceAll(
      / src='(?:javascript|vbscript|data):[^']*'/gi,
      ""
    );
    sanitized = sanitized.replaceAll(
      / action="(?:javascript|vbscript|data):[^"]*"/gi,
      ""
    );
    sanitized = sanitized.replaceAll(
      / action='(?:javascript|vbscript|data):[^']*'/gi,
      ""
    );
    return sanitized;
  }
  const tempDiv = document.createElement("div");
  tempDiv.innerHTML = htmlContent;
  const dangerousTags = tempDiv.querySelectorAll(
    "script, style, iframe, object, embed"
  );
  dangerousTags.forEach((element) => element.remove());
  const allElements = tempDiv.querySelectorAll("*");
  allElements.forEach((element) => {
    const attributeNames = element.getAttributeNames();
    attributeNames.forEach((attrName) => {
      const lowerAttrName = attrName.toLowerCase();
      if (lowerAttrName.startsWith("on")) {
        element.removeAttribute(attrName);
        return;
      }
      if (DANGEROUS_ATTRIBUTES.has(lowerAttrName)) {
        element.removeAttribute(attrName);
        return;
      }
      if (lowerAttrName === "href" || lowerAttrName === "src" || lowerAttrName === "action") {
        const value = element.getAttribute(attrName);
        if (value && DANGEROUS_URI_PATTERN.test(value)) {
          element.removeAttribute(attrName);
        }
      }
    });
  });
  return tempDiv.innerHTML;
};
var processHtmlWithMath = (htmlContent) => {
  if (!htmlContent) return [];
  let processedContent = recoverFromKatexErrorSpans(htmlContent);
  const parts = [];
  const sentinel = `__MATH_${generateSecureRandomId()}_`;
  const mathFormulaPattern = /<span[^>]*class="math-formula"[^>]*data-latex="([^"]*)"[^>]*>[\s\S]*?<\/span>/g;
  processedContent = processedContent.replaceAll(
    mathFormulaPattern,
    (match2, latex) => {
      const isDisplayMode = match2.includes('data-display-mode="true"');
      const placeholder = `${sentinel}${parts.length}__`;
      parts.push({
        type: isDisplayMode ? "block-math" : "math",
        content: match2,
        latex: cleanLatex(latex)
      });
      return placeholder;
    }
  );
  const wrappedMathPattern = /<span[^>]*class="math-expression"[^>]*data-math="([^"]*)"[^>]*>.*?<\/span>/g;
  processedContent = processedContent.replaceAll(
    wrappedMathPattern,
    (match2, latex) => {
      const placeholder = `${sentinel}${parts.length}__`;
      parts.push({
        type: "math",
        content: match2,
        latex: cleanLatex(latex)
      });
      return placeholder;
    }
  );
  const doubleDollarPattern = /(?<!\\)\$\$([\s\S]+?)\$\$/g;
  processedContent = processedContent.replaceAll(
    doubleDollarPattern,
    (match2, latex) => {
      const placeholder = `${sentinel}${parts.length}__`;
      parts.push({
        type: "block-math",
        content: match2,
        latex: cleanLatex(latex)
      });
      return placeholder;
    }
  );
  const singleDollarPattern = /(?<!\\)\$([\s\S]+?)\$/g;
  processedContent = processedContent.replaceAll(
    singleDollarPattern,
    (match2, latex) => {
      if (!looksLikeLatex(latex)) return match2;
      const placeholder = `${sentinel}${parts.length}__`;
      parts.push({
        type: "math",
        content: match2,
        latex: cleanLatex(latex)
      });
      return placeholder;
    }
  );
  const latexTagPattern = /(?:<latex>|&lt;latex&gt;)([\s\S]*?)(?:<\/latex>|&lt;\/latex&gt;)/g;
  processedContent = processedContent.replaceAll(
    latexTagPattern,
    (match2, latex) => {
      const placeholder = `${sentinel}${parts.length}__`;
      parts.push({
        type: "math",
        content: match2,
        latex: cleanLatex(latex)
      });
      return placeholder;
    }
  );
  const latexEnvPattern = /\\begin\{([^}]+)\}([\s\S]*?)\\end\{\1\}/g;
  processedContent = processedContent.replaceAll(latexEnvPattern, (match2) => {
    const placeholder = `${sentinel}${parts.length}__`;
    parts.push({
      type: "block-math",
      content: match2,
      latex: cleanLatex(match2)
    });
    return placeholder;
  });
  const finalParts = [];
  let currentIndex = 0;
  const escapedSentinel = sentinel.replaceAll(
    /[.*+?^${}()|[\]\\]/g,
    String.raw`\$&`
  );
  const placeholderPattern = new RegExp(
    String.raw`${escapedSentinel}(\d+)__`,
    "g"
  );
  let match;
  while ((match = placeholderPattern.exec(processedContent)) !== null) {
    if (match.index > currentIndex) {
      finalParts.push({
        type: "text",
        content: decodeDollarEscapes(
          processedContent.slice(currentIndex, match.index)
        )
      });
    }
    const mathIndex = Number.parseInt(match[1], 10);
    if (parts[mathIndex]) {
      finalParts.push(parts[mathIndex]);
    }
    currentIndex = match.index + match[0].length;
  }
  if (currentIndex < processedContent.length) {
    finalParts.push({
      type: "text",
      content: decodeDollarEscapes(processedContent.slice(currentIndex))
    });
  }
  return finalParts;
};
var containsMath = (content) => {
  if (!content) return false;
  const patterns = [
    /\$\$[\s\S]+?\$\$/,
    // Display mode $$...$$
    /(?<!\\)\$[\s\S]+?\$/,
    // Inline mode $...$
    /<span[^>]*class="math-formula"/,
    // Editor spans
    /<span[^>]*class="math-expression"/,
    // Legacy spans
    /<latex>|&lt;latex&gt;/,
    // LaTeX tags
    /\\begin\{[^}]+\}/
    // LaTeX environments
  ];
  return patterns.some((pattern) => pattern.test(content));
};

// src/components/MarkdownMathRenderer/MarkdownMathRenderer.tsx
import { jsx as jsx7 } from "react/jsx-runtime";
var stripInvisibleChars = (str) => str.replaceAll(/[\u200B-\u200D\uFEFF]/g, "");
var protectCurrencyInlineMath = (markdown) => markdown.replaceAll(
  /(?<!\\)\$(?!\$)([^\n$]+?)(?<!\\)\$(?!\$)/g,
  (match, inner) => looksLikeLatex(inner) ? match : match.replaceAll("$", String.raw`\$`)
);
var reflowDisplayMath = (markdown) => markdown.replaceAll(
  /(?<!\$)\$\$(?!\$)([^\n]+?)\$\$(?!\$)/g,
  (_match, inner) => `

$$
${inner.trim()}
$$

`
);
var withProtectedCode = (markdown, transform) => {
  const stash = [];
  const tokenized = markdown.replaceAll(
    /```[\s\S]*?```|`[^`\n]*`/g,
    (segment) => {
      const token = `__CODE_SEG_${stash.length}__`;
      stash.push(segment);
      return token;
    }
  );
  return transform(tokenized).replaceAll(
    /__CODE_SEG_(\d+)__/g,
    (_match, index) => stash[Number(index)]
  );
};
var preprocessMarkdown = (content) => withProtectedCode(
  stripInvisibleChars(content),
  (safe) => reflowDisplayMath(protectCurrencyInlineMath(safe))
);
var MarkdownMathRenderer = forwardRef3(({ content, className, style, testId }, ref) => {
  const sharedClassName = cn(
    "leading-relaxed",
    // Paragraph spacing
    "[&_p]:my-2 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0",
    // Headings
    "[&_h1]:text-xl [&_h1]:font-bold [&_h1]:mt-3 [&_h1]:mb-2",
    "[&_h2]:text-lg [&_h2]:font-bold [&_h2]:mt-3 [&_h2]:mb-2",
    "[&_h3]:text-base [&_h3]:font-semibold [&_h3]:mt-2.5 [&_h3]:mb-1.5",
    "[&_h4]:text-base [&_h4]:font-semibold [&_h4]:mt-2.5 [&_h4]:mb-1.5",
    "[&_h5]:font-semibold [&_h6]:font-semibold",
    // Lists
    "[&_ul]:list-disc [&_ul]:pl-5 [&_ul]:my-2",
    "[&_ol]:list-decimal [&_ol]:pl-5 [&_ol]:my-2",
    "[&_li]:my-1 [&_li>ul]:my-1 [&_li>ol]:my-1",
    // Text formatting
    "[&_b]:font-bold [&_strong]:font-bold",
    "[&_i]:italic [&_em]:italic",
    "[&_u]:underline",
    "[&_blockquote]:border-l-4 [&_blockquote]:border-border-200 [&_blockquote]:pl-3 [&_blockquote]:text-text-700",
    "[&_code]:rounded [&_code]:bg-background-100 [&_code]:px-1 [&_code]:py-0.5 [&_code]:text-sm",
    // Hide the KaTeX MathML accessibility layer visually (still readable to
    // screen readers). Tailwind preflight overrides KaTeX's default clip
    // rule, so without this the MathML layer duplicates every formula as
    // raw text next to the visual render.
    "[&_.katex-mathml]:sr-only",
    // Display math spacing
    "[&_.katex-display]:my-2.5",
    // Tables (GFM)
    "[&_table]:border-collapse [&_table]:w-full [&_table]:my-2.5 [&_table]:table-auto",
    "[&_table_td]:border [&_table_td]:border-border-200 [&_table_td]:p-2 [&_table_td]:min-w-[50px] [&_table_td]:align-top",
    "[&_table_th]:border [&_table_th]:border-border-200 [&_table_th]:p-2 [&_table_th]:min-w-[50px] [&_table_th]:align-top [&_table_th]:bg-background-50 [&_table_th]:font-semibold",
    // Images and links
    "[&_img]:max-w-full [&_img]:h-auto [&_img]:rounded-md [&_img]:my-2",
    "[&_a]:text-primary-500 [&_a]:underline [&_a:hover]:text-primary-600",
    className
  );
  return /* @__PURE__ */ jsx7(
    "div",
    {
      ref,
      className: sharedClassName,
      style,
      "data-testid": testId,
      children: /* @__PURE__ */ jsx7(
        ReactMarkdown,
        {
          remarkPlugins: [remarkGfm, remarkMath],
          rehypePlugins: [rehypeKatex],
          children: preprocessMarkdown(content)
        }
      )
    }
  );
});
MarkdownMathRenderer.displayName = "MarkdownMathRenderer";
var MarkdownMathRenderer_default = memo(MarkdownMathRenderer);

// src/components/HtmlMathRenderer/HtmlMathRenderer.tsx
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
var HtmlMathRenderer = forwardRef4(
  ({
    content,
    className,
    style,
    sanitize = true,
    renderMathError,
    testId,
    inline = false
  }, ref) => {
    if (!inline && content && isLikelyMarkdown(content)) {
      return /* @__PURE__ */ jsx8(
        MarkdownMathRenderer_default,
        {
          ref,
          content,
          className,
          style,
          testId
        }
      );
    }
    const defaultErrorRenderer = (latex) => /* @__PURE__ */ jsxs4("span", { className: "text-error-600 text-sm", children: [
      "Math Error: ",
      latex
    ] });
    const errorRenderer = renderMathError || defaultErrorRenderer;
    const renderContent = () => {
      if (!content) return null;
      const processedContent = sanitize ? sanitizeHtmlForDisplay(content) : content;
      const parts = processHtmlWithMath(processedContent);
      if (parts.every((part) => part.type === "text")) {
        const joinedHtml = parts.map((part) => part.content).join("");
        const Element = inline ? "span" : "div";
        return /* @__PURE__ */ jsx8(
          Element,
          {
            dangerouslySetInnerHTML: {
              __html: joinedHtml || processedContent
            }
          }
        );
      }
      const getPartKey = (part, idx) => {
        const contentHash = (part.latex || part.content).slice(0, 20);
        return `${part.type}-${idx}-${contentHash}`;
      };
      return /* @__PURE__ */ jsx8(Fragment3, { children: parts.map((part, index) => {
        const key = getPartKey(part, index);
        if (part.type === "math" && part.latex) {
          return /* @__PURE__ */ jsx8(
            KatexMath,
            {
              math: part.latex,
              renderError: () => errorRenderer(part.latex)
            },
            key
          );
        } else if (part.type === "block-math" && part.latex) {
          if (inline) {
            return /* @__PURE__ */ jsx8(
              KatexMath,
              {
                math: part.latex,
                renderError: () => errorRenderer(part.latex)
              },
              key
            );
          }
          return /* @__PURE__ */ jsx8("div", { className: "my-2.5 text-center", children: /* @__PURE__ */ jsx8(
            KatexMath,
            {
              math: part.latex,
              displayMode: true,
              renderError: () => errorRenderer(part.latex)
            }
          ) }, key);
        } else {
          return /* @__PURE__ */ jsx8(
            "span",
            {
              dangerouslySetInnerHTML: { __html: part.content }
            },
            key
          );
        }
      }) });
    };
    const sharedClassName = cn(
      // Base styles
      "leading-relaxed",
      // Paragraph styles
      "[&_p]:mb-0",
      // Hide the KaTeX MathML accessibility layer visually (still readable
      // to screen readers). Tailwind preflight overrides the KaTeX default
      // `position: absolute; clip:...` rule, so the MathML layer ends up
      // duplicating every formula as raw text next to the visual render.
      "[&_.katex-mathml]:sr-only",
      // Table styles (only relevant for block mode, but harmless for inline)
      "[&_table]:border-collapse [&_table]:w-full [&_table]:my-2.5 [&_table]:table-auto",
      "[&_table_td]:border [&_table_td]:border-border-200 [&_table_td]:p-2 [&_table_td]:min-w-[50px] [&_table_td]:align-top",
      "[&_table_th]:border [&_table_th]:border-border-200 [&_table_th]:p-2 [&_table_th]:min-w-[50px] [&_table_th]:align-top [&_table_th]:bg-background-50 [&_table_th]:font-semibold",
      "[&_table_tr:nth-child(even)]:bg-background-50/50",
      "[&_table_tr:hover]:bg-background-100/50",
      // Image styles
      "[&_img]:max-w-full [&_img]:h-auto [&_img]:rounded-md [&_img]:my-2",
      // Link styles
      "[&_a]:text-primary-500 [&_a]:underline [&_a:hover]:text-primary-600",
      // Text formatting styles
      "[&_b]:font-bold [&_strong]:font-bold",
      "[&_i]:italic [&_em]:italic",
      "[&_u]:underline",
      className
    );
    if (inline) {
      return /* @__PURE__ */ jsx8(
        "span",
        {
          ref,
          className: sharedClassName,
          style,
          "data-testid": testId,
          children: renderContent()
        }
      );
    }
    return /* @__PURE__ */ jsx8(
      "div",
      {
        ref,
        className: sharedClassName,
        style,
        "data-testid": testId,
        children: renderContent()
      }
    );
  }
);
HtmlMathRenderer.displayName = "HtmlMathRenderer";
var HtmlMathRenderer_default = memo2(HtmlMathRenderer);

// src/components/Chatbot/ChatbotContentRenderer.tsx
import { jsx as jsx9 } from "react/jsx-runtime";
var MATH_CHAR_PATTERN = /[\\^_{}]/;
function collectDollarIndices(content) {
  const result = [];
  for (let i = 0; i < content.length; i++) {
    if (content[i] === "$" && content[i - 1] !== "\\") {
      result.push(i);
    }
  }
  return result;
}
function hasInlineMathSpan(content, indices) {
  for (let i = 0; i < indices.length; i++) {
    for (let j = i + 1; j < indices.length; j++) {
      const inner = content.slice(indices[i] + 1, indices[j]);
      if (inner.includes("\n")) break;
      if (MATH_CHAR_PATTERN.test(inner)) return true;
    }
  }
  return false;
}
function looksLikeMath(content) {
  if (!containsMath(content)) return false;
  if (/\$\$[\s\S]+?\$\$/.test(content)) return true;
  if (/\\begin\{[^}]+\}[\s\S]+?\\end\{[^}]+\}/.test(content)) return true;
  return hasInlineMathSpan(content, collectDollarIndices(content));
}
function ChatbotContentRenderer({
  content,
  className
}) {
  if (looksLikeMath(content)) {
    return /* @__PURE__ */ jsx9(
      HtmlMathRenderer_default,
      {
        content,
        className: cn("whitespace-pre-wrap break-words", className)
      }
    );
  }
  return /* @__PURE__ */ jsx9(
    "div",
    {
      className: cn(
        "prose prose-sm max-w-none break-words",
        // tighten prose defaults so the bubble feels compact
        "[&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
        className
      ),
      children: /* @__PURE__ */ jsx9(ReactMarkdown2, { remarkPlugins: [remarkGfm2], children: content })
    }
  );
}

// src/types/chatbot.ts
var CHATBOT_MESSAGE_ROLES = {
  USER: "user",
  ASSISTANT: "assistant"
};

// src/components/Chatbot/ChatbotMessage.tsx
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
function formatTimestamp(value) {
  const date = value instanceof Date ? value : new Date(value);
  if (Number.isNaN(date.getTime())) return "";
  return date.toLocaleTimeString("pt-BR", {
    hour: "2-digit",
    minute: "2-digit"
  });
}
function ChatbotMessage({
  message,
  className,
  contentClassName
}) {
  const isUser = message.role === CHATBOT_MESSAGE_ROLES.USER;
  return /* @__PURE__ */ jsxs5(
    "div",
    {
      className: cn(
        "flex w-full gap-2",
        isUser ? "justify-end" : "justify-start",
        className
      ),
      children: [
        !isUser && /* @__PURE__ */ jsx10(
          "div",
          {
            role: "img",
            "aria-label": "Mensagem do assistente",
            className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-primary-100 text-primary-600",
            children: /* @__PURE__ */ jsx10(RobotIcon2, { size: 18, weight: "fill", "aria-hidden": "true" })
          }
        ),
        /* @__PURE__ */ jsxs5(
          "div",
          {
            className: cn(
              "max-w-[80%] px-4 py-2",
              isUser ? "rounded-2xl rounded-br-md bg-background-200 text-text-900" : "rounded-2xl rounded-bl-md bg-background-100 text-text-900"
            ),
            children: [
              isUser ? /* @__PURE__ */ jsx10(Text_default, { size: "sm", className: "whitespace-pre-wrap break-words", children: message.content }) : /* @__PURE__ */ jsx10(
                ChatbotContentRenderer,
                {
                  content: message.content,
                  className: contentClassName
                }
              ),
              /* @__PURE__ */ jsx10(Text_default, { size: "2xs", className: "mt-1 block text-right text-text-700", children: formatTimestamp(message.createdAt) })
            ]
          }
        ),
        isUser && /* @__PURE__ */ jsx10(
          "div",
          {
            role: "img",
            "aria-label": "Sua mensagem",
            className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-primary-500 text-white",
            children: /* @__PURE__ */ jsx10(UserIcon, { size: 18, weight: "fill", "aria-hidden": "true" })
          }
        )
      ]
    }
  );
}

// src/components/Chatbot/ChatbotTypingIndicator.tsx
import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
function ChatbotTypingIndicator({
  className
}) {
  return /* @__PURE__ */ jsxs6(
    "output",
    {
      "aria-label": "Assistente digitando",
      className: cn(
        "inline-flex items-center gap-1 rounded-2xl rounded-bl-md bg-background-100 px-4 py-3",
        className
      ),
      children: [
        /* @__PURE__ */ jsx11(
          Text_default,
          {
            as: "span",
            className: "h-2 w-2 animate-bounce rounded-full bg-text-400 [animation-delay:-0.3s]"
          }
        ),
        /* @__PURE__ */ jsx11(
          Text_default,
          {
            as: "span",
            className: "h-2 w-2 animate-bounce rounded-full bg-text-400 [animation-delay:-0.15s]"
          }
        ),
        /* @__PURE__ */ jsx11(
          Text_default,
          {
            as: "span",
            className: "h-2 w-2 animate-bounce rounded-full bg-text-400"
          }
        )
      ]
    }
  );
}

// src/components/Chatbot/ChatbotMessageList.tsx
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
function ChatbotMessageList({
  messages,
  isSending = false,
  isLoading = false,
  emptyHint = "Comece a conversa enviando uma pergunta.",
  className
}) {
  const bottomRef = useRef2(null);
  const didMountRef = useRef2(false);
  useEffect2(() => {
    if (!didMountRef.current) {
      didMountRef.current = true;
      return;
    }
    if (bottomRef.current) {
      bottomRef.current.scrollIntoView({ behavior: "smooth", block: "end" });
    }
  }, [messages.length, isSending]);
  const showEmpty = !isLoading && messages.length === 0 && !isSending;
  return /* @__PURE__ */ jsxs7(
    "div",
    {
      role: "log",
      "aria-live": "polite",
      "aria-relevant": "additions",
      className: cn(
        "flex-1 overflow-y-auto p-4 space-y-3",
        "bg-background-50",
        className
      ),
      children: [
        showEmpty && /* @__PURE__ */ jsx12("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx12(Text_default, { size: "sm", className: "text-center text-text-400", children: emptyHint }) }),
        messages.map((msg) => /* @__PURE__ */ jsx12(ChatbotMessage, { message: msg }, msg.id)),
        isSending && /* @__PURE__ */ jsx12("div", { className: "flex justify-start", children: /* @__PURE__ */ jsx12(ChatbotTypingIndicator, {}) }),
        /* @__PURE__ */ jsx12("div", { ref: bottomRef })
      ]
    }
  );
}

// src/components/Chatbot/ChatbotInput.tsx
import { useCallback, useState as useState3 } from "react";
import { PaperPlaneTiltIcon } from "@phosphor-icons/react";

// src/components/TextArea/TextArea.tsx
import {
  forwardRef as forwardRef5,
  useState as useState2,
  useId,
  useEffect as useEffect3,
  useRef as useRef3,
  useImperativeHandle
} from "react";
import { WarningCircle } from "phosphor-react";
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
var SIZE_CLASSES2 = {
  small: {
    textarea: "h-24 text-sm",
    // 96px height, 14px font
    textSize: "sm"
  },
  medium: {
    textarea: "h-24 text-base",
    // 96px height, 16px font
    textSize: "md"
  },
  large: {
    textarea: "h-24 text-lg",
    // 96px height, 18px font
    textSize: "lg"
  },
  extraLarge: {
    textarea: "h-24 text-xl",
    // 96px height, 20px font
    textSize: "xl"
  }
};
var BASE_TEXTAREA_CLASSES = "w-full box-border p-3 bg-background border border-solid rounded-[4px] resize-none focus:outline-none font-roboto font-normal leading-[150%] placeholder:text-text-600 transition-all duration-200";
var STATE_CLASSES = {
  default: {
    base: "border-border-300 bg-background text-text-600",
    hover: "hover:border-border-400",
    focus: "focus:border-border-500"
  },
  hovered: {
    base: "border-border-400 bg-background text-text-600",
    hover: "",
    focus: "focus:border-border-500"
  },
  focused: {
    base: "border-2 border-primary-950 bg-background text-text-900",
    hover: "",
    focus: ""
  },
  invalid: {
    base: "border-2 border-red-700 bg-white text-gray-800",
    hover: "hover:border-red-700",
    focus: "focus:border-red-700"
  },
  disabled: {
    base: "border-border-300 bg-background text-text-600 cursor-not-allowed opacity-40",
    hover: "",
    focus: ""
  }
};
var TextArea = forwardRef5(
  ({
    label,
    size = "medium",
    state = "default",
    errorMessage,
    helperMessage,
    className = "",
    labelClassName = "",
    disabled,
    id,
    onChange,
    placeholder,
    required,
    showCharacterCount = false,
    maxLength,
    value,
    autoResize = false,
    minHeight = 96,
    ...props
  }, ref) => {
    const generatedId = useId();
    const inputId = id ?? `textarea-${generatedId}`;
    const internalRef = useRef3(null);
    useImperativeHandle(ref, () => internalRef.current);
    const [isFocused, setIsFocused] = useState2(false);
    const currentLength = typeof value === "string" ? value.length : 0;
    const isNearLimit = maxLength && currentLength >= maxLength * 0.8;
    useEffect3(() => {
      if (autoResize && internalRef.current) {
        const textarea = internalRef.current;
        textarea.style.height = "auto";
        textarea.style.height = `${Math.max(textarea.scrollHeight, minHeight)}px`;
      }
    }, [autoResize, minHeight, value]);
    const handleChange = (event) => {
      onChange?.(event);
    };
    const handleFocus = (event) => {
      setIsFocused(true);
      props.onFocus?.(event);
    };
    const handleBlur = (event) => {
      setIsFocused(false);
      props.onBlur?.(event);
    };
    let currentState = disabled ? "disabled" : state;
    if (isFocused && currentState !== "invalid" && currentState !== "disabled") {
      currentState = "focused";
    }
    const sizeClasses = SIZE_CLASSES2[size];
    const stateClasses = STATE_CLASSES[currentState];
    const heightClasses = autoResize ? "h-auto overflow-hidden" : sizeClasses.textarea;
    const fontSizeClass = sizeClasses.textarea.split(" ").find((c) => c.startsWith("text-")) ?? "text-base";
    const textareaClasses = cn(
      BASE_TEXTAREA_CLASSES,
      autoResize ? fontSizeClass : sizeClasses.textarea,
      heightClasses,
      stateClasses.base,
      stateClasses.hover,
      stateClasses.focus,
      className
    );
    return /* @__PURE__ */ jsxs8("div", { className: `flex flex-col`, children: [
      label && /* @__PURE__ */ jsxs8(
        Text_default,
        {
          as: "label",
          htmlFor: inputId,
          size: sizeClasses.textSize,
          weight: "medium",
          color: "text-text-950",
          className: cn("mb-1.5", labelClassName),
          children: [
            label,
            " ",
            required && /* @__PURE__ */ jsx13("span", { className: "text-indicator-error", children: "*" })
          ]
        }
      ),
      /* @__PURE__ */ jsx13(
        "textarea",
        {
          ref: internalRef,
          id: inputId,
          disabled,
          onChange: handleChange,
          onFocus: handleFocus,
          onBlur: handleBlur,
          className: textareaClasses,
          placeholder,
          required,
          maxLength,
          value,
          ...props
        }
      ),
      errorMessage && /* @__PURE__ */ jsxs8("p", { className: "flex gap-1 items-center text-sm text-indicator-error mt-1.5", children: [
        /* @__PURE__ */ jsx13(WarningCircle, { size: 16 }),
        " ",
        errorMessage
      ] }),
      !errorMessage && showCharacterCount && maxLength && /* @__PURE__ */ jsxs8(
        Text_default,
        {
          size: "sm",
          weight: "normal",
          className: `mt-1.5 ${isNearLimit ? "text-indicator-warning" : "text-text-500"}`,
          children: [
            currentLength,
            "/",
            maxLength,
            " caracteres"
          ]
        }
      ),
      !errorMessage && helperMessage && !(showCharacterCount && maxLength) && /* @__PURE__ */ jsx13(Text_default, { size: "sm", weight: "normal", className: "mt-1.5 text-text-500", children: helperMessage })
    ] });
  }
);
TextArea.displayName = "TextArea";
var TextArea_default = TextArea;

// src/components/Chatbot/ChatbotInput.tsx
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
var MIN_HEIGHT = 40;
var MAX_HEIGHT = 120;
function ChatbotInput({
  onSend,
  disabled = false,
  placeholder = "Pergunte ao assistente...",
  className
}) {
  const [value, setValue] = useState3("");
  const submit = useCallback(() => {
    const trimmed = value.trim();
    if (!trimmed || disabled) return;
    onSend(trimmed);
    setValue("");
  }, [disabled, onSend, value]);
  const handleKeyDown = useCallback(
    (e) => {
      if (e.nativeEvent.isComposing) return;
      if (e.key === "Enter" && !e.shiftKey) {
        e.preventDefault();
        submit();
      }
    },
    [submit]
  );
  const isSendDisabled = disabled || value.trim().length === 0;
  return /* @__PURE__ */ jsxs9(
    "div",
    {
      className: cn(
        "flex items-center gap-2 border-t border-background-200 bg-background p-3",
        className
      ),
      children: [
        /* @__PURE__ */ jsx14("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx14(
          TextArea_default,
          {
            value,
            onChange: (e) => setValue(e.target.value),
            onKeyDown: handleKeyDown,
            placeholder,
            disabled,
            autoResize: true,
            minHeight: MIN_HEIGHT,
            "aria-label": "Mensagem para o assistente",
            className: "w-full",
            style: { maxHeight: MAX_HEIGHT, overflowY: "auto" }
          }
        ) }),
        /* @__PURE__ */ jsx14(
          Button_default,
          {
            variant: "raw",
            type: "button",
            onClick: submit,
            disabled: isSendDisabled,
            "aria-label": "Enviar mensagem",
            className: cn(
              "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full",
              "bg-primary-500 text-white transition-colors",
              "hover:bg-primary-600",
              "disabled:bg-background-200 disabled:text-text-500 disabled:cursor-not-allowed",
              "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-300"
            ),
            children: /* @__PURE__ */ jsx14(PaperPlaneTiltIcon, { size: 20, weight: "fill" })
          }
        )
      ]
    }
  );
}

// src/components/Chatbot/ChatbotConversationList.tsx
import { TrashIcon, PlusIcon as PlusIcon2 } from "@phosphor-icons/react";

// src/components/EmptyState/EmptyState.tsx
import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
var EmptyState = ({
  image,
  title,
  description,
  buttonText,
  buttonIcon,
  onButtonClick,
  buttonVariant = "solid",
  buttonAction = "primary",
  size = "large"
}) => {
  const displayTitle = title || "Nenhum dado dispon\xEDvel";
  const displayDescription = description || "N\xE3o h\xE1 dados para exibir no momento.";
  const titleClassName = size === "compact" ? "text-text-600 text-sm font-semibold text-center" : "text-text-950 text-3xl font-semibold text-center";
  const descriptionClassName = size === "compact" ? "text-text-600 text-sm font-normal text-center" : "text-text-600 text-[18px] font-normal text-center";
  const containerMinHeight = size === "compact" ? "min-h-0" : "min-h-[705px]";
  return /* @__PURE__ */ jsxs10(
    "div",
    {
      className: `flex flex-col justify-center items-center gap-6 w-full ${containerMinHeight} bg-background rounded-xl p-6`,
      children: [
        image && /* @__PURE__ */ jsx15("div", { className: "max-w-[170px] max-h-[150px] flex items-center justify-center", children: typeof image === "string" ? /* @__PURE__ */ jsx15(
          "img",
          {
            src: image,
            alt: displayTitle,
            className: "w-full h-full max-w-[170px] max-h-[150px]"
          }
        ) : /* @__PURE__ */ jsx15("div", { className: "w-[170px] h-[150px] flex items-center justify-center", children: image }) }),
        /* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-center gap-4 w-full max-w-[600px] px-6", children: [
          /* @__PURE__ */ jsx15(Text_default, { as: "h2", className: titleClassName, children: displayTitle }),
          /* @__PURE__ */ jsx15(Text_default, { className: descriptionClassName, children: displayDescription })
        ] }),
        buttonText && onButtonClick && /* @__PURE__ */ jsx15(
          Button_default,
          {
            variant: buttonVariant,
            action: buttonAction,
            size: "large",
            onClick: onButtonClick,
            iconLeft: buttonIcon,
            className: "rounded-full px-5 py-2.5",
            children: buttonText
          }
        )
      ]
    }
  );
};
var EmptyState_default = EmptyState;

// src/components/Skeleton/Skeleton.tsx
import { forwardRef as forwardRef6 } from "react";
import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
var SKELETON_ANIMATION_CLASSES = {
  pulse: "animate-pulse",
  none: ""
};
var SKELETON_VARIANT_CLASSES = {
  text: "h-4 bg-background-200 rounded",
  circular: "bg-background-200 rounded-full",
  rectangular: "bg-background-200",
  rounded: "bg-background-200 rounded-lg"
};
var SPACING_CLASSES = {
  none: "",
  small: "space-y-1",
  medium: "space-y-2",
  large: "space-y-3"
};
var Skeleton = forwardRef6(
  ({
    variant = "text",
    width,
    height,
    animation = "pulse",
    lines = 1,
    spacing = "none",
    className = "",
    children,
    ...props
  }, ref) => {
    const animationClass = SKELETON_ANIMATION_CLASSES[animation];
    const variantClass = SKELETON_VARIANT_CLASSES[variant];
    const spacingClass = SPACING_CLASSES[spacing];
    const style = {
      width: typeof width === "number" ? `${width}px` : width,
      height: typeof height === "number" ? `${height}px` : height
    };
    if (variant === "text" && lines > 1) {
      return /* @__PURE__ */ jsx16(
        "div",
        {
          ref,
          className: cn("flex flex-col", spacingClass, className),
          ...props,
          children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx16(
            "div",
            {
              className: cn(variantClass, animationClass),
              style: index === lines - 1 ? { width: "60%" } : void 0
            },
            index
          ))
        }
      );
    }
    return /* @__PURE__ */ jsx16(
      "div",
      {
        ref,
        className: cn(variantClass, animationClass, className),
        style,
        ...props,
        children
      }
    );
  }
);
var SkeletonText = forwardRef6(
  (props, ref) => /* @__PURE__ */ jsx16(Skeleton, { ref, variant: "text", ...props })
);
var SkeletonCircle = forwardRef6((props, ref) => /* @__PURE__ */ jsx16(Skeleton, { ref, variant: "circular", ...props }));
var SkeletonRectangle = forwardRef6((props, ref) => /* @__PURE__ */ jsx16(Skeleton, { ref, variant: "rectangular", ...props }));
var SkeletonRounded = forwardRef6((props, ref) => /* @__PURE__ */ jsx16(Skeleton, { ref, variant: "rounded", ...props }));
var SkeletonCard = forwardRef6(
  ({
    showAvatar = true,
    showTitle = true,
    showDescription = true,
    showActions = true,
    lines = 2,
    className = "",
    ...props
  }, ref) => {
    return /* @__PURE__ */ jsxs11(
      "div",
      {
        ref,
        className: cn(
          "w-full p-4 bg-background border border-border-200 rounded-lg",
          className
        ),
        ...props,
        children: [
          /* @__PURE__ */ jsxs11("div", { className: "flex items-start space-x-3", children: [
            showAvatar && /* @__PURE__ */ jsx16(SkeletonCircle, { width: 40, height: 40 }),
            /* @__PURE__ */ jsxs11("div", { className: "flex-1 space-y-2", children: [
              showTitle && /* @__PURE__ */ jsx16(SkeletonText, { width: "60%", height: 20 }),
              showDescription && /* @__PURE__ */ jsx16(SkeletonText, { lines, spacing: "small" })
            ] })
          ] }),
          showActions && /* @__PURE__ */ jsxs11("div", { className: "flex justify-end space-x-2 mt-4", children: [
            /* @__PURE__ */ jsx16(SkeletonRectangle, { width: 80, height: 32 }),
            /* @__PURE__ */ jsx16(SkeletonRectangle, { width: 80, height: 32 })
          ] })
        ]
      }
    );
  }
);
var SkeletonList = forwardRef6(
  ({
    items = 3,
    showAvatar = true,
    showTitle = true,
    showDescription = true,
    lines = 1,
    className = "",
    ...props
  }, ref) => {
    return /* @__PURE__ */ jsx16("div", { ref, className: cn("space-y-3", className), ...props, children: Array.from({ length: items }, (_, index) => /* @__PURE__ */ jsxs11("div", { className: "flex items-start space-x-3 p-3", children: [
      showAvatar && /* @__PURE__ */ jsx16(SkeletonCircle, { width: 32, height: 32 }),
      /* @__PURE__ */ jsxs11("div", { className: "flex-1 space-y-2", children: [
        showTitle && /* @__PURE__ */ jsx16(SkeletonText, { width: "40%", height: 16 }),
        showDescription && /* @__PURE__ */ jsx16(SkeletonText, { lines, spacing: "small" })
      ] })
    ] }, index)) });
  }
);
var SkeletonTable = forwardRef6(
  ({ rows = 5, columns = 4, showHeader = true, className = "", ...props }, ref) => {
    return /* @__PURE__ */ jsxs11("div", { ref, className: cn("w-full", className), ...props, children: [
      showHeader && /* @__PURE__ */ jsx16("div", { className: "flex space-x-2 mb-3", children: Array.from({ length: columns }, (_, index) => /* @__PURE__ */ jsx16(
        SkeletonText,
        {
          width: `${100 / columns}%`,
          height: 20
        },
        index
      )) }),
      /* @__PURE__ */ jsx16("div", { className: "space-y-2", children: Array.from({ length: rows }, (_, rowIndex) => /* @__PURE__ */ jsx16("div", { className: "flex space-x-2", children: Array.from({ length: columns }, (_2, colIndex) => /* @__PURE__ */ jsx16(
        SkeletonText,
        {
          width: `${100 / columns}%`,
          height: 16
        },
        colIndex
      )) }, rowIndex)) })
    ] });
  }
);

// src/components/Chatbot/ChatbotConversationList.tsx
import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
function formatDate(value) {
  const d = value instanceof Date ? value : new Date(value);
  if (Number.isNaN(d.getTime())) return "";
  return d.toLocaleDateString("pt-BR", {
    day: "2-digit",
    month: "2-digit"
  });
}
function ChatbotConversationList({
  conversations,
  activeConversationId,
  isLoading = false,
  onSelect,
  onDelete,
  onStartNew,
  className
}) {
  return /* @__PURE__ */ jsxs12(
    "div",
    {
      className: cn(
        "flex h-full flex-col border-r border-background-200 bg-background",
        className
      ),
      children: [
        /* @__PURE__ */ jsx17("div", { className: "p-3", children: /* @__PURE__ */ jsx17(
          Button_default,
          {
            variant: "solid",
            action: "primary",
            size: "small",
            onClick: onStartNew,
            iconLeft: /* @__PURE__ */ jsx17(PlusIcon2, { size: 14 }),
            className: "w-full",
            children: "Nova conversa"
          }
        ) }),
        /* @__PURE__ */ jsx17("div", { className: "flex-1 overflow-y-auto px-2 pb-2", children: renderBody() })
      ]
    }
  );
  function renderBody() {
    if (isLoading) {
      return /* @__PURE__ */ jsxs12("div", { className: "space-y-2 px-2", children: [
        /* @__PURE__ */ jsx17(SkeletonText, {}),
        /* @__PURE__ */ jsx17(SkeletonText, {}),
        /* @__PURE__ */ jsx17(SkeletonText, {})
      ] });
    }
    if (conversations.length === 0) {
      return /* @__PURE__ */ jsx17("div", { className: "mt-4", children: /* @__PURE__ */ jsx17(
        EmptyState_default,
        {
          title: "Sem conversas ainda",
          description: "Comece sua primeira conversa com o assistente."
        }
      ) });
    }
    return /* @__PURE__ */ jsx17("ul", { className: "space-y-1", children: conversations.map((c) => {
      const isActive = c.id === activeConversationId;
      return /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsxs12(
        "div",
        {
          className: cn(
            "group flex items-start gap-2 rounded-md px-2 py-2 transition-colors",
            isActive ? "bg-primary-50" : "hover:bg-background-100"
          ),
          children: [
            /* @__PURE__ */ jsxs12(
              Button_default,
              {
                variant: "raw",
                onClick: () => onSelect(c.id),
                className: "flex-1 text-left",
                children: [
                  /* @__PURE__ */ jsx17(
                    Text_default,
                    {
                      size: "sm",
                      weight: "semibold",
                      className: "truncate text-text-900",
                      children: c.title || "Conversa sem t\xEDtulo"
                    }
                  ),
                  /* @__PURE__ */ jsx17(Text_default, { size: "2xs", className: "text-text-400", children: formatDate(c.lastMessageAt) })
                ]
              }
            ),
            /* @__PURE__ */ jsx17(
              IconButton_default,
              {
                size: "sm",
                "aria-label": `Excluir conversa ${c.title || ""}`.trim(),
                onClick: () => onDelete(c.id),
                icon: /* @__PURE__ */ jsx17(TrashIcon, { size: 14 })
              }
            )
          ]
        }
      ) }, c.id);
    }) });
  }
}

// src/hooks/useChatbot.ts
import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
var DEFAULT_CONVERSATIONS_PAGE_SIZE = 20;
var DEFAULT_MESSAGES_PAGE_SIZE = 50;
var placeholderCounter = 0;
function generatePlaceholderId() {
  const globalCrypto = globalThis.crypto;
  if (globalCrypto && typeof globalCrypto.randomUUID === "function") {
    return `pending-${globalCrypto.randomUUID()}`;
  }
  placeholderCounter += 1;
  return `pending-${Date.now()}-${placeholderCounter}`;
}
function replacePlaceholder(prev, placeholderId, result) {
  return [
    ...prev.filter((m) => m.id !== placeholderId),
    result.userMessage,
    result.assistantMessage
  ];
}
function removePlaceholder(prev, placeholderId) {
  return prev.filter((m) => m.id !== placeholderId);
}
function removeById(items, id) {
  return items.filter((item) => item.id !== id);
}
function toUserErrorMessage(_err, fallback) {
  return fallback;
}
function createUseChatbot(resolver) {
  const resolveClient = typeof resolver === "function" ? resolver : () => resolver;
  return function useChatbot() {
    const [isOpen, setIsOpen] = useState4(false);
    const [isSending, setIsSending] = useState4(false);
    const [isLoadingHistory, setIsLoadingHistory] = useState4(false);
    const [isLoadingMessages, setIsLoadingMessages] = useState4(false);
    const [errorMessage, setErrorMessage] = useState4(null);
    const [conversations, setConversations] = useState4(
      []
    );
    const [activeConversationId, setActiveConversationId] = useState4(null);
    const [messages, setMessages] = useState4([]);
    const apiClientRef = useRef4(resolveClient());
    apiClientRef.current = resolveClient();
    const mountedRef = useRef4(false);
    useEffect4(() => {
      mountedRef.current = true;
      return () => {
        mountedRef.current = false;
      };
    }, []);
    const conversationsSeqRef = useRef4(0);
    const messagesSeqRef = useRef4(0);
    const isSendingRef = useRef4(false);
    const invalidateMessagesLoad = () => {
      messagesSeqRef.current += 1;
      setIsLoadingMessages(false);
    };
    const loadConversations = useCallback2(async () => {
      const seq = ++conversationsSeqRef.current;
      setIsLoadingHistory(true);
      setErrorMessage(null);
      try {
        const result = await apiClientRef.current.listConversations({
          page: 1,
          limit: DEFAULT_CONVERSATIONS_PAGE_SIZE
        });
        if (!mountedRef.current || seq !== conversationsSeqRef.current) return;
        setConversations(result.conversations);
      } catch (err) {
        if (!mountedRef.current || seq !== conversationsSeqRef.current) return;
        setErrorMessage(toUserErrorMessage(err, "Falha ao carregar conversas"));
      } finally {
        if (mountedRef.current && seq === conversationsSeqRef.current) {
          setIsLoadingHistory(false);
        }
      }
    }, []);
    const loadMessages = useCallback2(async (conversationId) => {
      const seq = ++messagesSeqRef.current;
      setIsLoadingMessages(true);
      setErrorMessage(null);
      try {
        const result = await apiClientRef.current.getMessages(conversationId, {
          page: 1,
          limit: DEFAULT_MESSAGES_PAGE_SIZE
        });
        if (!mountedRef.current || seq !== messagesSeqRef.current) return;
        setMessages(result.messages);
      } catch (err) {
        if (!mountedRef.current || seq !== messagesSeqRef.current) return;
        setErrorMessage(toUserErrorMessage(err, "Falha ao carregar mensagens"));
      } finally {
        if (mountedRef.current && seq === messagesSeqRef.current) {
          setIsLoadingMessages(false);
        }
      }
    }, []);
    const openPanel = useCallback2(() => {
      setIsOpen(true);
      void loadConversations();
    }, [loadConversations]);
    const closePanel = useCallback2(() => {
      setIsOpen(false);
    }, []);
    const togglePanel = useCallback2(() => {
      setIsOpen((prev) => {
        if (!prev) void loadConversations();
        return !prev;
      });
    }, [loadConversations]);
    const selectConversation = useCallback2(
      (id) => {
        setActiveConversationId(id);
        if (id) {
          void loadMessages(id);
        } else {
          invalidateMessagesLoad();
          setMessages([]);
        }
      },
      [loadMessages]
    );
    const startNewConversation = useCallback2(() => {
      invalidateMessagesLoad();
      setActiveConversationId(null);
      setMessages([]);
    }, []);
    const sendMessage = useCallback2(
      async (text, currentContext) => {
        const trimmed = text.trim();
        if (!trimmed || isSendingRef.current) return;
        isSendingRef.current = true;
        const sendSeq = messagesSeqRef.current;
        const placeholderId = generatePlaceholderId();
        const placeholder = {
          id: placeholderId,
          conversationId: activeConversationId ?? "",
          role: CHATBOT_MESSAGE_ROLES.USER,
          content: trimmed,
          createdAt: /* @__PURE__ */ new Date()
        };
        setMessages((prev) => [...prev, placeholder]);
        setIsSending(true);
        setErrorMessage(null);
        try {
          const result = await apiClientRef.current.sendMessage({
            message: trimmed,
            conversationId: activeConversationId ?? void 0,
            currentContext
          });
          if (!mountedRef.current) return;
          if (sendSeq !== messagesSeqRef.current) {
            void loadConversations();
            return;
          }
          setMessages(
            (prev) => replacePlaceholder(prev, placeholderId, result)
          );
          setActiveConversationId(result.conversationId);
          void loadConversations();
        } catch (err) {
          if (!mountedRef.current) return;
          if (sendSeq !== messagesSeqRef.current) return;
          setMessages((prev) => removePlaceholder(prev, placeholderId));
          setErrorMessage(toUserErrorMessage(err, "Falha ao enviar mensagem"));
        } finally {
          isSendingRef.current = false;
          if (mountedRef.current) setIsSending(false);
        }
      },
      [activeConversationId, loadConversations]
    );
    const deleteConversation = useCallback2(
      async (id) => {
        setErrorMessage(null);
        try {
          await apiClientRef.current.deleteConversation(id);
          if (!mountedRef.current) return;
          setConversations((prev) => removeById(prev, id));
          if (activeConversationId === id) {
            invalidateMessagesLoad();
            setActiveConversationId(null);
            setMessages([]);
          }
        } catch (err) {
          if (!mountedRef.current) return;
          setErrorMessage(toUserErrorMessage(err, "Falha ao excluir conversa"));
        }
      },
      [activeConversationId]
    );
    return {
      isOpen,
      isSending,
      isLoadingHistory,
      isLoadingMessages,
      errorMessage,
      conversations,
      activeConversationId,
      messages,
      openPanel,
      closePanel,
      togglePanel,
      selectConversation,
      startNewConversation,
      sendMessage,
      deleteConversation,
      reloadConversations: loadConversations
    };
  };
}

// src/components/Chatbot/Chatbot.tsx
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
function Chatbot({
  apiClient,
  user,
  currentContext,
  fabClassName,
  panelClassName
}) {
  const apiClientRef = useRef5(apiClient);
  apiClientRef.current = apiClient;
  const boundHookRef = useRef5(null);
  boundHookRef.current ??= createUseChatbot(() => apiClientRef.current);
  const useBoundChatbot = boundHookRef.current;
  const {
    isOpen,
    isSending,
    isLoadingHistory,
    isLoadingMessages,
    errorMessage,
    conversations,
    activeConversationId,
    messages,
    togglePanel,
    closePanel,
    selectConversation,
    startNewConversation,
    sendMessage,
    deleteConversation
  } = useBoundChatbot();
  const firstName = user.name?.trim().split(/\s+/)[0];
  const emptyHint = firstName ? `Ol\xE1, ${firstName}! Como posso ajudar nos seus estudos?` : "Comece a conversa enviando uma pergunta.";
  const handleSend = (text) => {
    sendMessage(text, currentContext).catch(() => void 0);
  };
  return /* @__PURE__ */ jsxs13(Fragment4, { children: [
    !isOpen && /* @__PURE__ */ jsx18(
      ChatbotFab,
      {
        onClick: togglePanel,
        isOpen,
        className: fabClassName
      }
    ),
    /* @__PURE__ */ jsx18(
      ChatbotPanel,
      {
        isOpen,
        onClose: closePanel,
        onStartNew: startNewConversation,
        className: panelClassName,
        errorMessage,
        historySlot: /* @__PURE__ */ jsx18(
          ChatbotConversationList,
          {
            conversations,
            activeConversationId,
            isLoading: isLoadingHistory,
            onSelect: selectConversation,
            onDelete: deleteConversation,
            onStartNew: startNewConversation
          }
        ),
        messagesSlot: /* @__PURE__ */ jsx18(
          ChatbotMessageList,
          {
            messages,
            isSending,
            isLoading: isLoadingMessages,
            emptyHint
          }
        ),
        inputSlot: /* @__PURE__ */ jsx18(ChatbotInput, { onSend: handleSend, disabled: isSending })
      }
    )
  ] });
}
export {
  Chatbot as default
};
//# sourceMappingURL=index.mjs.map