/**
 * @pigmilcom/a11y — CDN / Plug-and-Play entry
 *
 * Drop one script tag anywhere in your HTML — no React, no bundler, no config:
 *   <script src="https://cdn.pigmilcom.com/a11y/a11y.cdn.js"></script>
 *
 * Optional data-position attribute on the <script> tag:
 *   data-position="bottom-right"  (default)
 *   data-position="bottom-left"
 *   data-position="top-right"
 *   data-position="top-left"
 *
 * NOTE: Run "npm run build:css" before "npm run build:cdn" to regenerate
 * src/a11y-css.js (the CSS-as-JS module that esbuild bundles inline).
 */

import { createRoot } from 'react-dom/client';
import A11y from './widget.jsx';

// Inline the pre-built CSS (widget UI + a11y modifier rules).
// Imported as a JS module (generated by scripts/build-css.js) so esbuild bundles
// the string inline rather than tsup extracting it to a separate .css file.
import css from './a11y-css.js';

// ── Capture currentScript synchronously (only valid during initial execution) ─
const _script = document.currentScript;
let _attributeObserver = null;

// ── Position map — inline CSS applied to the container ────────────────────────
// env(safe-area-inset-*) ensures the button clears notches/home-bar on iOS/Android.
// Falls back to 0px on devices that don't support safe-area env variables.
const POSITIONS = {
    'bottom-right': 'bottom:calc(env(safe-area-inset-bottom,0px) + 1.25rem);right:calc(env(safe-area-inset-right,0px) + 1.25rem)',
    'bottom-left':  'bottom:calc(env(safe-area-inset-bottom,0px) + 1.25rem);left:calc(env(safe-area-inset-left,0px) + 1.25rem)',
    'top-right':    'top:calc(env(safe-area-inset-top,0px) + 1.25rem);right:calc(env(safe-area-inset-right,0px) + 1.25rem)',
    'top-left':     'top:calc(env(safe-area-inset-top,0px) + 1.25rem);left:calc(env(safe-area-inset-left,0px) + 1.25rem)',
};

// ── Style injection — idempotent, runs once ────────────────────────────────────
function injectStyles() {
    if (document.getElementById('pgm-a11y-styles')) return;
    const el = document.createElement('style');
    el.id = 'pgm-a11y-styles';
    el.textContent = css;
    document.head.appendChild(el);
}

function getScriptConfig() {
    return {
        position: _script?.dataset?.position ?? 'bottom-right',
        theme: _script?.dataset?.theme ?? null,
        lang: _script?.dataset?.lang ?? null,
    };
}

function applyContainerPosition(container, position) {
    const posCSS = POSITIONS[position] ?? POSITIONS['bottom-right'];
    container.setAttribute('style', `position:fixed;z-index:9998;line-height:0;font-size:0;${posCSS}`);
}

function renderWidget() {
    if (!_root) return;
    const { theme, lang } = getScriptConfig();
    _root.render(<A11y theme={theme} lang={lang} />);
}

function watchScriptAttributes(container) {
    if (!_script || _attributeObserver) return;

    _attributeObserver = new MutationObserver((mutations) => {
        const changedAttributes = new Set(mutations.map((mutation) => mutation.attributeName));

        if (changedAttributes.has('data-position')) {
            applyContainerPosition(container, getScriptConfig().position);
        }

        if (changedAttributes.has('data-theme') || changedAttributes.has('data-lang')) {
            renderWidget();
        }
    });

    _attributeObserver.observe(_script, {
        attributes: true,
        attributeFilter: ['data-position', 'data-theme', 'data-lang'],
    });
}

// ── Mount — idempotent, runs once ─────────────────────────────────────────────
let _root = null;

function mount() {
    if (document.getElementById('pgm-a11y-root')) return;
    injectStyles();
    const container = document.createElement('div');
    container.id = 'pgm-a11y-root';
    // Inline styles win over any class-based CSS — no ordering conflicts.
    // line-height:0 / font-size:0 prevent inherited whitespace from adding
    // phantom height/width to the container div.
    applyContainerPosition(container, getScriptConfig().position);
    document.body.appendChild(container);
    _root = createRoot(container);
    renderWidget();
    watchScriptAttributes(container);
}

function unmount() {
    _attributeObserver?.disconnect();
    _attributeObserver = null;
    _root?.unmount();
    document.getElementById('pgm-a11y-root')?.remove();
    document.getElementById('pgm-a11y-styles')?.remove();
    _root = null;
}

// ── License loader — fetches dist/license.min.js from the pigmil CDN —————————
// Sets window.PigmilLicense before the React widget mounts so validateLicense
// is available synchronously when widget.jsx's useEffect fires.
// Falls back silently (widget renders with status:valid) if the script fails.
const _LIC_URL = 'https://cdn.pigmil.com/a11y/dist/license.min.js';

function _loadLicense(cb) {
    // Already available (re-mount, or host pre-loaded the script)
    if (typeof window !== 'undefined' && window?.PigmilLicense?.validateLicense) {
        cb(); return;
    }
    const s = document.createElement('script');
    s.src = _LIC_URL;
    s.onload  = cb;
    s.onerror = cb; // fail-open: mount anyway, widget falls back to status:valid
    (document.head || document.body).appendChild(s);
}

// ── Boot —————————————————————————————————————————————————————————————————
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => _loadLicense(mount));
} else {
    _loadLicense(mount);
}

// Expose programmatic control for advanced users via window.PigmilA11y
export { mount, unmount };
