"""
Browser-side DOM walkers for Web-Component CMPs and OEM design-systems.

Centralizes the JavaScript snippets used by banner_text_checker.py so the
checker file stays under the 500-LOC cap. Each function returns a JS string
that Playwright passes to `page.evaluate()`.

Two walkers:
  * SHADOW_BANNER_WALKER_JS — pierces shadow DOM (Mercedes cmm-cookie-banner,
    BMW cookie-consent-banner, etc.) and extracts banner text + label-based
    legal links (P63 — recognizes wb7-link/role=link/button, not just
    <a href>, since OEM design-systems wrap navigation).
  * FOOTER_LABELS_WALKER_JS — collects unique footer link labels from any
    candidate footer root (footer, [role=contentinfo], wb7-footer, ...) with
    a bottom-25%-of-viewport fallback (P64).
"""

from __future__ import annotations


SHADOW_BANNER_WALKER_JS = """() => {
    const LEGAL_KW = {
        impressum: ['impressum','imprint','legal notice','mentions legales','colophon'],
        dse: ['datenschutz','privacy','dsgvo','data protection','politique de confidentialite'],
    };
    function isLegalLabel(txt) {
        const t = (txt||'').toLowerCase();
        if (!t || t.length > 60) return null;
        for (const k of LEGAL_KW.impressum) if (t.includes(k)) return 'impressum';
        for (const k of LEGAL_KW.dse)       if (t.includes(k)) return 'dse';
        return null;
    }
    // P76: EXTENDED — scan ANY clickable element by label, not just
    // <a href> or named web-components. Mercedes uses small secondary
    // buttons below the main 3 actions: "Datenschutzerklaerung" + "Impressum"
    // as <wb7-link>/<button>/<small><a> — generic label-based scan catches them.
    function collectLegalLinksFromRoot(rootEl, acc) {
        if (!rootEl || !rootEl.querySelectorAll) return;
        // Generic scan: ALLE klickbaren/Link-aussehenden Elemente
        const cands = rootEl.querySelectorAll(
            'a, button, [role="link"], [role="button"], ' +
            'wb7-link, wb7-button, wb7-button-text, wb7-link-secondary, ' +
            'span[onclick], small a, small button, ' +
            '[class*="link" i], [class*="button" i]'
        );
        const seen = new Set();
        for (const c of cands) {
            const label = (c.textContent || '').trim();
            if (!label || label.length > 60) continue;
            const which = isLegalLabel(label);
            if (!which) continue;
            const key = which + '|' + label.toLowerCase();
            if (seen.has(key)) continue;
            seen.add(key);
            const href = (c.getAttribute('href') ||
                          c.getAttribute('data-href') ||
                          c.getAttribute('data-uri') ||
                          c.getAttribute('data-url') || '').toLowerCase();
            acc.links.push({
                href: href || ('#label-' + which),
                text: label.toLowerCase(),
            });
        }
    }
    function walk(root, acc) {
        if (!root) return;
        const all = root.querySelectorAll ? root.querySelectorAll('*') : [];
        for (const el of all) {
            if (el.shadowRoot) walk(el.shadowRoot, acc);
        }
        const tags = ['cmm-cookie-banner', 'cookie-consent-banner',
                      'consent-banner', 'cookie-banner', 'cmp-banner',
                      'ot-banner', 'usercentrics-banner'];
        for (const tag of tags) {
            const els = root.querySelectorAll ? root.querySelectorAll(tag) : [];
            for (const el of els) {
                if (el.shadowRoot) {
                    const txt = (el.shadowRoot.textContent || '').trim();
                    if (txt) acc.text += ' ' + txt;
                    // P76: full label-based scan of shadow content
                    collectLegalLinksFromRoot(el.shadowRoot, acc);
                    // Legacy: plain <a href> for backward compatibility
                    const links = el.shadowRoot.querySelectorAll('a[href]');
                    for (const a of links) {
                        acc.links.push({
                            href: (a.getAttribute('href') || '').toLowerCase(),
                            text: (a.textContent || '').trim().toLowerCase(),
                        });
                    }
                }
            }
        }
    }
    const acc = { text: '', links: [] };
    walk(document, acc);
    return acc;
}"""


FOOTER_LABELS_WALKER_JS = """() => {
    const out = new Set();
    const roots = [
        ...document.querySelectorAll(
            'footer, [role="contentinfo"], ' +
            'wb7-footer, wb-footer, b-footer, cmm-footer, ' +
            '[class*="footer" i], [id*="footer" i]'
        )
    ];
    if (roots.length === 0) {
        const viewH = window.innerHeight;
        for (const el of document.querySelectorAll('a, button, [role="link"], wb7-link')) {
            const r = el.getBoundingClientRect();
            if (r.top > viewH * 0.75) roots.push(el.parentElement);
        }
    }
    for (const root of roots) {
        if (!root) continue;
        const cands = root.querySelectorAll('a, button, [role="link"], wb7-link, wb7-button');
        let n = 0;
        for (const c of cands) {
            if (n++ > 80) break;
            const t = (c.textContent || '').trim().toLowerCase();
            if (t && t.length < 60) out.add(t);
        }
    }
    return [...out];
}"""
