// Upgrade CTA surfaces (KL-16): two ways the dashboard nudges Starter
// users toward Pro/Venue without nagging.
//
//   1. Sidebar tier badge gets a rotating feature teaser ("DMX fixtures",
//      "AI Director") between the STARTER label and the Upgrade ↗ link.
//      Always-visible ambient surface; one telemetry shown event per
//      session at mount, click events on the link.
//
//   2. Contextual toast that fires once per session after a 4-condition
//      gate is met:
//        - Tier is "starter"
//        - Audio engine has heard real signal at least once
//          (any band > 0 in any state_update)
//        - Session uptime > 3 minutes
//        - Not already shown this session AND not snoozed for 24h
//      "Snooze 24h" sets a localStorage timestamp; "See Pro" opens the
//      pricing page in the OS browser via target="_blank".
//
// Pro and Venue tiers get nothing — they're paying customers.
//
// Both surfaces fire the existing whitelisted telemetry events
// (upgrade.cta_shown / upgrade.cta_clicked / checkout.opened) so the
// funnel data lands alongside the locked-tab placard analytics.

import {pushToast, dismissToast, registerToastAction} from './toasts.js';
import {trackEvent, pricingUrlWithContext} from '../js/utils.js';

// Contextual toast keys + thresholds.
const TOAST_KEY = 'upgrade-contextual-cta';
const SHOWN_FLAG_KEY = 'conductor.upgrade_contextual_shown';     // sessionStorage
const SNOOZE_KEY = 'conductor.upgrade_contextual_snoozed_until'; // localStorage
const SNOOZE_MS = 24 * 60 * 60 * 1000;
const MIN_UPTIME_MS = 3 * 60 * 1000;
const GATE_POLL_MS = 10_000;

// Sidebar badge rotation.
const TEASER_FEATURES = ['DMX fixtures', 'AI Director'];
const TEASER_ROTATE_MS = 4_000;
const TEASER_FADE_MS = 220;

// Module-level state.
let haveHeardSignal = false;
const pageLoadTs = Date.now();

export function initUpgradeCta() {
    if (window.CONDUCTOR_TIER !== 'starter') return;
    initSidebarBadge();
    initContextualToast();
}

// Called from main.js's state_update handler. Cheap path so the 10Hz
// state push doesn't take a perf hit — once we've heard signal, we
// short-circuit on every subsequent tick.
export function noteUpgradeCtaSignal(smoothed) {
    if (haveHeardSignal) return;
    if (Array.isArray(smoothed) && smoothed.some(v => v > 0)) {
        haveHeardSignal = true;
    }
}

// --- Sidebar tier badge ---

function initSidebarBadge() {
    const badge = document.querySelector('.shell-tier-badge');
    const teaser = document.getElementById('tier-badge-teaser');
    if (!badge || !teaser) return;

    // Initial frame + rotation. Use opacity fade rather than a layout
    // change so the sidebar doesn't jitter while the text swaps.
    let idx = 0;
    teaser.textContent = TEASER_FEATURES[idx];
    teaser.style.opacity = '1';
    setInterval(() => {
        idx = (idx + 1) % TEASER_FEATURES.length;
        teaser.style.opacity = '0';
        setTimeout(() => {
            teaser.textContent = TEASER_FEATURES[idx];
            teaser.style.opacity = '1';
        }, TEASER_FADE_MS);
    }, TEASER_ROTATE_MS);

    // Fire once at mount — the badge is ambient, so this counts as
    // "shown" for the funnel even before the user looks at it.
    trackEvent('upgrade.cta_shown', {
        surface: 'sidebar_badge',
        tier: 'starter',
    });

    badge.addEventListener('click', () => {
        trackEvent('upgrade.cta_clicked', {
            surface: 'sidebar_badge',
            action: 'pricing',
        });
        trackEvent('checkout.opened', {
            surface: 'sidebar_badge',
            tier: 'starter',
        });
    });
}

// --- Contextual toast ---

function initContextualToast() {
    if (isShownThisSession() || isSnoozed()) return;

    const timer = setInterval(() => {
        if (checkAllGates()) {
            clearInterval(timer);
            showContextualToast();
        }
    }, GATE_POLL_MS);
}

function checkAllGates() {
    if (window.CONDUCTOR_TIER !== 'starter') return false;
    if (!haveHeardSignal) return false;
    if (Date.now() - pageLoadTs < MIN_UPTIME_MS) return false;
    if (isShownThisSession() || isSnoozed()) return false;
    return true;
}

function showContextualToast() {
    markShownThisSession();

    registerToastAction('upgrade-contextual-pro', () => {
        trackEvent('upgrade.cta_clicked', {
            surface: 'contextual_toast',
            action: 'see_pro',
        });
        trackEvent('checkout.opened', {
            surface: 'contextual_toast',
            tier: 'starter',
        });
        dismissToast(TOAST_KEY);
    });
    registerToastAction('upgrade-contextual-snooze', () => {
        snooze24h();
        dismissToast(TOAST_KEY);
    });

    pushToast({
        key: TOAST_KEY,
        level: 'info',
        title: 'Loving the show?',
        detail: 'Pro adds DMX fixtures + AI direction to Conductør.',
        actions: [
            {id: 'upgrade-contextual-pro', label: 'See Pro', href: pricingUrlWithContext('contextual_toast'), target: '_blank'},
            {id: 'upgrade-contextual-snooze', label: 'Snooze 24h'},
        ],
        dismissible: false,
    });

    trackEvent('upgrade.cta_shown', {
        surface: 'contextual_toast',
        tier: 'starter',
    });
}

// --- Persistence helpers ---

function isShownThisSession() {
    try { return sessionStorage.getItem(SHOWN_FLAG_KEY) === '1'; }
    catch (_) { return false; }
}
function markShownThisSession() {
    try { sessionStorage.setItem(SHOWN_FLAG_KEY, '1'); } catch (_) {}
}
function isSnoozed() {
    try {
        const raw = localStorage.getItem(SNOOZE_KEY);
        if (!raw) return false;
        const ts = parseInt(raw, 10);
        return Number.isFinite(ts) && ts > Date.now();
    } catch (_) { return false; }
}
function snooze24h() {
    try { localStorage.setItem(SNOOZE_KEY, String(Date.now() + SNOOZE_MS)); }
    catch (_) {}
}
