import { getWebSocketBaseUrl, createLiveTempMessageIdentity, formatMessageEvent, WebSocketSessionTurnSchema, mergeSessionMessages } from '../../chunk-M7WWRZ5Z.js';
import { ChatInterface } from '../../chunk-E6NSKXYN.js';
import { WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, validateTokenLimit, TOKEN_LIMITS } from '../../chunk-FVOMKZ7S.js';
import '../../chunk-TVTSASST.js';
import '../../chunk-I2KLQ2HA.js';
import { Center, Loader, Paper, Stack, Group, Title, Alert, PasswordInput, Button, Text, Box, Badge, Divider } from '@mantine/core';
import { IconLock, IconAlertCircle, IconSend, IconMessageCircle } from '@tabler/icons-react';
import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { jsx, jsxs } from 'react/jsx-runtime';

// src/features/public-agent-chat/queryKeys.ts
var publicAgentChatKeys = {
  all: ["public-agent-chat"],
  messages: (sessionId) => [...publicAgentChatKeys.all, "messages", sessionId]
};

// src/features/public-agent-chat/usePublicAgentChatMessages.ts
function usePublicAgentChatMessages(apiUrl, sessionId, capabilityToken) {
  return useQuery({
    queryKey: [...publicAgentChatKeys.messages(sessionId ?? "pending"), apiUrl, capabilityToken],
    queryFn: async () => {
      if (!sessionId || !capabilityToken) return [];
      const response = await fetch(`${apiUrl}/api/public/agent-chat/sessions/${sessionId}/messages`, {
        method: "GET",
        headers: {
          Authorization: `Bearer ${capabilityToken}`
        }
      });
      if (!response.ok) {
        throw new Error("Failed to load public agent chat messages");
      }
      const payload = await response.json();
      return payload.messages.map(
        (message) => ({
          ...message,
          createdAt: message.createdAt ? new Date(message.createdAt) : /* @__PURE__ */ new Date()
        })
      );
    },
    enabled: !!apiUrl && !!sessionId && !!capabilityToken,
    staleTime: 0
  });
}
function usePublicAgentChatWebSocket(sessionId, apiUrl, capabilityToken) {
  const [messages, setMessages] = useState([]);
  const [state, setState] = useState({
    isConnected: false,
    isProcessing: false,
    error: null
  });
  const [lastTokenUsage, setLastTokenUsage] = useState(null);
  const wsRef = useRef(null);
  const retryCountRef = useRef(0);
  const reconnectTimeoutRef = useRef(null);
  const queryClient = useQueryClient();
  const sessionIdRef = useRef(sessionId);
  sessionIdRef.current = sessionId;
  const capabilityTokenRef = useRef(capabilityToken);
  capabilityTokenRef.current = capabilityToken;
  const queryClientRef = useRef(queryClient);
  queryClientRef.current = queryClient;
  const connect = useCallback(() => {
    const currentSessionId = sessionIdRef.current;
    const currentCapabilityToken = capabilityTokenRef.current;
    if (!currentSessionId || !currentCapabilityToken) {
      return;
    }
    if (wsRef.current?.readyState === WebSocket.OPEN || wsRef.current?.readyState === WebSocket.CONNECTING) {
      return;
    }
    const wsUrl = `${getWebSocketBaseUrl(apiUrl)}/api/public/ws/agent-chat/${currentSessionId}?token=${encodeURIComponent(currentCapabilityToken)}`;
    const ws = new WebSocket(wsUrl);
    ws.onopen = () => {
      setState((prev) => ({ ...prev, isConnected: true, error: null }));
      retryCountRef.current = 0;
      queryClientRef.current.invalidateQueries({
        queryKey: publicAgentChatKeys.messages(currentSessionId)
      });
    };
    ws.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);
        if (data.type && data.type !== "turn:complete" && data.type !== "error") {
          const liveIdentity = createLiveTempMessageIdentity();
          const tempMessage = {
            id: liveIdentity.id,
            role: data.type === "user_message" ? "user" : "assistant",
            messageType: data.type,
            text: formatMessageEvent(data),
            metadata: data.type.startsWith("agent:") ? data : void 0,
            turnNumber: 999999,
            messageIndex: liveIdentity.messageIndex,
            createdAt: liveIdentity.createdAt
          };
          setMessages((prev) => [...prev, tempMessage]);
        } else if (data.type === "turn:complete") {
          if (data.tokenUsage) {
            setLastTokenUsage(data.tokenUsage);
          }
          setState((prev) => ({ ...prev, isProcessing: false }));
          queryClientRef.current.invalidateQueries({
            queryKey: publicAgentChatKeys.messages(currentSessionId)
          });
        } else if (data.type === "error") {
          setState((prev) => ({
            ...prev,
            error: data.error,
            isProcessing: false
          }));
        }
      } catch {
        setState((prev) => ({ ...prev, error: "Failed to parse agent chat message" }));
      }
    };
    ws.onerror = () => {
    };
    ws.onclose = (event) => {
      setState((prev) => ({ ...prev, isConnected: false }));
      if (!event.wasClean && retryCountRef.current >= WS_MAX_RETRIES_BEFORE_ERROR) {
        setState((prev) => ({ ...prev, error: "Unable to connect to agent chat. Retrying..." }));
      }
      const terminalCodes = [1003, 1008];
      if (terminalCodes.includes(event.code) || event.code >= 4e3) {
        setState((prev) => ({
          ...prev,
          error: `Connection rejected (code ${event.code})`
        }));
        return;
      }
      const delay = Math.min(WS_RECONNECT_BASE_DELAY * Math.pow(2, retryCountRef.current), WS_RECONNECT_MAX_DELAY);
      retryCountRef.current += 1;
      reconnectTimeoutRef.current = setTimeout(connect, delay);
    };
    wsRef.current = ws;
  }, [apiUrl]);
  useEffect(() => {
    retryCountRef.current = 0;
    if (sessionId && capabilityToken) {
      connect();
    }
    return () => {
      if (reconnectTimeoutRef.current) {
        clearTimeout(reconnectTimeoutRef.current);
      }
      if (wsRef.current) {
        wsRef.current.close();
        wsRef.current = null;
      }
    };
  }, [sessionId, capabilityToken, connect]);
  const sendMessage = useCallback(
    (text) => {
      const trimmed = text.trim();
      if (!trimmed || state.isProcessing) {
        return;
      }
      if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
        setState((prev) => ({ ...prev, error: "WebSocket not connected" }));
        return;
      }
      const tokenValidation = validateTokenLimit(trimmed, {
        maxTokens: TOKEN_LIMITS.USER_MESSAGE
      });
      if (!tokenValidation.withinLimit) {
        setState((prev) => ({ ...prev, error: "Input too large" }));
        return;
      }
      const liveIdentity = createLiveTempMessageIdentity();
      const userMessage = {
        id: liveIdentity.id,
        role: "user",
        messageType: "user_message",
        text: trimmed,
        turnNumber: 999999,
        messageIndex: liveIdentity.messageIndex,
        createdAt: liveIdentity.createdAt
      };
      setMessages((prev) => [...prev, userMessage]);
      const message = WebSocketSessionTurnSchema.parse({
        type: "session:turn",
        input: { message: trimmed }
      });
      wsRef.current.send(JSON.stringify(message));
      setState((prev) => ({ ...prev, isProcessing: true, error: null }));
    },
    [state.isProcessing]
  );
  const clearError = useCallback(() => {
    setState((prev) => ({ ...prev, error: null }));
  }, []);
  return {
    messages,
    state,
    sendMessage,
    clearError,
    lastTokenUsage
  };
}
async function fetchJson(url, init) {
  const response = await fetch(url, init);
  if (!response.ok) {
    throw new Error(`Request failed with status ${response.status}`);
  }
  return await response.json();
}
function brandingRecord(value) {
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
}
function brandingText(value) {
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
}
function humanizeSlug(slug) {
  return slug.split(/[-_\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
}
function resolveAgentTitle(title, slug, grant) {
  const branding = brandingRecord(grant?.branding);
  return title ?? brandingText(branding.title) ?? brandingText(branding.displayName) ?? brandingText(branding.agentName) ?? brandingText(branding.name) ?? humanizeSlug(slug);
}
function resolveAgentSubtitle(grant) {
  const branding = brandingRecord(grant?.branding);
  return brandingText(branding.subtitle) ?? brandingText(branding.description);
}
function statusStyles(tone) {
  if (tone === "ready") {
    return {
      label: "Online",
      background: "color-mix(in srgb, var(--color-success) 14%, transparent)",
      color: "var(--color-success)",
      border: "1px solid color-mix(in srgb, var(--color-success) 26%, var(--color-border))"
    };
  }
  if (tone === "locked") {
    return {
      label: "Access required",
      background: "color-mix(in srgb, var(--color-warning) 14%, transparent)",
      color: "var(--color-warning)",
      border: "1px solid color-mix(in srgb, var(--color-warning) 26%, var(--color-border))"
    };
  }
  if (tone === "error") {
    return {
      label: "Unavailable",
      background: "color-mix(in srgb, var(--color-error) 14%, transparent)",
      color: "var(--color-error)",
      border: "1px solid color-mix(in srgb, var(--color-error) 28%, var(--color-border))"
    };
  }
  return {
    label: "Connecting",
    background: "color-mix(in srgb, var(--color-primary) 12%, transparent)",
    color: "var(--color-primary)",
    border: "1px solid color-mix(in srgb, var(--color-primary) 24%, var(--color-border))"
  };
}
function PublicAgentChatFrame({
  className,
  style,
  title,
  subtitle,
  statusTone,
  children
}) {
  const status = statusStyles(statusTone);
  return /* @__PURE__ */ jsxs(
    Box,
    {
      className,
      style: {
        height: "100%",
        minHeight: 560,
        display: "flex",
        flexDirection: "column",
        border: "1px solid var(--color-border)",
        borderRadius: 8,
        overflow: "hidden",
        background: "var(--glass-background)",
        backdropFilter: "var(--glass-blur)",
        WebkitBackdropFilter: "var(--glass-blur)",
        boxShadow: "var(--standard-box-shadow)",
        ...style
      },
      children: [
        /* @__PURE__ */ jsx(
          Box,
          {
            style: {
              flexShrink: 0,
              padding: "16px clamp(16px, 2.6vw, 24px)",
              background: "color-mix(in srgb, var(--color-surface) 82%, transparent)"
            },
            children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", gap: "md", wrap: "nowrap", children: [
              /* @__PURE__ */ jsxs(Group, { gap: "sm", align: "center", style: { minWidth: 0 }, children: [
                /* @__PURE__ */ jsx(
                  Center,
                  {
                    style: {
                      width: 40,
                      height: 40,
                      flexShrink: 0,
                      borderRadius: 8,
                      color: "var(--color-primary)",
                      background: "color-mix(in srgb, var(--color-primary) 14%, transparent)",
                      border: "1px solid color-mix(in srgb, var(--color-primary) 24%, var(--color-border))"
                    },
                    children: /* @__PURE__ */ jsx(IconMessageCircle, { size: 21 })
                  }
                ),
                /* @__PURE__ */ jsxs(Box, { style: { minWidth: 0 }, children: [
                  /* @__PURE__ */ jsx(
                    Title,
                    {
                      order: 1,
                      style: {
                        fontSize: "clamp(18px, 2vw, 24px)",
                        lineHeight: 1.15,
                        color: "var(--color-text)",
                        fontFamily: "var(--mantine-headings-font-family)",
                        overflow: "hidden",
                        textOverflow: "ellipsis",
                        whiteSpace: "nowrap"
                      },
                      children: title
                    }
                  ),
                  subtitle && /* @__PURE__ */ jsx(Text, { size: "sm", style: { color: "var(--color-text-dimmed)" }, lineClamp: 1, children: subtitle })
                ] })
              ] }),
              /* @__PURE__ */ jsx(
                Badge,
                {
                  variant: "outline",
                  size: "md",
                  style: {
                    flexShrink: 0,
                    background: status.background,
                    color: status.color,
                    border: status.border,
                    textTransform: "none",
                    letterSpacing: 0
                  },
                  children: status.label
                }
              )
            ] })
          }
        ),
        /* @__PURE__ */ jsx(Divider, { color: "var(--color-border)" }),
        /* @__PURE__ */ jsx(
          Box,
          {
            style: {
              flex: "1 1 auto",
              minHeight: 0,
              padding: "12px",
              display: "flex",
              flexDirection: "column",
              overflow: "hidden"
            },
            children
          }
        )
      ]
    }
  );
}
function PublicAgentChat({
  apiUrl,
  slug,
  visitorId,
  metadata,
  title,
  className,
  style,
  onSessionReady,
  showAgentActivity = false
}) {
  const [grant, setGrant] = useState(null);
  const [capabilityToken, setCapabilityToken] = useState(null);
  const [session, setSession] = useState(null);
  const [status, setStatus] = useState("loading");
  const [error, setError] = useState(null);
  const [accessCode, setAccessCode] = useState("");
  const [input, setInput] = useState("");
  const autoStartedRef = useRef(false);
  const displayTitle = resolveAgentTitle(title, slug, grant);
  const displaySubtitle = resolveAgentSubtitle(grant);
  const { data: historyMessages = [] } = usePublicAgentChatMessages(apiUrl, session?.sessionId ?? null, capabilityToken);
  const {
    messages: liveMessages,
    state,
    sendMessage,
    clearError
  } = usePublicAgentChatWebSocket(session?.sessionId ?? null, apiUrl, capabilityToken);
  useEffect(() => {
    let cancelled = false;
    autoStartedRef.current = false;
    setGrant(null);
    setCapabilityToken(null);
    setSession(null);
    setError(null);
    setStatus("loading");
    fetchJson(`${apiUrl}/api/public/agent-chat/${encodeURIComponent(slug)}`).then((payload) => {
      if (cancelled) return;
      setGrant(payload.grant);
      setStatus(payload.grant.requiresCode ? "code-required" : "authorizing");
    }).catch((requestError) => {
      if (cancelled) return;
      setError(requestError instanceof Error ? requestError.message : "Unable to load agent chat");
      setStatus("error");
    });
    return () => {
      cancelled = true;
    };
  }, [apiUrl, slug]);
  const startSession = useCallback(
    async (code) => {
      if (!grant) return;
      try {
        setError(null);
        setStatus("authorizing");
        const authorization = await fetchJson(
          `${apiUrl}/api/public/agent-chat/${encodeURIComponent(slug)}/authorize`,
          {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
              ...code ? { code } : {},
              ...visitorId ? { visitorId } : {}
            })
          }
        );
        setCapabilityToken(authorization.capabilityToken);
        const createdSession = await fetchJson(
          `${apiUrl}/api/public/agent-chat/${encodeURIComponent(slug)}/sessions`,
          {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
              capabilityToken: authorization.capabilityToken,
              ...metadata ? { metadata } : {}
            })
          }
        );
        setSession(createdSession);
        setCapabilityToken(createdSession.capabilityToken ?? authorization.capabilityToken);
        setStatus("ready");
        onSessionReady?.(createdSession);
      } catch (requestError) {
        setError(requestError instanceof Error ? requestError.message : "Unable to start agent chat");
        setStatus(grant.requiresCode ? "code-required" : "error");
      }
    },
    [apiUrl, grant, metadata, onSessionReady, slug, visitorId]
  );
  useEffect(() => {
    if (!grant || grant.requiresCode || autoStartedRef.current) {
      return;
    }
    autoStartedRef.current = true;
    void startSession();
  }, [grant, startSession]);
  const allMessages = useMemo(
    () => mergeSessionMessages(historyMessages, liveMessages),
    [historyMessages, liveMessages]
  );
  const handleSend = () => {
    const trimmed = input.trim();
    if (!trimmed || state.isProcessing) return;
    sendMessage(trimmed);
    setInput("");
  };
  if (status === "loading" || status === "authorizing") {
    return /* @__PURE__ */ jsx(
      PublicAgentChatFrame,
      {
        className,
        style,
        title: displayTitle,
        subtitle: displaySubtitle,
        statusTone: "loading",
        children: /* @__PURE__ */ jsx(Center, { style: { height: "100%" }, children: /* @__PURE__ */ jsx(Loader, { size: "md" }) })
      }
    );
  }
  if (status === "code-required") {
    return /* @__PURE__ */ jsx(
      PublicAgentChatFrame,
      {
        className,
        style,
        title: displayTitle,
        subtitle: displaySubtitle,
        statusTone: "locked",
        children: /* @__PURE__ */ jsx(Center, { style: { height: "100%", padding: 16 }, children: /* @__PURE__ */ jsx(
          Paper,
          {
            withBorder: true,
            p: "lg",
            radius: 8,
            style: {
              width: "min(100%, 420px)",
              background: "var(--color-surface)",
              borderColor: "var(--color-border)",
              boxShadow: "var(--card-shadow)"
            },
            children: /* @__PURE__ */ jsx(
              "form",
              {
                onSubmit: (event) => {
                  event.preventDefault();
                  void startSession(accessCode);
                },
                children: /* @__PURE__ */ jsxs(Stack, { children: [
                  /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
                    /* @__PURE__ */ jsx(IconLock, { size: 18 }),
                    /* @__PURE__ */ jsx(Title, { order: 2, size: "h4", children: "Access code" })
                  ] }),
                  error && /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), children: error }),
                  /* @__PURE__ */ jsx(
                    PasswordInput,
                    {
                      label: "Code",
                      value: accessCode,
                      onChange: (event) => setAccessCode(event.currentTarget.value),
                      autoComplete: "one-time-code",
                      required: true
                    }
                  ),
                  /* @__PURE__ */ jsx(Button, { type: "submit", leftSection: /* @__PURE__ */ jsx(IconSend, { size: 16 }), disabled: !accessCode.trim(), children: "Continue" })
                ] })
              }
            )
          }
        ) })
      }
    );
  }
  if (status === "error") {
    return /* @__PURE__ */ jsx(
      PublicAgentChatFrame,
      {
        className,
        style,
        title: displayTitle,
        subtitle: displaySubtitle,
        statusTone: "error",
        children: /* @__PURE__ */ jsx(Center, { style: { height: "100%", padding: 16 }, children: /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), title: displayTitle, children: /* @__PURE__ */ jsx(Text, { size: "sm", children: error ?? "Unable to load agent chat" }) }) })
      }
    );
  }
  return /* @__PURE__ */ jsx(
    PublicAgentChatFrame,
    {
      className,
      style,
      title: displayTitle,
      subtitle: displaySubtitle,
      statusTone: state.isConnected ? "ready" : "loading",
      children: /* @__PURE__ */ jsx(Box, { style: { flex: "1 1 auto", minHeight: 0, display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsx(
        ChatInterface,
        {
          messages: allMessages,
          input,
          onInputChange: setInput,
          onSendMessage: handleSend,
          style: { flex: "1 1 auto", minHeight: 0, height: "100%" },
          isProcessing: state.isProcessing,
          isConnected: state.isConnected,
          error: state.error,
          onClearError: clearError,
          emptyStateText: "No messages yet",
          emptyStateSubtext: "Send a message to start the conversation",
          placeholder: "Message the agent...",
          messageAreaVariant: "grid",
          showAgentActivity
        }
      ) })
    }
  );
}
function PublicAgentChatRoutePage({ pageStyle, style, ...props }) {
  return /* @__PURE__ */ jsx(
    Box,
    {
      style: {
        minHeight: "100vh",
        display: "flex",
        justifyContent: "center",
        alignItems: "stretch",
        padding: "clamp(16px, 3vw, 32px)",
        background: "var(--color-background)",
        color: "var(--color-text)",
        ...pageStyle
      },
      children: /* @__PURE__ */ jsx(
        PublicAgentChat,
        {
          ...props,
          style: {
            width: "min(100%, 980px)",
            height: "calc(100vh - clamp(32px, 6vw, 64px))",
            minHeight: 560,
            maxHeight: "920px",
            ...style
          }
        }
      )
    }
  );
}

export { PublicAgentChat, PublicAgentChatRoutePage, publicAgentChatKeys, usePublicAgentChatMessages, usePublicAgentChatWebSocket };
