
const WEBHOOK_URL     = "https://n8n-bgdp.srv1516287.hstgr.cloud/webhook/francisjoseph";
const INITIAL_MESSAGE = "Hello! This is Francis's AI Assistant. How may I help you today?";
const AVATAR          = "assets/cyborg.png";
const AVATAR_FOCUS    = "center 26%";

const CHAT_RATE_KEY   = "fj_chat_timestamps"; // sliding-window timestamps
const MAX_PER_WINDOW  = 15;   // max messages per 10-minute window
const WINDOW_MS       = 600_000;
const COOLDOWN_MS     = 2_000; // min ms between sends
const SESSION_LIMIT   = 50;   // hard cap per page-load session
const MAX_INPUT_LEN   = 500;

function isChatRateLimited() {
  const now = Date.now();
  let times = JSON.parse(localStorage.getItem(CHAT_RATE_KEY) || "[]");
  times = times.filter(t => now - t < WINDOW_MS);
  return times.length >= MAX_PER_WINDOW;
}

function recordChatMessage() {
  const now = Date.now();
  let times = JSON.parse(localStorage.getItem(CHAT_RATE_KEY) || "[]");
  times = times.filter(t => now - t < WINDOW_MS);
  times.push(now);
  localStorage.setItem(CHAT_RATE_KEY, JSON.stringify(times));
}

const ChatbotWidget = () => {
  const [isOpen, setIsOpen]           = React.useState(false);
  const [showBubble, setShowBubble]   = React.useState(false);
  const [messages, setMessages]       = React.useState([]);
  const [input, setInput]             = React.useState("");
  const [isLoading, setIsLoading]     = React.useState(false);
  const [isMobile, setIsMobile]       = React.useState(() => window.innerWidth <= 768);
  const messagesEndRef                = React.useRef(null);
  const lastSentAt                    = React.useRef(0);
  const sessionCount                  = React.useRef(0);

  React.useEffect(() => {
    const mediaQuery = window.matchMedia("(max-width: 768px)");
    const syncMobile = () => setIsMobile(mediaQuery.matches);
    syncMobile();
    mediaQuery.addEventListener("change", syncMobile);
    return () => mediaQuery.removeEventListener("change", syncMobile);
  }, []);

  // Auto-scroll to latest message
  React.useEffect(() => {
    if (messagesEndRef.current) {
      messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
    }
  }, [messages]);

  const openChat = () => {
    setIsOpen(true);
    setShowBubble(false);
    if (messages.length === 0) {
      setMessages([{ role: "bot", text: INITIAL_MESSAGE }]);
    }
  };

  const closeChat = () => setIsOpen(false);

  const dismissBubble = (e) => {
    e.stopPropagation();
    setShowBubble(false);
  };

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

    // Input length cap
    if (text.length > MAX_INPUT_LEN) {
      setMessages(prev => [...prev, { role: "bot", text: `Please keep messages under ${MAX_INPUT_LEN} characters.` }]);
      return;
    }

    // Session cap
    if (sessionCount.current >= SESSION_LIMIT) {
      setMessages(prev => [...prev, { role: "bot", text: "You've reached the session message limit. Feel free to email me at francisdanao55@gmail.com!" }]);
      return;
    }

    // Per-send cooldown
    const now = Date.now();
    if (now - lastSentAt.current < COOLDOWN_MS) return;

    // Sliding-window rate limit
    if (isChatRateLimited()) {
      setMessages(prev => [...prev, { role: "bot", text: "You're sending messages too quickly. Please wait a few minutes before trying again." }]);
      return;
    }

    lastSentAt.current = now;
    sessionCount.current += 1;
    recordChatMessage();

    setMessages(prev => [...prev, { role: "user", text }]);
    setInput("");
    setIsLoading(true);

    try {
      const res = await fetch(WEBHOOK_URL, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ message: text }),
      });
      const data = await res.json();
      const reply =
        data.reply || data.message || data.text || data.output ||
        (Array.isArray(data) && (data[0]?.reply || data[0]?.message || data[0]?.text || data[0]?.output)) ||
        "I received your message. I'll get back to you shortly!";
      setMessages(prev => [...prev, { role: "bot", text: reply }]);
    } catch {
      setMessages(prev => [...prev, { role: "bot", text: "Sorry, I'm having trouble connecting right now. Please try again shortly." }]);
    } finally {
      setIsLoading(false);
    }
  };

  const handleKeyDown = (e) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      sendMessage();
    }
  };

  return (
    <div style={{
      position: "fixed",
      bottom: isMobile ? 16 : 28,
      right: isMobile ? 16 : 28,
      left: isMobile && isOpen ? 16 : "auto",
      zIndex: 10000,
      display: "flex",
      flexDirection: "column",
      alignItems: "flex-end",
      gap: 12
    }}>

      {/* Notification bubble */}
      {showBubble && !isOpen && (
        <div
          onClick={openChat}
          style={{
            position: "relative", maxWidth: isMobile ? 220 : 260,
            background: "oklch(0.11 0.022 198)", border: "1px solid var(--teal)",
            borderRadius: "16px 16px 4px 16px",
            padding: "12px 36px 12px 16px",
            boxShadow: "0 4px 24px rgba(0,0,0,0.5), 0 0 16px oklch(0.65 0.16 185 / 0.2)",
            cursor: "pointer",
            animation: "fadeIn 0.4s ease",
          }}>
          <p style={{ fontFamily: "Montserrat, sans-serif", fontSize: 13, color: "var(--fg)", lineHeight: 1.5 }}>
            {INITIAL_MESSAGE}
          </p>
          <button
            onClick={dismissBubble}
            style={{
              position: "absolute", top: 8, right: 10,
              background: "none", border: "none", cursor: "pointer",
              color: "var(--muted)", fontSize: 14, lineHeight: 1, padding: 2,
            }}>✕</button>
        </div>
      )}

      {/* Chat window */}
      {isOpen && (
        <div style={{
          width: isMobile ? "calc(100vw - 32px)" : 340,
          maxWidth: isMobile ? "calc(100vw - 32px)" : 340,
          height: isMobile ? "min(68vh, 520px)" : 480,
          background: "oklch(0.09 0.02 198)",
          border: "1px solid var(--border)",
          borderRadius: 16,
          display: "flex", flexDirection: "column",
          boxShadow: "0 8px 40px rgba(0,0,0,0.6), 0 0 24px oklch(0.65 0.16 185 / 0.15)",
          overflow: "hidden",
          animation: "fadeIn 0.25s ease",
        }}>

          {/* Header */}
          <div style={{
            display: "flex", alignItems: "center", justifyContent: "space-between",
            padding: "14px 16px",
            background: "oklch(0.11 0.022 198)",
            borderBottom: "1px solid var(--border)",
            flexShrink: 0,
          }}>
            <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
              <div style={{ position: "relative", flexShrink: 0 }}>
                <img
                  src={AVATAR}
                  alt="Francis"
                  style={{
                    width: 38, height: 38, borderRadius: "50%",
                    objectFit: "cover", objectPosition: AVATAR_FOCUS,
                    border: "2px solid var(--teal)",
                    boxShadow: "0 0 10px oklch(0.65 0.16 185 / 0.4)",
                  }}
                />
                <div style={{
                  position: "absolute", bottom: 1, right: 1,
                  width: 9, height: 9, borderRadius: "50%",
                  background: "#22c55e",
                  border: "2px solid oklch(0.11 0.022 198)",
                }} />
              </div>
              <div>
                <p style={{ fontFamily: "Montserrat, sans-serif", fontWeight: 700, fontSize: 13, color: "var(--fg)" }}>Francis's AI Assistant</p>
                <p style={{ fontFamily: "Roboto Mono, monospace", fontSize: 10, color: "var(--muted)", letterSpacing: "0.06em" }}>Online</p>
              </div>
            </div>
            <button onClick={closeChat} style={{
              background: "none", border: "none", cursor: "pointer",
              color: "var(--muted)", padding: 4, borderRadius: 6,
              transition: "color 0.15s",
            }}
              onMouseEnter={e => e.currentTarget.style.color = "var(--fg)"}
              onMouseLeave={e => e.currentTarget.style.color = "var(--muted)"}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <path d="M18 6L6 18M6 6l12 12"/>
              </svg>
            </button>
          </div>

          {/* Messages */}
          <div style={{
            flex: 1, overflowY: "auto", padding: "16px 14px",
            display: "flex", flexDirection: "column", gap: 10,
          }}>
            {messages.map((msg, i) => (
              <div key={i} style={{
                display: "flex", alignItems: "flex-end", gap: 8,
                justifyContent: msg.role === "user" ? "flex-end" : "flex-start",
              }}>
                {msg.role === "bot" && (
                  <img
                    src={AVATAR}
                    alt="Francis"
                    style={{
                      width: isMobile ? 22 : 26, height: isMobile ? 22 : 26, borderRadius: "50%",
                      objectFit: "cover", objectPosition: AVATAR_FOCUS,
                      border: "1px solid var(--teal)",
                      flexShrink: 0,
                    }}
                  />
                )}
                <div style={{
                  maxWidth: isMobile ? "82%" : "75%",
                  padding: "10px 13px",
                  borderRadius: msg.role === "user" ? "14px 14px 4px 14px" : "14px 14px 14px 4px",
                  background: msg.role === "user"
                    ? "var(--teal)"
                    : "oklch(0.13 0.022 198)",
                  border: msg.role === "bot" ? "1px solid var(--border)" : "none",
                  color: msg.role === "user" ? "#030d0e" : "var(--fg)",
                  fontFamily: "Montserrat, sans-serif",
                  fontSize: isMobile ? 12 : 13, lineHeight: 1.55,
                  boxShadow: msg.role === "user" ? "0 0 12px oklch(0.65 0.16 185 / 0.3)" : "none",
                }}>
                  {msg.text}
                </div>
              </div>
            ))}
            {isLoading && (
              <div style={{ display: "flex", alignItems: "flex-end", gap: 8, justifyContent: "flex-start" }}>
                <img
                  src={AVATAR}
                  alt="Francis"
                  style={{
                    width: isMobile ? 22 : 26, height: isMobile ? 22 : 26, borderRadius: "50%",
                    objectFit: "cover", objectPosition: AVATAR_FOCUS,
                    border: "1px solid var(--teal)", flexShrink: 0,
                  }}
                />
                <div style={{
                  padding: "10px 16px",
                  borderRadius: "14px 14px 14px 4px",
                  background: "oklch(0.13 0.022 198)",
                  border: "1px solid var(--border)",
                  display: "flex", alignItems: "center", gap: 5,
                }}>
                  {[0, 1, 2].map(d => (
                    <div key={d} style={{
                      width: 6, height: 6, borderRadius: "50%",
                      background: "var(--teal)",
                      animation: `bounce 1.2s ease-in-out ${d * 0.2}s infinite`,
                    }} />
                  ))}
                </div>
              </div>
            )}
            <div ref={messagesEndRef} />
          </div>

          {/* Input */}
          <div style={{
            padding: "10px 12px",
            borderTop: "1px solid var(--border)",
            display: "flex", gap: 8, alignItems: "flex-end",
            flexShrink: 0,
            background: "oklch(0.09 0.02 198)",
          }}>
            <textarea
              value={input}
              onChange={e => setInput(e.target.value.slice(0, MAX_INPUT_LEN))}
              onKeyDown={handleKeyDown}
              placeholder="Type a message…"
              rows={1}
              maxLength={MAX_INPUT_LEN}
              style={{
                flex: 1, resize: "none", background: "oklch(0.13 0.022 198)",
                border: "1px solid var(--border)", borderRadius: 10,
                padding: "9px 12px",
                fontFamily: "Montserrat, sans-serif", fontSize: 13,
                color: "var(--fg)", outline: "none",
                transition: "border-color 0.2s",
                lineHeight: 1.5, maxHeight: 90, overflowY: "auto",
              }}
              onFocus={e => e.target.style.borderColor = "var(--teal)"}
              onBlur={e => e.target.style.borderColor = "var(--border)"}
            />
            <button
              onClick={sendMessage}
              disabled={!input.trim() || isLoading}
              style={{
                width: 38, height: 38, borderRadius: 10, flexShrink: 0,
                background: input.trim() && !isLoading ? "var(--teal)" : "oklch(0.13 0.022 198)",
                border: "1px solid",
                borderColor: input.trim() && !isLoading ? "var(--teal)" : "var(--border)",
                cursor: input.trim() && !isLoading ? "pointer" : "default",
                display: "flex", alignItems: "center", justifyContent: "center",
                transition: "background 0.2s, border-color 0.2s",
                boxShadow: input.trim() && !isLoading ? "0 0 12px oklch(0.65 0.16 185 / 0.4)" : "none",
              }}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none"
                stroke={input.trim() && !isLoading ? "#030d0e" : "var(--muted)"}
                strokeWidth="2.2">
                <path d="M22 2L11 13M22 2L15 22l-4-9-9-4 20-7z"/>
              </svg>
            </button>
          </div>
        </div>
      )}

      {/* Toggle button — profile photo */}
      <button
        onClick={isOpen ? closeChat : openChat}
        style={{
          width: 56, height: 56, borderRadius: "50%",
          padding: 0, overflow: "hidden",
          border: "2px solid var(--teal)",
          cursor: "pointer",
          boxShadow: isOpen
            ? "0 4px 16px rgba(0,0,0,0.4)"
            : "0 4px 20px oklch(0.65 0.16 185 / 0.5), 0 0 32px oklch(0.65 0.16 185 / 0.25)",
          transition: "box-shadow 0.2s",
          animation: !isOpen ? "buttonGlow 2.5s ease-in-out infinite" : "none",
          flexShrink: 0,
          background: "oklch(0.11 0.022 198)",
        }}>
        {isOpen
          ? <div style={{ width: "100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center", background: "oklch(0.11 0.022 198)" }}>
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--teal)" strokeWidth="2.2"><path d="M18 6L6 18M6 6l12 12"/></svg>
            </div>
          : <img
              src={AVATAR}
              alt="Francis"
              style={{ width: "100%", height: "100%", objectFit: "cover", objectPosition: AVATAR_FOCUS }}
            />
        }
      </button>
    </div>
  );
};

Object.assign(window, { ChatbotWidget });
