(() => {
    'use strict';

    const HIGHLIGHT_CLASS = 'claralex-highlight';
    const HIGHLIGHT_TAG = 'MARK';
    const STATUS_WIDGET_ID = 'claralex-status-widget';
    const STATUS_DOCK_ID = 'claralex-status-dock';
    const ANALYSIS_PANEL_ID = 'claralex-analysis-panel';
    const AUTO_SCAN_DELAY_MS = 1400;
    const AUTO_SCAN_RETRY_MS = 4200;
    const AUTO_SCAN_THRESHOLD = 6;
    const MIN_TEXT_LENGTH = 650;
    const APPROX_CHARS_PER_TOKEN = 4;
    const MAX_INPUT_TOKENS = 125000;
    const MAX_PAGE_TEXT = MAX_INPUT_TOKENS * APPROX_CHARS_PER_TOKEN;
    const ANALYSIS_BATCH_SIZE = 3;
    const ANALYSIS_WINDOW_CHARS = 18000;
    const ANALYSIS_WINDOW_OVERLAP = 300;
    const MAX_PASSES_PER_WINDOW = 4;
    const MAX_KNOWN_REFERENCES = 400;
    const MAX_ACTIVITY_LOG = 14;
    const MAX_REFERENCE_MATCHES_PER_NODE = 25;
    const MAX_TOTAL_CLAUSES = 5;
    const MATCH_VARIANT_WORDS = 8;
    const CONTRACT_KEYWORDS = ['termini', 'condizioni', 'contratto', 'clausola', 'clausole', 'vessator', 'recesso', 'foro competente', 'rinnovo', 'abbonamento', 'penale', 'responsabilita', 'garanzia', 'checkout', 'subscription', 'billing', 'terms', 'conditions', 'renewal', 'refund', 'return policy', 'cancellation'];
    const ACTION_KEYWORDS = ['accetto', 'accetta', 'accettare', 'conferma', 'confermare', 'prosegui', 'continua', 'autorizza', 'iscriviti', 'abbonati', 'acquista', 'paga', 'i agree', 'agree', 'accept', 'confirm', 'continue', 'subscribe', 'buy now', 'complete order', 'place order', 'start trial'];
    const HIGH_INTENT_URL_KEYWORDS = ['terms', 'privacy', 'checkout', 'subscribe', 'billing', 'purchase', 'renew', 'conditions', 'condizioni', 'termini', 'contratto', 'consent', 'payment', 'order', 'account', 'abbon'];
    const LOW_SIGNAL_URL_KEYWORDS = ['blog', 'news', 'article', 'docs', 'documentation', 'forum', 'support', 'help', 'careers', 'press', 'about'];
    const state = { status: 'idle', error: null, analysis: null, heuristics: null, lastUrl: location.href, pendingTimer: null, retryTimer: null, panelOpen: false, widgetHidden: false, activeClauseId: null, expandedClauseId: null, activeReferenceIndex: null, focusCycles: {}, audio: null };
    let currentScanPromise = null;
    let currentAudioElement = null;
    let currentAudioObjectUrl = null;
    let currentRemoteAudioData = '';
    let currentRemoteAudioMimeType = 'audio/wav';

    const normalizeWhitespace = (value) => String(value || '').replace(/\s+/g, ' ').trim();
    const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    const escapeHtml = (value) => String(value || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
    const isGenericClauseTitle = (value) => {
        const lowered = normalizeWhitespace(value).toLowerCase();
        return [
            'verifica generale',
            'general review',
            'clausola rilevata',
            'clause review',
            'modifica unilaterale',
            'sospensione o chiusura unilaterale'
        ].includes(lowered);
    };
    const normalizeRiskLevel = (value) => {
        const lowered = normalizeWhitespace(value).toLowerCase();
        if (['danger', 'red', 'rosso', 'critical', 'critico'].includes(lowered)) return 'danger';
        if (['warning', 'yellow', 'giallo', 'attenzione', 'sospetta', 'sospetto'].includes(lowered)) return 'warning';
        if (['success', 'green', 'verde', 'ok', 'safe', 'positivo'].includes(lowered)) return 'success';
        return 'info';
    };

    function sendRuntimeMessage(message) {
        return new Promise((resolve, reject) => {
            chrome.runtime.sendMessage(message, (response) => {
                const runtimeError = chrome.runtime.lastError;
                if (runtimeError) {
                    reject(new Error(runtimeError.message));
                    return;
                }
                resolve(response);
            });
        });
    }

    function collectInteractiveText() {
        return Array.from(document.querySelectorAll('button, [role="button"], input[type="submit"], input[type="button"], label, a'))
            .slice(0, 80)
            .map((node) => normalizeWhitespace(node.innerText || node.textContent || node.value || node.getAttribute('aria-label') || ''))
            .filter(Boolean)
            .join(' | ');
    }

    function findKeywordHits(text, keywords) {
        const lowered = text.toLowerCase();
        return keywords.filter((keyword) => lowered.includes(keyword)).slice(0, 10);
    }

    function analyzePageHeuristics() {
        const pageText = normalizeWhitespace(document.body?.innerText || '');
        const title = normalizeWhitespace(document.title || '');
        const interactiveText = normalizeWhitespace(collectInteractiveText());
        const combined = `${title} ${location.href} ${interactiveText} ${pageText.slice(0, 12000)}`.toLowerCase();
        const contractHits = findKeywordHits(combined, CONTRACT_KEYWORDS);
        const actionHits = findKeywordHits(combined, ACTION_KEYWORDS);
        const strongIntentHits = findKeywordHits(`${title} ${location.href} ${interactiveText}`.toLowerCase(), HIGH_INTENT_URL_KEYWORDS);
        const lowSignalHits = findKeywordHits(`${title} ${location.href}`.toLowerCase(), LOW_SIGNAL_URL_KEYWORDS);
        const hasEconomicSignal = /(\beur\b|\btrial\b|\bmensil|\bannual|\bmonth\b|\byear\b|\bpagamento\b|\bpayment\b|\u20AC)/i.test(pageText);
        const hasSensitiveClause = /(foro competente|arbitr|limita.{0,20}responsabilita|modific.{0,20}prezzo|rinnovo automatico|rinuncia|penale|disdetta)/i.test(pageText);
        const reasons = [];
        let score = 0;

        if (pageText.length >= MIN_TEXT_LENGTH) {
            score += 1;
            reasons.push('pagina con testo sufficiente');
        }
        if (pageText.length >= 2200) {
            score += 1;
            reasons.push('testo lungo tipico di termini o condizioni');
        }
        if (contractHits.length > 0) {
            score += Math.min(contractHits.length, 3);
            reasons.push(`parole chiave legali: ${contractHits.slice(0, 3).join(', ')}`);
        }
        if (actionHits.length > 0) {
            score += Math.min(actionHits.length, 2);
            reasons.push(`azione di consenso o conferma: ${actionHits.slice(0, 2).join(', ')}`);
        }
        if (strongIntentHits.length > 0) {
            score += Math.min(strongIntentHits.length, 2);
            reasons.push(`segnali forti in titolo o url: ${strongIntentHits.slice(0, 2).join(', ')}`);
        }
        if (hasEconomicSignal) {
            score += 1;
            reasons.push('sono presenti elementi economici o rinnovi');
        }
        if (hasSensitiveClause) {
            score += 2;
            reasons.push('il testo contiene possibili clausole sensibili');
        }
        if (lowSignalHits.length > 0 && contractHits.length === 0 && actionHits.length === 0) {
            score -= 2;
            reasons.push('pagina piu simile a contenuto informativo che a contratto');
        }

        const hasStrongIntent = strongIntentHits.length > 0 || actionHits.length > 0 || hasSensitiveClause;
        const hasContractContext = contractHits.length > 0 || hasEconomicSignal;

        return {
            isCandidate: pageText.length >= MIN_TEXT_LENGTH && score >= AUTO_SCAN_THRESHOLD && hasStrongIntent && hasContractContext,
            score,
            reasons: reasons.slice(0, 6),
            pageText: pageText.slice(0, MAX_PAGE_TEXT),
            keywordHits: [...new Set([...contractHits, ...actionHits, ...strongIntentHits])].slice(0, 12),
            interactiveText: interactiveText.slice(0, 500),
            title
        };
    }
    function computeTriage(clauses) {
        return clauses.reduce((totals, clause) => {
            totals[normalizeRiskLevel(clause.type)] += 1;
            return totals;
        }, { danger: 0, warning: 0, success: 0, info: 0 });
    }

    function normalizeReferences(rawReferences) {
        const list = Array.isArray(rawReferences) ? rawReferences : [rawReferences];
        return Array.from(new Set(list.map((item) => normalizeWhitespace(item).replace(/^["'`]+|["'`]+$/g, '')).filter((item) => item.length >= 10))).slice(0, 6);
    }

    function buildReferenceVariants(reference) {
        const cleaned = normalizeWhitespace(reference).replace(/^["'`]+|["'`]+$/g, '');
        if (!cleaned) return [];
        const words = cleaned.split(' ').filter(Boolean);
        const variants = [cleaned];
        if (words.length > MATCH_VARIANT_WORDS + 2) {
            variants.push(words.slice(0, MATCH_VARIANT_WORDS).join(' '));
            variants.push(words.slice(-MATCH_VARIANT_WORDS).join(' '));
            const middleStart = Math.max(0, Math.floor((words.length - MATCH_VARIANT_WORDS) / 2));
            variants.push(words.slice(middleStart, middleStart + MATCH_VARIANT_WORDS).join(' '));
        }
        return Array.from(new Set(variants.filter((item) => item.length >= 24)));
    }

    function hydrateAnalysis(rawAnalysis) {
        const clauses = Array.isArray(rawAnalysis?.clauses) ? rawAnalysis.clauses.map((clause, index) => {
            const references = normalizeReferences(clause.references || clause.quotes || [clause.textToFind || clause.quote || '']);
            return {
                id: clause.id || `claralex-clause-${index + 1}`,
                type: normalizeRiskLevel(clause.type),
                title: normalizeWhitespace(clause.title) || `Clausola ${index + 1}`,
                description: normalizeWhitespace(clause.description) || 'Leggi con attenzione questo punto.',
                clauseSummary: normalizeWhitespace(clause.clauseSummary || clause.description || ''),
                riskLabel: normalizeWhitespace(clause.riskLabel || ''),
                whyItMatters: normalizeWhitespace(clause.whyItMatters || clause.description || ''),
                userImpact: normalizeWhitespace(clause.userImpact || ''),
                legalBasis: normalizeWhitespace(clause.legalBasis || clause.legalReasoning || ''),
                legalReasoning: normalizeWhitespace(clause.legalReasoning),
                confidence: clause.confidence ?? null,
                references,
                quote: references[0] || normalizeWhitespace(clause.textToFind || clause.quote || ''),
                textToFind: references[0] || normalizeWhitespace(clause.textToFind || clause.quote || ''),
                occurrenceCount: 0
            };
        }) : [];
        return {
            ...rawAnalysis,
            riskLevel: normalizeRiskLevel(rawAnalysis?.riskLevel),
            summary: normalizeWhitespace(rawAnalysis?.summary),
            suggestedAction: normalizeWhitespace(rawAnalysis?.suggestedAction),
            clauses,
            triage: computeTriage(clauses)
        };
    }

    function createEmptyAnalysisState(windowCount) {
        return {
            isContractLike: true,
            pageType: 'other',
            riskLevel: 'info',
            summary: 'Analisi progressiva avviata.',
            suggestedAction: 'I risultati arriveranno a blocchi di 3 o 4 clausole per volta.',
            clauses: [],
            triage: computeTriage([]),
            activityLog: [],
            progress: {
                chunkIndex: 1,
                chunkCount: windowCount,
                passIndex: 1,
                batchSize: ANALYSIS_BATCH_SIZE,
                batchesCompleted: 0
            }
        };
    }

    function createEmptyAudioState() {
        return {
            status: 'idle',
            headline: '',
            text: '',
            mood: 'calm',
            error: null,
            isSpeaking: false,
            estimatedSeconds: null,
            analysisKey: '',
            source: null,
            playbackToken: 0,
            playbackMode: null,
            voice: null,
            provider: null,
            hasRemoteAudio: false,
            fallback: false
        };
    }

    function pushActivity(message, tone = 'info') {
        if (!message) {
            return;
        }

        if (!state.analysis) {
            state.analysis = createEmptyAnalysisState(1);
        }

        const timestamp = new Date().toLocaleTimeString('it-IT', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
        const entry = {
            id: `${Date.now()}-${Math.random().toString(16).slice(2, 8)}`,
            tone,
            message,
            timestamp
        };

        state.analysis.activityLog = [...(state.analysis.activityLog || []), entry].slice(-MAX_ACTIVITY_LOG);
    }

    function ensureAudioState() {
        if (!state.audio) {
            state.audio = createEmptyAudioState();
        }

        return state.audio;
    }

    function resetAudioState() {
        stopAudioPlayback({ silent: true });
        currentRemoteAudioData = '';
        currentRemoteAudioMimeType = 'audio/wav';
        state.audio = createEmptyAudioState();
    }

    function getAnalysisAudioKey(analysis) {
        if (!analysis) {
            return '';
        }

        return [
            normalizeWhitespace(analysis.summary),
            normalizeWhitespace(analysis.suggestedAction),
            Array.isArray(analysis.clauses) ? analysis.clauses.length : 0,
            normalizeWhitespace(analysis.scannedAt)
        ].join('|');
    }

    function normalizeAudioMood(value) {
        const lowered = normalizeWhitespace(value).toLowerCase();
        if (['alert', 'calm', 'positive'].includes(lowered)) {
            return lowered;
        }

        return 'calm';
    }

    function normalizeAudioSummaryData(rawSummary) {
        return {
            headline: normalizeWhitespace(rawSummary?.headline) || 'Riepilogo audio ClaraLex',
            text: normalizeWhitespace(rawSummary?.spokenSummary || rawSummary?.summary || rawSummary?.text),
            mood: normalizeAudioMood(rawSummary?.mood),
            estimatedSeconds: Number(rawSummary?.estimatedSeconds) || null,
            fallback: Boolean(rawSummary?.fallback),
            provider: normalizeWhitespace(rawSummary?.audio?.provider || rawSummary?.provider),
            voice: normalizeWhitespace(rawSummary?.audio?.voice || rawSummary?.voice),
            ttsError: normalizeWhitespace(rawSummary?.ttsError || ''),
            audioData: typeof rawSummary?.audio?.data === 'string' ? rawSummary.audio.data : '',
            audioMimeType: normalizeWhitespace(rawSummary?.audio?.mimeType) || 'audio/wav',
            hasRemoteAudio: Boolean(rawSummary?.audio?.data)
        };
    }

    function buildLocalAudioSummary(analysis) {
        const triage = analysis?.triage || computeTriage(analysis?.clauses || []);
        const topClauses = Array.isArray(analysis?.clauses)
            ? analysis.clauses.slice(0, 3).map((clause) => `${clause.title}. ${clause.description || clause.legalReasoning || ''}`.trim()).filter(Boolean)
            : [];
        const intro = analysis?.riskLevel === 'danger'
            ? 'Aspetta un secondo: qui ci sono punti che meritano attenzione vera.'
            : analysis?.riskLevel === 'warning'
                ? 'Prima di confermare, c e piu di un dettaglio che vale una rilettura.'
                : 'Ti porto subito al punto, senza giri lunghi.';
        const triageLine = `Ho trovato ${triage.danger || 0} punti rossi, ${triage.warning || 0} gialli e ${triage.success || 0} verdi.`;
        const body = topClauses.length > 0
            ? `Le cose da guardare meglio sono queste. ${topClauses.join(' ')}`
            : analysis?.summary || 'Non ho trovato clausole specifiche da leggere ad alta voce in questo momento.';
        const closing = analysis?.suggestedAction
            ? `Il consiglio finale e questo: ${analysis.suggestedAction}`
            : 'Il consiglio finale e questo: prima di accettare, rileggi le frasi evidenziate.';

        return {
            headline: analysis?.riskLevel === 'danger' ? 'Attenzione prima di accettare' : analysis?.riskLevel === 'warning' ? 'Occhio ai punti chiave' : 'Riepilogo rapido ClaraLex',
            text: normalizeWhitespace(`${intro} ${triageLine} ${body} ${closing}`),
            mood: analysis?.riskLevel === 'danger' || analysis?.riskLevel === 'warning' ? 'alert' : 'calm',
            estimatedSeconds: null,
            fallback: true
        };
    }

    function getAudioButtonLabel() {
        const audio = ensureAudioState();
        if (audio.status === 'loading') return 'Creo audio...';
        if (audio.isSpeaking) return 'Ferma audio';
        if (audio.text) return 'Ascolta audio';
        return 'Genera audio';
    }

    function createAudioMarkup(audio) {
        if (!audio || (!audio.text && audio.status === 'idle')) {
            return '<div class="claralex-analysis-empty">Premi Genera audio per ascoltare un riepilogo semplice e veloce di questa analisi.</div>';
        }

        if (audio.status === 'loading') {
            return '<div class="claralex-audio-card claralex-audio-card--loading"><div class="claralex-audio-card__headline">Sto preparando il riepilogo audio</div><div class="claralex-audio-card__text">Genero prima un testo breve, chiaro e piu parlato, poi avvio subito l ascolto.</div></div>';
        }

        const meta = [];
        if (clause.confidence) meta.push(`confidenza ${Math.round(Number(clause.confidence) * 100)}%`);
        if (audio.estimatedSeconds) meta.push(`circa ${audio.estimatedSeconds} secondi`);
        if (audio.fallback) meta.push('modalita locale');
        if (audio.provider) meta.push(audio.provider === 'edge-tts' ? 'ClaraLex TTS' : audio.provider);
        if (audio.voice) meta.push(`voce ${audio.voice}`);
        if (audio.playbackMode === 'remote-tts') meta.push('audio TTS remoto');
        if (audio.playbackMode === 'browser') meta.push('voce browser');
        if (audio.isSpeaking) meta.push('in riproduzione');

        return `<div class="claralex-audio-card claralex-audio-card--${audio.mood || 'calm'}"><div class="claralex-audio-card__headline">${escapeHtml(audio.headline || 'Riepilogo audio ClaraLex')}</div><div class="claralex-audio-card__meta">${escapeHtml(meta.join(' | ') || 'pronto da ascoltare')}</div><div class="claralex-audio-card__text">${escapeHtml(audio.text || 'Riepilogo audio non disponibile.')}</div>${audio.error ? `<div class="claralex-audio-card__error">${escapeHtml(audio.error)}</div>` : ''}</div>`;
    }

    function revokeAudioObjectUrl() {
        if (currentAudioObjectUrl) {
            URL.revokeObjectURL(currentAudioObjectUrl);
            currentAudioObjectUrl = null;
        }
    }

    function createObjectUrlFromBase64Audio(base64Data, mimeType) {
        const binary = atob(base64Data);
        const bytes = new Uint8Array(binary.length);
        for (let index = 0; index < binary.length; index += 1) {
            bytes[index] = binary.charCodeAt(index);
        }

        revokeAudioObjectUrl();
        currentAudioObjectUrl = URL.createObjectURL(new Blob([bytes], { type: mimeType || 'audio/wav' }));
        return currentAudioObjectUrl;
    }

    async function waitForSpeechVoices() {
        if (!('speechSynthesis' in window)) {
            return [];
        }

        const voices = window.speechSynthesis.getVoices();
        if (voices.length > 0) {
            return voices;
        }

        return new Promise((resolve) => {
            const handleVoices = () => {
                window.speechSynthesis.removeEventListener('voiceschanged', handleVoices);
                resolve(window.speechSynthesis.getVoices());
            };

            window.speechSynthesis.addEventListener('voiceschanged', handleVoices);
            window.setTimeout(() => {
                window.speechSynthesis.removeEventListener('voiceschanged', handleVoices);
                resolve(window.speechSynthesis.getVoices());
            }, 1200);
        });
    }

    async function pickSpeechVoice() {
        const voices = await waitForSpeechVoices();
        return voices.find((voice) => /^it\b/i.test(voice.lang))
            || voices.find((voice) => /ital/i.test(voice.name))
            || voices[0]
            || null;
    }

    function stopAudioPlayback(options = {}) {
        const audio = ensureAudioState();
        audio.playbackToken += 1;

        if (currentAudioElement) {
            currentAudioElement.pause();
            currentAudioElement.src = '';
            currentAudioElement = null;
        }
        revokeAudioObjectUrl();

        if ('speechSynthesis' in window) {
            window.speechSynthesis.cancel();
        }

        if (audio.isSpeaking) {
            audio.isSpeaking = false;
            audio.status = audio.text ? 'ready' : 'idle';
            if (!options.silent) {
                pushActivity('Riproduzione audio interrotta.', 'info');
            }
            renderAnalysisPanel();
        }
    }

    async function speakAudioSummary(audioSummary) {
        if (!('speechSynthesis' in window) || typeof window.SpeechSynthesisUtterance !== 'function') {
            throw new Error('Il browser non supporta la lettura vocale integrata.');
        }

        stopAudioPlayback({ silent: true });
        const audio = ensureAudioState();
        audio.isSpeaking = true;
        audio.status = 'ready';
        audio.error = null;
        audio.playbackMode = 'browser';
        audio.playbackToken += 1;
        const playbackToken = audio.playbackToken;
        renderAnalysisPanel();

        const utterance = new window.SpeechSynthesisUtterance(audioSummary.text);
        utterance.lang = 'it-IT';
        utterance.rate = audioSummary.mood === 'alert' ? 1.02 : 0.97;
        utterance.pitch = audioSummary.mood === 'positive' ? 1.03 : 0.98;
        const selectedVoice = await pickSpeechVoice();
        if (selectedVoice) {
            utterance.voice = selectedVoice;
        }

        utterance.onend = () => {
            if (audio.playbackToken !== playbackToken) {
                return;
            }
            audio.isSpeaking = false;
            audio.status = 'ready';
            pushActivity('Riproduzione audio completata.', 'success');
            renderAnalysisPanel();
        };

        utterance.onerror = () => {
            if (audio.playbackToken !== playbackToken) {
                return;
            }
            audio.isSpeaking = false;
            audio.status = 'ready';
            audio.error = 'La riproduzione audio si e fermata prima della fine.';
            pushActivity('La riproduzione audio si e fermata in anticipo.', 'warning');
            renderAnalysisPanel();
        };

        window.speechSynthesis.speak(utterance);
    }

    async function playRemoteAudio(audioSummary) {
        if (!currentRemoteAudioData) {
            throw new Error('Audio TTS remoto non disponibile.');
        }

        stopAudioPlayback({ silent: true });
        const audio = ensureAudioState();
        audio.isSpeaking = true;
        audio.status = 'ready';
        audio.error = audioSummary.ttsError || null;
        audio.playbackMode = 'remote-tts';
        audio.playbackToken += 1;
        const playbackToken = audio.playbackToken;
        renderAnalysisPanel();

        const objectUrl = createObjectUrlFromBase64Audio(currentRemoteAudioData, currentRemoteAudioMimeType);
        const htmlAudio = new Audio(objectUrl);
        currentAudioElement = htmlAudio;

        htmlAudio.onended = () => {
            if (audio.playbackToken !== playbackToken) {
                return;
            }
            audio.isSpeaking = false;
            audio.status = 'ready';
            pushActivity('Riproduzione audio TTS completata.', 'success');
            renderAnalysisPanel();
        };

        htmlAudio.onerror = () => {
            if (audio.playbackToken !== playbackToken) {
                return;
            }
            audio.isSpeaking = false;
            audio.status = 'ready';
            audio.error = 'Non sono riuscito a riprodurre il file audio generato.';
            pushActivity('Il file audio TTS remoto non e stato riprodotto correttamente. Passo alla voce del browser.', 'warning');
            renderAnalysisPanel();
            speakAudioSummary(audioSummary).catch((error) => {
                audio.error = error.message;
                renderAnalysisPanel();
            });
        };

        await htmlAudio.play();
    }

    async function handleGenerateAudio() {
        if (!state.analysis) {
            pushActivity('Prima serve un analisi pronta per creare il riepilogo audio.', 'warning');
            renderAnalysisPanel();
            return;
        }

        const audio = ensureAudioState();
        const analysisKey = getAnalysisAudioKey(state.analysis);

        if (audio.isSpeaking) {
            stopAudioPlayback({ silent: false });
            return;
        }

        if (audio.text && audio.analysisKey === analysisKey) {
            pushActivity('Riascolto il riepilogo audio gia pronto.', 'info');
            renderAnalysisPanel();
            if (audio.hasRemoteAudio && currentRemoteAudioData) {
                await playRemoteAudio(audio);
            } else {
                await speakAudioSummary(audio);
            }
            return;
        }

        audio.status = 'loading';
        audio.error = null;
        audio.analysisKey = analysisKey;
        audio.headline = '';
        audio.text = '';
        audio.estimatedSeconds = null;
        audio.source = 'remote';
        audio.provider = null;
        audio.voice = null;
        audio.hasRemoteAudio = false;
        audio.fallback = false;
        audio.playbackMode = null;
        pushActivity('Sto preparando un riepilogo audio accattivante della pagina.', 'info');
        renderAnalysisPanel();

        try {
            const response = await sendRuntimeMessage({
                action: 'claralex.generateAudioSummary',
                payload: {
                    title: document.title || '',
                    url: location.href,
                    heuristics: state.heuristics,
                    analysis: state.analysis
                }
            });

            if (!response?.ok) {
                throw new Error(response?.error || 'Riepilogo audio non disponibile.');
            }

            const normalizedSummary = normalizeAudioSummaryData(response.data);
            if (!normalizedSummary.text) {
                throw new Error('Il backend non ha restituito un testo audio leggibile.');
            }

            currentRemoteAudioData = normalizedSummary.hasRemoteAudio ? normalizedSummary.audioData : '';
            currentRemoteAudioMimeType = normalizedSummary.audioMimeType || 'audio/wav';

            Object.assign(audio, {
                status: 'ready',
                headline: normalizedSummary.headline,
                text: normalizedSummary.text,
                mood: normalizedSummary.mood,
                error: normalizedSummary.ttsError || (normalizedSummary.fallback ? 'Sto usando un riepilogo locale, ma l ascolto funziona comunque.' : null),
                estimatedSeconds: normalizedSummary.estimatedSeconds,
                analysisKey,
                source: normalizedSummary.fallback ? 'fallback' : 'remote',
                fallback: normalizedSummary.fallback,
                provider: normalizedSummary.provider || null,
                voice: normalizedSummary.voice || null,
                hasRemoteAudio: normalizedSummary.hasRemoteAudio,
                playbackMode: normalizedSummary.hasRemoteAudio ? 'remote-tts' : 'browser',
                ttsError: normalizedSummary.ttsError || ''
            });

            pushActivity(
                normalizedSummary.hasRemoteAudio
                    ? 'Riepilogo audio pronto con TTS remoto ClaraLex. Avvio la riproduzione.'
                    : normalizedSummary.fallback
                        ? 'Riepilogo audio pronto con una versione locale di sicurezza.'
                        : 'Riepilogo audio pronto. Avvio la lettura.',
                normalizedSummary.hasRemoteAudio ? 'success' : normalizedSummary.fallback ? 'warning' : 'success'
            );
        } catch (error) {
            const fallbackSummary = buildLocalAudioSummary(state.analysis);
            currentRemoteAudioData = '';
            currentRemoteAudioMimeType = 'audio/wav';
            Object.assign(audio, {
                status: 'ready',
                headline: fallbackSummary.headline,
                text: fallbackSummary.text,
                mood: fallbackSummary.mood,
                error: 'Uso un riepilogo locale per l audio, ma puoi ascoltarlo normalmente.',
                estimatedSeconds: fallbackSummary.estimatedSeconds,
                analysisKey,
                source: 'fallback',
                fallback: true,
                provider: null,
                voice: null,
                hasRemoteAudio: false,
                playbackMode: 'browser',
                ttsError: ''
            });
            pushActivity(`Riepilogo audio remoto non disponibile: ${error.message}. Passo a una versione locale.`, 'warning');
        }

        renderAnalysisPanel();
        if (audio.hasRemoteAudio && currentRemoteAudioData) {
            await playRemoteAudio(audio);
            return;
        }
        await speakAudioSummary(audio);
    }

    function getKnownReferences(clauses) {
        return Array.from(new Set(
            clauses.flatMap((clause) => Array.isArray(clause.references) ? clause.references : [])
        )).slice(0, MAX_KNOWN_REFERENCES);
    }

    function mergeClauseCollections(existingClauses, nextClauses) {
        const merged = [...existingClauses];
        let addedCount = 0;

        nextClauses.forEach((incomingClause, incomingIndex) => {
            const incomingReferences = normalizeReferences(incomingClause.references || [incomingClause.textToFind || incomingClause.quote || '']);
            const key = `${normalizeWhitespace(incomingClause.title).toLowerCase()}|${incomingReferences.join('|').toLowerCase()}`;
            const existingIndex = merged.findIndex((existingClause) => {
                const existingKey = `${normalizeWhitespace(existingClause.title).toLowerCase()}|${normalizeReferences(existingClause.references).join('|').toLowerCase()}`;
                return existingKey === key || incomingReferences.some((reference) => existingClause.references.includes(reference));
            });

            if (existingIndex !== -1) {
                const existingClause = merged[existingIndex];
                merged[existingIndex] = {
                    ...existingClause,
                    title: isGenericClauseTitle(existingClause.title) && !isGenericClauseTitle(incomingClause.title)
                        ? (incomingClause.title || existingClause.title)
                        : existingClause.title,
                    references: Array.from(new Set([...(existingClause.references || []), ...incomingReferences])),
                    clauseSummary: existingClause.clauseSummary || incomingClause.clauseSummary || incomingClause.description,
                    description: existingClause.description && existingClause.description.length >= (incomingClause.description || '').length
                        ? existingClause.description
                        : (incomingClause.description || existingClause.description),
                    whyItMatters: existingClause.whyItMatters && existingClause.whyItMatters.length >= (incomingClause.whyItMatters || '').length
                        ? existingClause.whyItMatters
                        : (incomingClause.whyItMatters || existingClause.whyItMatters),
                    userImpact: existingClause.userImpact || incomingClause.userImpact,
                    riskLabel: existingClause.riskLabel || incomingClause.riskLabel,
                    legalBasis: existingClause.legalBasis || incomingClause.legalBasis,
                    legalReasoning: existingClause.legalReasoning || incomingClause.legalReasoning,
                    type: normalizeRiskLevel(existingClause.type === 'danger' ? 'danger' : incomingClause.type || existingClause.type),
                    occurrenceCount: 0
                };
                return;
            }

            merged.push({
                ...incomingClause,
                id: incomingClause.id || `claralex-clause-${merged.length + incomingIndex + 1}`,
                references: incomingReferences,
                textToFind: incomingReferences[0] || incomingClause.textToFind,
                quote: incomingReferences[0] || incomingClause.quote,
                occurrenceCount: 0
            });
            addedCount += 1;
        });

        return {
            clauses: merged,
            addedCount
        };
    }

    function summarizeProgress(analysis) {
        const triage = analysis.triage || computeTriage(analysis.clauses || []);
        const parts = [];

        if (triage.danger) parts.push(`${triage.danger} rosse`);
        if (triage.warning) parts.push(`${triage.warning} gialle`);
        if (triage.success) parts.push(`${triage.success} verdi`);

        const progress = analysis.progress;
        const progressText = progress
            ? `Blocco ${progress.chunkIndex}/${progress.chunkCount}, passaggio ${progress.passIndex}, ${progress.batchesCompleted} lotti completati.`
            : '';

        return parts.length > 0
            ? `${progressText} Trovate finora ${parts.join(', ')}.`
            : `${progressText} Nessuna clausola trovata per ora.`;
    }

    function finalizeAggregateAnalysis(analysis, heuristics) {
        const triage = computeTriage(analysis.clauses || []);
        const riskyCount = (triage.danger || 0) + (triage.warning || 0);

        analysis.triage = triage;
        analysis.riskLevel = triage.danger > 0 ? 'danger' : triage.warning > 0 ? 'warning' : triage.success > 0 ? 'success' : 'info';
        analysis.isContractLike = heuristics?.isCandidate || (analysis.clauses || []).length > 0;
        analysis.summary = riskyCount > 0
            ? `Analisi completata: trovate ${triage.danger || 0} clausole rosse, ${triage.warning || 0} gialle e ${triage.success || 0} verdi.`
            : `Analisi completata: nessuna clausola critica forte trovata, ${triage.success || 0} punti verdi evidenziati.`;
        analysis.suggestedAction = analysis.riskLevel === 'danger'
            ? 'Leggi con calma i punti rossi prima di accettare o confermare.'
            : analysis.riskLevel === 'warning'
                ? 'Controlla soprattutto i punti gialli su rinnovi, prezzo e recesso.'
                : 'Puoi usare il pannello per rivedere tutte le frasi evidenziate.';
        analysis.progress = {
            ...(analysis.progress || {}),
            done: true
        };
        return analysis;
    }

    function buildAnalysisWindows(text) {
        const normalized = normalizeWhitespace(text);
        if (!normalized) {
            return [];
        }

        if (normalized.length <= ANALYSIS_WINDOW_CHARS) {
            return [normalized];
        }

        const windows = [];
        let start = 0;

        while (start < normalized.length) {
            let end = Math.min(normalized.length, start + ANALYSIS_WINDOW_CHARS);
            if (end < normalized.length) {
                const candidate = normalized.slice(start, end);
                const punctuationIndex = Math.max(
                    candidate.lastIndexOf('. '),
                    candidate.lastIndexOf('; '),
                    candidate.lastIndexOf(': ')
                );
                if (punctuationIndex > ANALYSIS_WINDOW_CHARS * 0.55) {
                    end = start + punctuationIndex + 1;
                }
            }

            const windowText = normalizeWhitespace(normalized.slice(start, end));
            if (windowText.length >= 120) {
                windows.push(windowText);
            }

            if (end >= normalized.length) {
                break;
            }

            start = Math.max(end - ANALYSIS_WINDOW_OVERLAP, start + 1);
        }

        return windows;
    }

    function removeExistingHighlights() {
        document.querySelectorAll(`${HIGHLIGHT_TAG}.${HIGHLIGHT_CLASS}`).forEach((mark) => {
            const parent = mark.parentNode;
            if (!parent) return;
            parent.replaceChild(document.createTextNode(mark.textContent), mark);
            parent.normalize();
        });
    }

    function collectTextNodes(root = document.body) {
        if (!root) return [];
        const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
            acceptNode: (node) => {
                const parentTag = node.parentNode?.tagName;
                if (!parentTag) return NodeFilter.FILTER_REJECT;
                if (['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'OPTION', HIGHLIGHT_TAG, 'BUTTON'].includes(parentTag)) return NodeFilter.FILTER_REJECT;
                if (node.parentNode?.closest(`#${ANALYSIS_PANEL_ID}, #${STATUS_WIDGET_ID}`)) return NodeFilter.FILTER_REJECT;
                if (!normalizeWhitespace(node.textContent || '')) return NodeFilter.FILTER_REJECT;
                return NodeFilter.FILTER_ACCEPT;
            }
        });
        const textNodes = [];
        let currentNode;
        while ((currentNode = walker.nextNode())) textNodes.push(currentNode);
        return textNodes;
    }

    function findAllMatchesInText(text, textToFind) {
        const cleanedNeedle = normalizeWhitespace(textToFind);
        if (!cleanedNeedle) return [];
        const regex = new RegExp(escapeRegExp(cleanedNeedle).replace(/\s+/g, '\\s+'), 'gi');
        const matches = [];
        let match;
        let guard = 0;
        while ((match = regex.exec(text)) && guard < MAX_REFERENCE_MATCHES_PER_NODE) {
            matches.push({ start: match.index, end: match.index + match[0].length, matchText: match[0] });
            if (match[0].length === 0) regex.lastIndex += 1;
            guard += 1;
        }
        return matches;
    }

    function collectMatchesForNode(text, clauses) {
        const candidates = [];
        const seen = new Set();
        clauses.forEach((clause) => {
            clause.references.forEach((reference, referenceIndex) => {
                const variants = buildReferenceVariants(reference);
                variants.forEach((variant) => findAllMatchesInText(text, variant).forEach((match) => {
                    const key = `${clause.id}:${match.start}:${match.end}:${match.matchText.toLowerCase()}`;
                    if (seen.has(key)) return;
                    seen.add(key);
                    candidates.push({ ...match, clauseId: clause.id, type: clause.type, title: clause.title, description: clause.description, legalReasoning: clause.legalReasoning, referenceIndex });
                }));
            });
        });
        candidates.sort((left, right) => left.start - right.start || (right.end - right.start) - (left.end - left.start));
        const accepted = [];
        let currentEnd = -1;
        candidates.forEach((candidate) => {
            if (candidate.start < currentEnd) return;
            accepted.push(candidate);
            currentEnd = candidate.end;
        });
        return accepted;
    }

    function addMarkInteraction(mark, clauseId, referenceIndex) {
        const activate = (event) => {
            event.preventDefault();
            event.stopPropagation();
            setActiveClauseState(clauseId, referenceIndex, { expand: true });
            openAnalysisPanel();
            pulseElement(mark, 'claralex-highlight--active');
            focusAnalysisCard(clauseId, true);
        };
        mark.addEventListener('click', activate);
        mark.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' || event.key === ' ') activate(event);
        });
    }

    function processDOM(analysis, root = document.body) {
        if (!root || !Array.isArray(analysis?.clauses) || analysis.clauses.length === 0) return analysis;
        const textNodes = collectTextNodes(root);
        const occurrenceByClause = Object.fromEntries(analysis.clauses.map((clause) => [clause.id, 0]));
        textNodes.forEach((node) => {
            const text = node.textContent || '';
            const matches = collectMatchesForNode(text, analysis.clauses);
            if (matches.length === 0 || !node.parentNode) return;
            const fragment = document.createDocumentFragment();
            let cursor = 0;
            matches.forEach((match) => {
                if (match.start > cursor) fragment.appendChild(document.createTextNode(text.slice(cursor, match.start)));
                const mark = document.createElement(HIGHLIGHT_TAG);
                mark.className = `${HIGHLIGHT_CLASS} highlight-${match.type}`;
                mark.textContent = match.matchText;
                mark.setAttribute('role', 'button');
                mark.tabIndex = 0;
                mark.dataset.clauseId = match.clauseId;
                mark.dataset.referenceIndex = String(match.referenceIndex);
                occurrenceByClause[match.clauseId] += 1;
                mark.dataset.occurrence = String(occurrenceByClause[match.clauseId]);
                const tooltipParts = [match.title, match.description, match.legalReasoning].map((part) => normalizeWhitespace(part)).filter(Boolean);
                if (tooltipParts.length > 0) mark.title = tooltipParts.join(' - ');
                addMarkInteraction(mark, match.clauseId, match.referenceIndex);
                fragment.appendChild(mark);
                cursor = match.end;
            });
            if (cursor < text.length) fragment.appendChild(document.createTextNode(text.slice(cursor)));
            node.parentNode.replaceChild(fragment, node);
        });
        analysis.clauses = analysis.clauses.map((clause) => ({ ...clause, occurrenceCount: occurrenceByClause[clause.id] || 0 }));
        analysis.triage = computeTriage(analysis.clauses);
        return analysis;
    }

    const getMarksForClause = (clauseId) => Array.from(document.querySelectorAll(`${HIGHLIGHT_TAG}.${HIGHLIGHT_CLASS}[data-clause-id="${clauseId}"]`));
    const normalizeReferenceIndex = (value) => {
        const parsed = Number.parseInt(value, 10);
        return Number.isInteger(parsed) && parsed >= 0 ? parsed : null;
    };

    function setActiveClauseState(clauseId, referenceIndex = null, options = {}) {
        const clauseChanged = state.activeClauseId !== clauseId;
        state.activeClauseId = clauseId;
        if (options.expand) {
            state.expandedClauseId = clauseId;
        }
        if (referenceIndex !== null && Number.isInteger(referenceIndex) && referenceIndex >= 0) {
            state.activeReferenceIndex = referenceIndex;
            return;
        }
        if (clauseChanged) {
            state.activeReferenceIndex = null;
        }
    }

    function toggleClauseExpansion(clauseId) {
        if (!clauseId) {
            return;
        }

        if (state.expandedClauseId === clauseId) {
            state.expandedClauseId = null;
            renderAnalysisPanel();
            return;
        }

        const referenceIndex = state.activeClauseId === clauseId ? state.activeReferenceIndex : null;
        setActiveClauseState(clauseId, referenceIndex, { expand: true });
        renderAnalysisPanel();
        focusAnalysisCard(clauseId, true);
    }

    function getClausePreview(clause) {
        const previewSource = normalizeWhitespace(clause.clauseSummary || clause.description || clause.legalReasoning || clause.references?.[0] || '');
        if (!previewSource) {
            return '';
        }
        return previewSource.length > 180 ? `${previewSource.slice(0, 177)}...` : previewSource;
    }

    function pulseElement(element, className) {
        if (!element) return;
        element.classList.remove(className);
        void element.offsetWidth;
        element.classList.add(className);
        window.setTimeout(() => element.classList.remove(className), 1800);
    }

    function focusAnalysisCard(clauseId, shouldScroll) {
        const panel = ensureAnalysisPanel();
        panel.querySelectorAll('.claralex-analysis-card').forEach((card) => {
            card.classList.toggle('claralex-analysis-card--active', card.dataset.clauseId === clauseId);
        });
        const targetCard = panel.querySelector(`.claralex-analysis-card[data-clause-id="${clauseId}"]`);
        if (!targetCard) return false;
        if (shouldScroll) targetCard.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
        pulseElement(targetCard, 'claralex-analysis-card--pulse');
        return true;
    }

    function focusClauseInText(clauseId, options = {}) {
        const marks = getMarksForClause(clauseId);
        if (marks.length === 0) return false;
        const referenceIndex = normalizeReferenceIndex(options.referenceIndex);
        const referenceMarks = referenceIndex === null
            ? marks
            : marks.filter((mark) => normalizeReferenceIndex(mark.dataset.referenceIndex) === referenceIndex);
        const targetMarks = referenceMarks.length > 0 ? referenceMarks : marks;
        const cycleKey = referenceIndex === null ? clauseId : `${clauseId}:${referenceIndex}`;
        const shouldCycle = options.shouldCycle === true;
        const nextIndex = shouldCycle ? (state.focusCycles[cycleKey] || 0) % targetMarks.length : 0;
        state.focusCycles[cycleKey] = (nextIndex + 1) % targetMarks.length;
        setActiveClauseState(clauseId, referenceIndex, { expand: true });
        renderAnalysisPanel();
        const target = targetMarks[nextIndex];
        target.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
        pulseElement(target, 'claralex-highlight--active');
        focusAnalysisCard(clauseId, true);
        return true;
    }

    function createTriageMarkup(triage) {
        return [
            { type: 'danger', label: 'Rosse', count: triage?.danger || 0 },
            { type: 'warning', label: 'Gialle', count: triage?.warning || 0 },
            { type: 'success', label: 'Verdi', count: triage?.success || 0 }
        ].map((item) => `<div class="claralex-triage-card claralex-triage-card--${item.type}"><span class="claralex-triage-card__count">${item.count}</span><span class="claralex-triage-card__label">${item.label}</span></div>`).join('');
    }

    function createClauseMarkup(clause) {
        const meta = [];
        if (clause.occurrenceCount > 0) meta.push(`${clause.occurrenceCount} evidenziazioni nel testo`);
        if (clause.references.length > 1) meta.push(`${clause.references.length} citazioni`);
        const isExpanded = state.expandedClauseId === clause.id;
        const isActive = state.activeClauseId === clause.id;
        const preferredReferenceIndex = isActive && Number.isInteger(state.activeReferenceIndex) ? state.activeReferenceIndex : 0;
        const preview = getClausePreview(clause);
        const quoteMarkup = clause.references.map((reference, referenceIndex) => {
            const isReferenceActive = isActive && state.activeReferenceIndex === referenceIndex;
            return `<button type="button" class="claralex-analysis-card__quote${isReferenceActive ? ' claralex-analysis-card__quote--active' : ''}" data-claralex-action="focus-reference" data-clause-id="${clause.id}" data-reference-index="${referenceIndex}">"${escapeHtml(reference)}"</button>`;
        }).join('');
        const badge = `<span class="claralex-analysis-card__badge claralex-analysis-card__badge--${clause.type}">${escapeHtml(clause.riskLabel || 'Punto')}</span>`;
        const summaryMarkup = clause.clauseSummary ? `<div class="claralex-analysis-card__summary">${escapeHtml(clause.clauseSummary)}</div>` : '';
        const descriptionMarkup = clause.description ? `<div class="claralex-analysis-card__description">${badge}<span>${escapeHtml(clause.description)}</span></div>` : badge;
        const reasoningMarkup = clause.legalReasoning ? `<div class="claralex-analysis-card__reason">${escapeHtml(clause.legalReasoning)}</div>` : '';
        const quotesSectionMarkup = quoteMarkup
            ? `<div class="claralex-analysis-card__quotes"><div class="claralex-analysis-card__quotes-label">Citazioni navigabili</div>${quoteMarkup}</div>`
            : '<div class="claralex-analysis-empty">Nessuna frase citata disponibile per questa clausola.</div>';
        const ctaLabel = isExpanded ? 'Vai al punto nel testo' : 'Apri e vai al testo';

        return `<article class="claralex-analysis-card claralex-analysis-card--${clause.type}${isExpanded ? ' claralex-analysis-card--expanded' : ''}${isActive ? ' claralex-analysis-card--active' : ''}" data-clause-id="${clause.id}" data-claralex-action="open-clause" data-reference-index="${preferredReferenceIndex}" tabindex="0" aria-expanded="${isExpanded ? 'true' : 'false'}"><div class="claralex-analysis-card__header"><div><div class="claralex-analysis-card__title">${escapeHtml(clause.title)}</div><div class="claralex-analysis-card__meta">${escapeHtml(meta.join(' | ') || 'Apri la card per leggere tutta l analisi')}</div></div><div class="claralex-analysis-card__actions"><button type="button" class="claralex-inline-button" data-claralex-action="focus-clause" data-clause-id="${clause.id}" data-reference-index="${preferredReferenceIndex}">${ctaLabel}</button><button type="button" class="claralex-inline-button claralex-inline-button--secondary" data-claralex-action="toggle-clause" data-clause-id="${clause.id}">${isExpanded ? 'Riduci' : 'Approfondisci'}</button></div></div>${preview ? `<div class="claralex-analysis-card__preview">${escapeHtml(preview)}</div>` : ''}<div class="claralex-analysis-card__body"${isExpanded ? '' : ' hidden'}>${summaryMarkup}${descriptionMarkup}${reasoningMarkup}${quotesSectionMarkup}</div></article>`;
    }

    function createSummaryMarkup(analysis) {
        const headline = escapeHtml(analysis?.investorHeadline || 'Brief ClaraLex');
        const summary = escapeHtml(analysis?.summary || 'Analisi pronta.');
        const clauseCount = Array.isArray(analysis?.clauses) ? analysis.clauses.length : 0;
        const riskLabel = analysis?.riskLevel === 'danger' ? 'Alta priorita' : analysis?.riskLevel === 'warning' ? 'Attenzione' : analysis?.riskLevel === 'success' ? 'Favorevole' : 'Informativa';
        return `<div class="claralex-summary-card claralex-summary-card--${escapeHtml(analysis?.riskLevel || 'info')}"><div class="claralex-summary-card__eyebrow">${headline}</div><div class="claralex-summary-card__body">${summary}</div><div class="claralex-summary-card__meta">${escapeHtml(riskLabel)}${clauseCount ? ` | ${clauseCount} punti ordinati per priorita` : ''}</div></div>`;
    }

    function createActionMarkup(analysis) {
        const action = escapeHtml(analysis?.suggestedAction || 'Apri una clausola per vedere subito il punto esatto nel testo.');
        return `<div class="claralex-action-card"><div class="claralex-action-card__label">Cosa fare adesso</div><div class="claralex-action-card__body">${action}</div></div>`;
    }
    function createActivityMarkup(activityLog) {
        const items = Array.isArray(activityLog) ? activityLog.slice(-6) : [];
        if (items.length === 0) {
            return '<div class="claralex-analysis-empty">Nessun log disponibile per ora.</div>';
        }

        return items.map((item) => `<div class="claralex-activity-item claralex-activity-item--${item.tone || 'info'}"><span class="claralex-activity-item__time">${escapeHtml(item.timestamp || '')}</span><span class="claralex-activity-item__text">${escapeHtml(item.message || '')}</span></div>`).join('');
    }

    function ensureStatusWidget() {
        let widget = document.getElementById(STATUS_WIDGET_ID);
        if (widget) return widget;
        widget = document.createElement('aside');
        widget.id = STATUS_WIDGET_ID;
        widget.className = 'claralex-status claralex-status--hidden';
        widget.innerHTML = '<div class="claralex-status__header"><div class="claralex-status__title"></div><button type="button" class="claralex-status__close" data-claralex-action="hide-widget" aria-label="Nascondi ClaraLex">x</button></div><div class="claralex-status__body"></div><div class="claralex-status__actions"><button type="button" class="claralex-button claralex-button--light" data-claralex-action="toggle-panel">Vedi analisi</button></div>';
        widget.addEventListener('click', (event) => {
            const action = event.target.closest('[data-claralex-action]')?.dataset.claralexAction;
            if (action === 'toggle-panel') state.panelOpen ? closeAnalysisPanel() : openAnalysisPanel();
            if (action === 'hide-widget') hideFloatingUi();
        });
        (document.body || document.documentElement).appendChild(widget);
        return widget;
    }

    function ensureStatusDock() {
        let dock = document.getElementById(STATUS_DOCK_ID);
        if (dock) return dock;
        dock = document.createElement('button');
        dock.id = STATUS_DOCK_ID;
        dock.type = 'button';
        dock.className = 'claralex-dock claralex-dock--hidden';
        dock.textContent = 'ClaraLex';
        dock.addEventListener('click', () => showFloatingUi());
        (document.body || document.documentElement).appendChild(dock);
        return dock;
    }

    function ensureAnalysisPanel() {
        let panel = document.getElementById(ANALYSIS_PANEL_ID);
        if (panel) return panel;
        panel = document.createElement('aside');
        panel.id = ANALYSIS_PANEL_ID;
        panel.className = 'claralex-panel claralex-panel--hidden';
        panel.innerHTML = '<div class="claralex-panel__header"><div><div class="claralex-panel__eyebrow">ClaraLex</div><div class="claralex-panel__title">Analisi pagina</div></div><button type="button" class="claralex-icon-button" data-claralex-action="close-panel" aria-label="Chiudi analisi">x</button></div><div class="claralex-panel__body"><div class="claralex-panel__summary"></div><div class="claralex-panel__triage"></div><div class="claralex-panel__action"></div><div class="claralex-panel__tools"><button type="button" class="claralex-tool-button claralex-tool-button--primary" data-claralex-action="generate-audio">Genera audio</button><button type="button" class="claralex-tool-button" data-claralex-action="focus-top">Vai al primo punto</button></div><div class="claralex-panel__audio"></div><div class="claralex-panel__activity"></div><div class="claralex-panel__clauses"></div></div>'; 
        panel.addEventListener('click', (event) => {
            const actionTarget = event.target.closest('[data-claralex-action]');
            if (!actionTarget) return;
            const action = actionTarget.dataset.claralexAction;
            if (action === 'close-panel') {
                closeAnalysisPanel();
                return;
            }
            if (action === 'open-clause') {
                focusClauseInText(actionTarget.dataset.clauseId, { shouldCycle: false, referenceIndex: actionTarget.dataset.referenceIndex });
                return;
            }
            if (action === 'focus-clause') {
                focusClauseInText(actionTarget.dataset.clauseId, { shouldCycle: false, referenceIndex: actionTarget.dataset.referenceIndex });
                return;
            }
            if (action === 'focus-reference') {
                focusClauseInText(actionTarget.dataset.clauseId, { shouldCycle: false, referenceIndex: actionTarget.dataset.referenceIndex });
                return;
            }
            if (action === 'toggle-clause') {
                toggleClauseExpansion(actionTarget.dataset.clauseId);
                return;
            }
            if (action === 'generate-audio') {
                handleGenerateAudio().catch((error) => {
                    const audio = ensureAudioState();
                    audio.status = 'ready';
                    audio.isSpeaking = false;
                    audio.error = error.message;
                    pushActivity(`Audio non disponibile: ${error.message}`, 'warning');
                    renderAnalysisPanel();
                });
                return;
            }
            if (action === 'focus-top') {
                const firstClause = state.analysis?.clauses?.[0];
                if (firstClause?.id) {
                    focusClauseInText(firstClause.id, { shouldCycle: false, referenceIndex: 0 });
                }
                return;
            }
        });
        panel.addEventListener('keydown', (event) => {
            const card = event.target.closest('.claralex-analysis-card[data-clause-id]');
            if (!card || ['BUTTON', 'A'].includes(event.target.tagName)) {
                return;
            }
            if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                focusClauseInText(card.dataset.clauseId, { shouldCycle: false, referenceIndex: card.dataset.referenceIndex });
            }
        });
        (document.body || document.documentElement).appendChild(panel);
        return panel;
    }

    function getStatusPresentation() {
        if (state.status === 'analyzing') {
            const latestActivity = state.analysis?.activityLog?.slice(-1)?.[0]?.message;
            const partialSummary = latestActivity || (state.analysis ? summarizeProgress(state.analysis) : 'Sto controllando clausole, rinnovi, limiti di responsabilita e conferme da accettare.');
            return {
                tone: state.analysis?.triage?.danger > 0 ? 'danger' : state.analysis?.triage?.warning > 0 ? 'warning' : 'info',
                title: 'ClaraLex sta analizzando la pagina',
                body: partialSummary,
                canOpenPanel: Boolean(state.analysis)
            };
        }
        if (state.status === 'error') return { tone: 'danger', title: 'ClaraLex non riesce ad analizzare la pagina', body: state.error || 'Controlla backend e chiave API.', canOpenPanel: false };
        if (state.status === 'done' && state.analysis) {
            const triage = state.analysis.triage || computeTriage(state.analysis.clauses || []);
            const warningCount = (triage.danger || 0) + (triage.warning || 0);
            if (!state.analysis.isContractLike) return { tone: 'info', title: 'ClaraLex: pagina non contrattuale', body: state.analysis.summary || 'La pagina non sembra un contratto rilevante.', canOpenPanel: true };
            if (warningCount > 0) return { tone: state.analysis.riskLevel === 'danger' ? 'danger' : 'warning', title: `ClaraLex: ${warningCount} punto${warningCount > 1 ? 'i' : ''} da rileggere`, body: state.analysis.summary || 'Apri il pannello per vedere triage e frasi evidenziate.', canOpenPanel: true };
            return { tone: state.analysis.riskLevel || 'success', title: 'ClaraLex: analisi pronta', body: state.analysis.summary || 'Apri il pannello per vedere triage e frasi evidenziate.', canOpenPanel: true };
        }
        return null;
    }

    function hideFloatingUi() {
        state.widgetHidden = true;
        state.panelOpen = false;
        renderStatusWidget();
        renderAnalysisPanel();
    }

    function showFloatingUi() {
        state.widgetHidden = false;
        renderStatusWidget();
        if (state.analysis) {
            openAnalysisPanel();
        }
    }

    function renderStatusWidget() {
        const widget = ensureStatusWidget();
        const dock = ensureStatusDock();
        const presentation = getStatusPresentation();
        if (!presentation) {
            widget.className = 'claralex-status claralex-status--hidden';
            dock.className = 'claralex-dock claralex-dock--hidden';
            return;
        }
        if (state.widgetHidden) {
            widget.className = 'claralex-status claralex-status--hidden';
            dock.className = `claralex-dock claralex-dock--${presentation.tone}`;
            dock.textContent = `ClaraLex ${presentation.tone === 'danger' ? 'rosso' : presentation.tone === 'warning' ? 'giallo' : 'attivo'}`;
            return;
        }
        widget.className = `claralex-status claralex-status--${presentation.tone}`;
        dock.className = 'claralex-dock claralex-dock--hidden';
        widget.querySelector('.claralex-status__title').textContent = presentation.title;
        widget.querySelector('.claralex-status__body').textContent = presentation.body;
        const button = widget.querySelector('[data-claralex-action="toggle-panel"]');
        button.hidden = !presentation.canOpenPanel;
        button.textContent = state.panelOpen ? 'Nascondi analisi' : 'Vedi analisi';
    }

    function renderAnalysisPanel() {
        const panel = ensureAnalysisPanel();
        if (!state.panelOpen) {
            panel.className = 'claralex-panel claralex-panel--hidden';
            return;
        }
        panel.className = 'claralex-panel claralex-panel--open';
        const triageNode = panel.querySelector('.claralex-panel__triage');
        const summaryNode = panel.querySelector('.claralex-panel__summary');
        const actionNode = panel.querySelector('.claralex-panel__action');
        const audioNode = panel.querySelector('.claralex-panel__audio');
        const activityNode = panel.querySelector('.claralex-panel__activity');
        const clausesNode = panel.querySelector('.claralex-panel__clauses');
        const audioButton = panel.querySelector('[data-claralex-action="generate-audio"]');
        if (audioButton) {
            audioButton.textContent = getAudioButtonLabel();
            audioButton.disabled = ensureAudioState().status === 'loading';
        }
        if (state.status === 'analyzing') {
            triageNode.innerHTML = createTriageMarkup(state.analysis?.triage || computeTriage(state.analysis?.clauses || []));
            summaryNode.innerHTML = createSummaryMarkup(state.analysis || {});
            actionNode.innerHTML = createActionMarkup({ suggestedAction: summarizeProgress(state.analysis || createEmptyAnalysisState(1)) });
            audioNode.innerHTML = createAudioMarkup(ensureAudioState());
            activityNode.innerHTML = createActivityMarkup(state.analysis?.activityLog || []);
            clausesNode.innerHTML = Array.isArray(state.analysis?.clauses) && state.analysis.clauses.length > 0
                ? state.analysis.clauses.map(createClauseMarkup).join('')
                : '<div class="claralex-analysis-empty">I risultati compariranno qui man mano che arrivano i lotti successivi.</div>';
            return;
        }
        if (state.status === 'error') {
            triageNode.innerHTML = '';
            summaryNode.innerHTML = createSummaryMarkup({ investorHeadline: 'Analisi non disponibile', summary: 'Il motore ClaraLex non ha restituito un risultato leggibile.', riskLevel: 'warning', clauses: [] });
            actionNode.innerHTML = createActionMarkup({ suggestedAction: state.error || 'Riprova tra pochi secondi o rilancia l analisi dalla popup.' });
            audioNode.innerHTML = createAudioMarkup(ensureAudioState());
            activityNode.innerHTML = createActivityMarkup(state.analysis?.activityLog || []);
            clausesNode.innerHTML = '';
            return;
        }
        if (!state.analysis) {
            triageNode.innerHTML = '';
            summaryNode.innerHTML = createSummaryMarkup({ investorHeadline: 'ClaraLex pronto', summary: 'Apri una pagina da controllare e ClaraLex si preparera solo se il contesto contrattuale e forte.', riskLevel: 'info', clauses: [] });
            actionNode.innerHTML = createActionMarkup({ suggestedAction: 'Se vuoi una demo guidata, usa il popup e premi Analizza adesso su una pagina con termini, checkout o rinnovi.' });
            audioNode.innerHTML = createAudioMarkup(ensureAudioState());
            activityNode.innerHTML = '';
            clausesNode.innerHTML = '';
            return;
        }
        triageNode.innerHTML = createTriageMarkup(state.analysis.triage || computeTriage(state.analysis.clauses || []));
        summaryNode.innerHTML = createSummaryMarkup(state.analysis);
        actionNode.innerHTML = createActionMarkup(state.analysis);
        audioNode.innerHTML = createAudioMarkup(ensureAudioState());
        activityNode.innerHTML = createActivityMarkup(state.analysis.activityLog || []);
        if (!state.analysis.isContractLike) {
            clausesNode.innerHTML = '<div class="claralex-analysis-empty">La pagina non sembra un contratto o una conferma importante, ma puoi forzare una nuova analisi dalla popup.</div>';
            return;
        }
        if (!Array.isArray(state.analysis.clauses) || state.analysis.clauses.length === 0) {
            clausesNode.innerHTML = '<div class="claralex-analysis-empty">Nessuna clausola specifica evidenziata in questa analisi.</div>';
            return;
        }
        clausesNode.innerHTML = state.analysis.clauses.map(createClauseMarkup).join('');
        if (state.activeClauseId) focusAnalysisCard(state.activeClauseId, false);
    }

    const openAnalysisPanel = () => { state.panelOpen = true; state.widgetHidden = false; renderStatusWidget(); renderAnalysisPanel(); };
    const closeAnalysisPanel = () => { state.panelOpen = false; renderStatusWidget(); renderAnalysisPanel(); };

    async function clearBadge() {
        try {
            await sendRuntimeMessage({ action: 'claralex.clearBadge' });
        } catch (error) {
            console.warn('ClaraLex: badge non aggiornato.', error);
        }
    }

    async function runScan(options = {}) {
        if (currentScanPromise) return currentScanPromise;
        currentScanPromise = executeScan(options).finally(() => { currentScanPromise = null; });
        return currentScanPromise;
    }

    async function executeScan({ trigger = 'manual', force = false } = {}) {
        const heuristics = analyzePageHeuristics();
        state.heuristics = { isCandidate: heuristics.isCandidate, score: heuristics.score, reasons: heuristics.reasons, keywordHits: heuristics.keywordHits };
        if (!force && !heuristics.isCandidate) {
            state.status = 'skipped';
            state.error = null;
            state.analysis = null;
            resetAudioState();
            state.activeClauseId = null;
            state.expandedClauseId = null;
            state.activeReferenceIndex = null;
            state.focusCycles = {};
            state.panelOpen = false;
            removeExistingHighlights();
            renderStatusWidget();
            renderAnalysisPanel();
            await clearBadge();
            return getScanState();
        }
        state.status = 'analyzing';
        state.error = null;
        state.analysis = createEmptyAnalysisState(buildAnalysisWindows(heuristics.pageText).length || 1);
        resetAudioState();
        state.activeClauseId = null;
        state.expandedClauseId = null;
        state.activeReferenceIndex = null;
        state.focusCycles = {};
        pushActivity('Analisi avviata. Inizio dalla parte alta della pagina.', 'info');
        renderStatusWidget();
        renderAnalysisPanel();
        try {
            const windows = buildAnalysisWindows(heuristics.pageText);
            if (windows.length === 0) {
                finalizeAggregateAnalysis(state.analysis, heuristics);
                state.status = 'done';
                renderStatusWidget();
                renderAnalysisPanel();
                return getScanState();
            }

            for (let chunkIndex = 0; chunkIndex < windows.length; chunkIndex += 1) {
                let passIndex = 0;
                while (passIndex < MAX_PASSES_PER_WINDOW) {
                    state.analysis.progress = {
                        chunkIndex: chunkIndex + 1,
                        chunkCount: windows.length,
                        passIndex: passIndex + 1,
                        batchSize: ANALYSIS_BATCH_SIZE,
                        batchesCompleted: state.analysis.progress?.batchesCompleted || 0
                    };
                    state.analysis.summary = `Analisi progressiva ${chunkIndex + 1}/${windows.length} in corso.`;
                    state.analysis.suggestedAction = 'Le clausole trovate vengono aggiunte man mano.';
                    pushActivity(`Esamino blocco ${chunkIndex + 1} di ${windows.length}, passaggio ${passIndex + 1}.`, 'info');
                    renderStatusWidget();
                    renderAnalysisPanel();

                    const response = await sendRuntimeMessage({
                        action: 'claralex.analyze',
                        payload: {
                            text: windows[chunkIndex],
                            title: heuristics.title,
                            url: location.href,
                            trigger,
                            batchSize: ANALYSIS_BATCH_SIZE,
                            chunkIndex: chunkIndex + 1,
                            chunkCount: windows.length,
                            passIndex: passIndex + 1,
                            knownReferences: getKnownReferences(state.analysis.clauses),
                            heuristics: {
                                score: heuristics.score,
                                reasons: heuristics.reasons,
                                keywordHits: heuristics.keywordHits,
                                interactiveText: heuristics.interactiveText
                            }
                        }
                    });

                    if (!response?.ok) {
                        throw new Error(response?.error || 'Analisi non disponibile.');
                    }

                    const batchAnalysis = hydrateAnalysis(response.data);
                    const merged = mergeClauseCollections(state.analysis.clauses, batchAnalysis.clauses || []);
                    state.analysis.clauses = merged.clauses;
                    state.analysis.triage = computeTriage(state.analysis.clauses);
                    state.analysis.riskLevel = state.analysis.triage.danger > 0 ? 'danger' : state.analysis.triage.warning > 0 ? 'warning' : state.analysis.triage.success > 0 ? 'success' : 'info';
                    state.analysis.isContractLike = state.analysis.isContractLike || batchAnalysis.isContractLike || merged.addedCount > 0;
                    state.analysis.pageType = batchAnalysis.pageType || state.analysis.pageType;
                    state.analysis.summary = summarizeProgress(state.analysis);
                    state.analysis.suggestedAction = batchAnalysis.suggestedAction || state.analysis.suggestedAction;
                    state.analysis.progress = {
                        chunkIndex: chunkIndex + 1,
                        chunkCount: windows.length,
                        passIndex: passIndex + 1,
                        batchSize: ANALYSIS_BATCH_SIZE,
                        batchesCompleted: (state.analysis.progress?.batchesCompleted || 0) + 1
                    };

                    if (merged.addedCount > 0) {
                        pushActivity(`Blocco ${chunkIndex + 1}: aggiunte ${merged.addedCount} clausole nuove.`, batchAnalysis.riskLevel || 'info');
                        removeExistingHighlights();
                        if (state.analysis.clauses.length > 0) {
                            processDOM(state.analysis);
                        }
                    } else {
                        pushActivity(`Blocco ${chunkIndex + 1}: nessuna clausola nuova in questo passaggio.`, 'info');
                    }

                    renderStatusWidget();
                    renderAnalysisPanel();

                    if (state.analysis.clauses.length >= MAX_TOTAL_CLAUSES) {
                        pushActivity(`Raggiunto il limite di ${MAX_TOTAL_CLAUSES} punti piu rilevanti per mantenere l analisi leggibile e veloce.`, 'success');
                        break;
                    }

                    if (!response.data?.hasMoreInChunk || merged.addedCount === 0) {
                        break;
                    }

                    passIndex += 1;
                }
            }

            finalizeAggregateAnalysis(state.analysis, heuristics);
            pushActivity('Analisi completata. Nessuna clausola gia analizzata e stata ripetuta.', 'success');
            state.status = 'done';
            renderStatusWidget();
            renderAnalysisPanel();
            return getScanState();
        } catch (error) {
            state.status = 'error';
            state.error = error.message;
            state.analysis = null;
            resetAudioState();
            state.activeClauseId = null;
            state.expandedClauseId = null;
            state.activeReferenceIndex = null;
            state.focusCycles = {};
            removeExistingHighlights();
            renderStatusWidget();
            renderAnalysisPanel();
            await clearBadge();
            return getScanState();
        }
    }

    function getScanState() {
        return { status: state.status, error: state.error, analysis: state.analysis, heuristics: state.heuristics, panelOpen: state.panelOpen, widgetHidden: state.widgetHidden, activeClauseId: state.activeClauseId, expandedClauseId: state.expandedClauseId, activeReferenceIndex: state.activeReferenceIndex, audio: state.audio, url: location.href, title: document.title || '' };
    }

    function resetForNavigation() {
        state.status = 'idle';
        state.error = null;
        state.analysis = null;
        state.heuristics = null;
        state.panelOpen = false;
        resetAudioState();
        state.activeClauseId = null;
        state.expandedClauseId = null;
        state.activeReferenceIndex = null;
        state.focusCycles = {};
        removeExistingHighlights();
        renderStatusWidget();
        renderAnalysisPanel();
        clearBadge();
    }

    function scheduleAutoScan(reason, delay = AUTO_SCAN_DELAY_MS) {
        const heuristics = analyzePageHeuristics();
        if (!heuristics.isCandidate) {
            state.heuristics = { isCandidate: heuristics.isCandidate, score: heuristics.score, reasons: heuristics.reasons, keywordHits: heuristics.keywordHits };
            state.status = 'skipped';
            state.analysis = null;
            renderStatusWidget();
            renderAnalysisPanel();
            return;
        }
        window.clearTimeout(state.pendingTimer);
        state.pendingTimer = window.setTimeout(() => runScan({ trigger: `auto:${reason}`, force: false }), delay);
    }

    function installNavigationObserver() {
        const originalPushState = history.pushState;
        const originalReplaceState = history.replaceState;
        const handleUrlChange = (trigger) => {
            if (location.href === state.lastUrl) return;
            state.lastUrl = location.href;
            resetForNavigation();
            scheduleAutoScan(trigger);
            window.clearTimeout(state.retryTimer);
            state.retryTimer = window.setTimeout(() => {
                if (state.status === 'idle' || state.status === 'skipped') scheduleAutoScan(`${trigger}:retry`, 0);
            }, AUTO_SCAN_RETRY_MS);
        };
        history.pushState = function (...args) {
            const result = originalPushState.apply(this, args);
            window.setTimeout(() => handleUrlChange('pushState'), 150);
            return result;
        };
        history.replaceState = function (...args) {
            const result = originalReplaceState.apply(this, args);
            window.setTimeout(() => handleUrlChange('replaceState'), 150);
            return result;
        };
        window.addEventListener('popstate', () => window.setTimeout(() => handleUrlChange('popstate'), 150));
    }

    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
        if (request?.action === 'claralex.getScanState') {
            sendResponse(getScanState());
            return true;
        }
        if (request?.action === 'claralex.manualScan') {
            runScan({ trigger: 'manual', force: true }).then(sendResponse);
            return true;
        }
        if (request?.action === 'claralex.openAnalysisPanel') {
            openAnalysisPanel();
            if (request.clauseId) {
                setActiveClauseState(request.clauseId, null, { expand: true });
                renderAnalysisPanel();
                focusAnalysisCard(request.clauseId, true);
            }
            sendResponse({ ok: true, state: getScanState() });
            return true;
        }
        if (request?.action === 'claralex.focusClause') {
            openAnalysisPanel();
            sendResponse({ ok: focusClauseInText(request.clauseId, { shouldCycle: request.shouldCycle !== false, referenceIndex: request.referenceIndex }), state: getScanState() });
            return true;
        }
        if (request?.action === 'claralex.clearHighlights' || request?.action === 'clear') {
            resetForNavigation();
            sendResponse({ status: 'cleared' });
            return true;
        }
        if (request?.action === 'getText') {
            sendResponse({ content: normalizeWhitespace(document.body?.innerText || '') });
            return true;
        }
        return false;
    });

    window.ClaraLexTest = { run: () => runScan({ trigger: 'manual-test', force: true }), clear: () => resetForNavigation(), state: () => getScanState() };
    scheduleAutoScan('initial');
    window.addEventListener('load', () => scheduleAutoScan('load', 900));
    state.retryTimer = window.setTimeout(() => {
        if (state.status === 'idle' || state.status === 'skipped') scheduleAutoScan('retry', 0);
    }, AUTO_SCAN_RETRY_MS);
    installNavigationObserver();
    console.log('ClaraLex content script caricato: autoscan selettivo pronto.');
})();
















