/**
 * Chat-Kontext für Logs und Antwort-Pfeil – letzte Kundennachricht auf torchwood.app.
 */
(function (global) {
  'use strict';

  const CUSTOMER_CLASS = 'Message__Bubble--customer';
  const FAKE_CLASS = 'Message__Bubble--fake';
  const RESPOND_ICON_SELECTOR = '.icon-message-respond, [class*="icon-message-respond"]';

  function norm(text) {
    return String(text || '')
      .replace(/\s+/g, ' ')
      .replace(/\s*\d{4}-\d{2}-\d{2}\s+\d{1,2}:\d{2}\s*$/u, '')
      .trim();
  }

  function isMessageBubbleElement(el) {
    const cls = String(el?.className || '');
    return /\bMessage__Bubble\b/i.test(cls)
      || /\bMessage__Bubble-/i.test(cls)
      || (/\bBubble\b/i.test(cls) && !!el.closest?.('[class*="MessageScroll"], [class*="Conversation__StyledChat"], [class*="Conversation"]'));
  }

  function cleanBubbleMessageText(text) {
    return norm(text)
      .replace(/^[A-ZÄÖÜ][\p{L}\p{M}'’-]{1,32}\s+\d{4}-\d{2}-\d{2}\s+\d{1,2}:\d{2}\s*/u, '')
      .replace(/^[A-ZÄÖÜ][\p{L}\p{M}'’-]{1,32}\d{4}-\d{2}-\d{2}\s+\d{1,2}:\d{2}\s*/u, '')
      .replace(/^\d{4}-\d{2}-\d{2}\s+\d{1,2}:\d{2}\s*/u, '')
      .trim();
  }

  function extractCustomerBubbleBodyText(bubbleEl) {
    if (!bubbleEl) return '';
    const clone = bubbleEl.cloneNode(true);
    clone.querySelectorAll?.(
      '[class*="Message__TitleRow"], [class*="Message__NameText"], [class*="Message__NameToolTip"], [class*="TitleRow"], time, button, [class*="Timestamp"], [class*="timestamp"]',
    ).forEach((node) => node.remove());
    return cleanBubbleMessageText(clone.textContent || '');
  }

  function isVisible(el) {
    if (!el || !el.isConnected) return false;
    const rect = el.getBoundingClientRect();
    if (rect.width < 4 || rect.height < 4) return false;
    const st = window.getComputedStyle(el);
    return st.display !== 'none' && st.visibility !== 'hidden' && Number(st.opacity) !== 0;
  }

  function rgbHintFromElement(el) {
    if (!el) return null;
    const st = window.getComputedStyle(el);
    const bg = st.backgroundColor || '';
    const m = bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i);
    if (!m) return null;
    const r = Number(m[1]);
    const g = Number(m[2]);
    const b = Number(m[3]);
    const pinkish = r > 170 && g < 150 && b > 120 && r > b;
    const bluish = b > r + 18 && b > g + 8 && b > 90;
    return { pinkish, bluish };
  }

  function bubbleColorHint(el) {
    const nodes = [el];
    if (el instanceof HTMLElement) {
      el.querySelectorAll('*').forEach((child) => {
        if (child instanceof HTMLElement && nodes.length < 24) nodes.push(child);
      });
    }
    for (const node of nodes) {
      const hint = rgbHintFromElement(node);
      if (hint?.pinkish || hint?.bluish) return hint;
    }
    return rgbHintFromElement(el);
  }

  function bubbleTorchwoodRoleFromClasses(el) {
    let node = el;
    for (let i = 0; i < 10 && node; i++) {
      const cls = String(node.className || '');
      if (new RegExp(`\\b${CUSTOMER_CLASS}\\b`).test(cls)) return 'customer';
      if (new RegExp(`\\b${FAKE_CLASS}\\b`).test(cls)) return 'fake';
      node = node.parentElement;
    }
    return null;
  }

  function bubbleClassSideHint(el) {
    const torchwoodRole = bubbleTorchwoodRoleFromClasses(el);
    if (torchwoodRole) return torchwoodRole;

    let node = el;
    for (let i = 0; i < 8 && node; i++) {
      const cls = String(node.className || '');
      if (new RegExp(`\\b${CUSTOMER_CLASS}\\b`).test(cls)) return 'customer';
      if (new RegExp(`\\b${FAKE_CLASS}\\b`).test(cls)) return 'fake';
      if (/\boutgoing|outbound|sent|own-message|moderator|mod-message|fake-message|agent-message/i.test(cls)) return 'fake';
      if (/\bincoming|inbound|received|customer-message|kunde|client-message/i.test(cls)) return 'customer';
      node = node.parentElement;
    }
    return null;
  }

  function bubbleLayoutSideHint(el, rect) {
    const cx = rect.left + rect.width / 2;
    const vw = window.innerWidth || 1;
    if (cx < vw * 0.42) return 'customer';
    if (cx > vw * 0.58) return 'fake';
    return null;
  }

  function classifyBubble(el) {
    if (!isMessageBubbleElement(el)) return null;
    if (el.parentElement?.closest?.('[class*="Message__Bubble"]')) return null;

    const text = cleanBubbleMessageText(el?.textContent || '');
    if (text.length < 2) return null;

    const torchwoodRole = bubbleTorchwoodRoleFromClasses(el);
    if (torchwoodRole === 'customer') return { role: 'customer', text, el };
    if (torchwoodRole === 'fake') return { role: 'fake', text, el };

    const rect = el.getBoundingClientRect();
    const colorHint = bubbleColorHint(el);
    const clsSide = bubbleClassSideHint(el);
    const side = bubbleLayoutSideHint(el, rect);

    if (colorHint?.pinkish || clsSide === 'fake' || side === 'fake') return { role: 'fake', text, el };
    if (colorHint?.bluish || clsSide === 'customer' || side === 'customer') return { role: 'customer', text, el };
    return null;
  }

  function findChatScopes() {
    const scopes = [];
    const seen = new Set();
    const add = (el) => {
      if (!el || seen.has(el)) return;
      seen.add(el);
      scopes.push(el);
    };

    document.querySelectorAll('[class*="Conversation"], [class*="Chat"], [class*="MessageList"], [class*="Messages"]').forEach(add);
    if (!scopes.length) add(document.body);
    return scopes;
  }

  function collectVisibleBubbles() {
    const bubbles = [];
    const seen = new Set();

    findChatScopes().forEach((scope) => {
      scope.querySelectorAll('[class*="Message__Bubble"]').forEach((el) => {
        if (!isVisible(el) || seen.has(el) || !isMessageBubbleElement(el)) return;
        seen.add(el);
        const msg = classifyBubble(el);
        if (!msg) return;
        const rect = el.getBoundingClientRect();
        bubbles.push({ ...msg, top: rect.top, left: rect.left });
      });
    });

    bubbles.sort((a, b) => a.top - b.top || a.left - b.left);
    return bubbles;
  }

  function scanMessagesFallback() {
    return collectVisibleBubbles().map(({ role, text }) => ({ role, text }));
  }

  function lastCustomerMessageFromMessages(messages) {
    for (let i = (messages || []).length - 1; i >= 0; i--) {
      const msg = messages[i];
      if (msg?.role !== 'customer') continue;
      const text = norm(msg.text);
      if (text) return text.slice(0, 800);
    }
    return '';
  }

  function findLastCustomerMessageBubble() {
    const bubbles = collectVisibleBubbles();
    const strict = bubbles.filter((b) => /\bMessage__Bubble--customer\b/.test(String(b.el?.className || '')));
    const pool = strict.length
      ? strict
      : bubbles.filter((b) => b.role === 'customer' && !/\bMessage__Bubble--fake\b/.test(String(b.el?.className || '')));
    if (!pool.length) return null;
    return pool[pool.length - 1].el || null;
  }

  function isClickableCandidate(el) {
    if (!el?.isConnected || el.disabled) return false;
    const st = window.getComputedStyle(el);
    return st.display !== 'none' && st.visibility !== 'hidden';
  }

  function hasRespondIcon(el) {
    if (!el) return false;
    return !!el.querySelector?.(`${RESPOND_ICON_SELECTOR}`)
      || /\bicon-message-respond\b/.test(String(el.className || ''));
  }

  function resolveRespondButton(node) {
    if (!node) return null;
    if (node.matches?.('button, [role="button"], [data-react-aria-pressable="true"]') && hasRespondIcon(node)) {
      return isClickableCandidate(node) ? node : null;
    }
    const icon = node.matches?.(RESPOND_ICON_SELECTOR)
      ? node
      : node.querySelector?.(RESPOND_ICON_SELECTOR);
    if (!icon) return null;
    const btn = icon.closest?.('button, [role="button"], [data-react-aria-pressable="true"]');
    return btn && isClickableCandidate(btn) ? btn : null;
  }

  function findMessageBlock(bubbleEl) {
    return bubbleEl?.closest?.('[class*="ScrollViewBlock"], [class*="Message__"]') || bubbleEl;
  }

  function findRespondButtonNearBubble(bubbleEl) {
    if (!bubbleEl) return null;

    const scopes = [
      bubbleEl,
      findMessageBlock(bubbleEl),
      bubbleEl.parentElement,
      bubbleEl.parentElement?.parentElement,
    ].filter(Boolean);

    const seen = new Set();
    for (const scope of scopes) {
      if (seen.has(scope)) continue;
      seen.add(scope);
      const direct = resolveRespondButton(scope);
      if (direct) return direct;
      const icons = scope.querySelectorAll?.(RESPOND_ICON_SELECTOR);
      for (const icon of icons || []) {
        const btn = icon.closest?.('button, [role="button"], [data-react-aria-pressable="true"]');
        if (btn && isClickableCandidate(btn)) return btn;
      }
    }

    const bubbleRect = bubbleEl.getBoundingClientRect();
    let best = null;
    let bestScore = Infinity;
    document.querySelectorAll(RESPOND_ICON_SELECTOR).forEach((icon) => {
      const btn = icon.closest?.('button, [role="button"], [data-react-aria-pressable="true"]');
      if (!btn || !isClickableCandidate(btn)) return;
      const rect = btn.getBoundingClientRect();
      const dy = Math.abs(rect.top - bubbleRect.top);
      const dx = Math.abs(rect.left - bubbleRect.left);
      const score = dy + dx * 0.25;
      if (score < bestScore) {
        bestScore = score;
        best = btn;
      }
    });
    return bestScore <= 180 ? best : null;
  }

  function safeRespondClick(el) {
    if (!el || !isClickableCandidate(el)) return false;
    try { el.scrollIntoView?.({ block: 'nearest', inline: 'nearest' }); } catch (_) {}
    try {
      el.click();
      return true;
    } catch (_) {
      return false;
    }
  }

  function clickRespondOnLastCustomerMessage() {
    const bubble = findLastCustomerMessageBubble();
    if (!bubble) {
      return { ok: false, reason: 'no-customer-bubble' };
    }

    const snippet = norm(bubble.textContent || '').slice(0, 120);
    const button = findRespondButtonNearBubble(bubble);
    if (!button) {
      return { ok: false, reason: 'no-respond-button', snippet };
    }

    if (!safeRespondClick(button)) {
      return { ok: false, reason: 'click-failed', snippet };
    }

    return {
      ok: true,
      reason: 'clicked',
      snippet,
      buttonClass: String(button.className || '').slice(0, 120),
      iconClass: String(button.querySelector?.(RESPOND_ICON_SELECTOR)?.className || '').slice(0, 120),
    };
  }

  function getLastCustomerMessage() {
    try {
      const scan = global.ChillicollectivoTorchwoodAsa?.scanMessages;
      const messages = typeof scan === 'function' ? scan() : scanMessagesFallback();
      return lastCustomerMessageFromMessages(messages);
    } catch (_) {
      return '';
    }
  }

  global.chillicollectivoGetLastCustomerMessage = getLastCustomerMessage;
  global.chillicollectivoFindLastCustomerMessageBubble = findLastCustomerMessageBubble;
  global.chillicollectivoExtractCustomerBubbleBodyText = extractCustomerBubbleBodyText;
  global.chillicollectivoCleanBubbleMessageText = cleanBubbleMessageText;
  global.chillicollectivoClickRespondOnLastCustomerMessage = clickRespondOnLastCustomerMessage;
})(typeof globalThis !== 'undefined' ? globalThis : window);
