/**
 * Anonymous listener id interop (Phase 16 §3, wave 16.3, D5 Option A). Mints a random first-party GUID
 * on first visit, stores it in localStorage, and reads it back thereafter — one opaque token per
 * browser-install-until-cleared. No PII, no fingerprinting, no cross-site use: it is a "this browser,
 * until you clear it" token the server counts distinctly to estimate unique listeners.
 *
 * Degrades safely: if localStorage is unavailable (private mode, blocked, partitioned third-party
 * iframe) it returns null rather than throwing, and the caller simply sends no anonId. Over-counting is
 * the known, accepted direction of error (§3).
 *
 * Exposed on window.DeepDrftAnonId; imported once in App.razor alongside the audio engine and beacon.
 */

const STORAGE_KEY = 'deepdrft.anonId';

// crypto.randomUUID is the standard, secure source. A guarded fallback covers older/insecure-context
// browsers where it is absent — still a random opaque token, not a fingerprint.
function mint(): string {
    if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
        return crypto.randomUUID();
    }
    // RFC4122-ish fallback from getRandomValues; only reached on browsers lacking randomUUID.
    const bytes = new Uint8Array(16);
    crypto.getRandomValues(bytes);
    bytes[6] = (bytes[6] & 0x0f) | 0x40;
    bytes[8] = (bytes[8] & 0x3f) | 0x80;
    const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
    return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}

const DeepDrftAnonId = {
    /**
     * Read the stored anon id, minting and persisting one on first call. Returns null if localStorage
     * cannot be read or written (private mode / blocked / partitioned) — telemetry then omits the id.
     * Both the read and the write are guarded independently: a readable-but-unwritable store still mints
     * a fresh id each call (acceptable over-count) rather than throwing.
     */
    get: (): string | null => {
        try {
            const existing = localStorage.getItem(STORAGE_KEY);
            if (existing) return existing;

            const minted = mint();
            try {
                localStorage.setItem(STORAGE_KEY, minted);
            } catch {
                // Read worked, write did not — return the minted value anyway; it just won't persist.
            }
            return minted;
        } catch {
            // localStorage is entirely unavailable — send no anonId.
            return null;
        }
    },
};

declare global {
    interface Window {
        DeepDrftAnonId: typeof DeepDrftAnonId;
    }
}

window.DeepDrftAnonId = DeepDrftAnonId;

export { DeepDrftAnonId };
