'use strict';

import {Controller} from '@hotwired/stimulus';
// @ts-ignore
import {Component, getComponent} from '@symfony/ux-live-component';

const STORAGE_KEY = 'ferienpass.participantIds';

/**
 * Bridges localStorage <-> the live component's `participantIds` writable
 * LiveProp so anonymous applications can be remembered across visits without
 * starting a server-side session — keeping the offer-detail response
 * cacheable by Varnish.
 *
 * Attached to the root element of any LiveComponent that exposes the
 * `participantIds` prop (ApplicationForm and the embedded sign-in
 * Registration component).
 *
 * - On connect: reads UUIDs from localStorage and pushes them to the server.
 * - On every successful re-render: writes the current prop value back to
 *   localStorage. After a successful sign-up the participants are adopted
 *   into the new account; the next render is on a different page (full
 *   redirect), so stale entries get re-validated server-side on next read
 *   (mismatched/already-claimed UUIDs are filtered out by `user IS NULL`).
 */
export default class extends Controller {
    private comp: Component | null = null;

    async initialize(): Promise<void> {
        try {
            this.comp = await getComponent(this.element as HTMLElement);
        } catch {
            return;
        }

        const stored = this.read();
        if (stored.length > 0) {
            try {
                // Push to server; the LiveComponent will re-render.
                await (this.comp as any).set('participantIds', stored, true);
            } catch {
                // Best-effort — if the API differs we just lose the sync, the
                // user can still apply (just won't see prior anonymous entries).
            }
        }

        this.element.addEventListener('live:render', () => this.persist());
    }

    private read(): string[] {
        try {
            const raw = localStorage.getItem(STORAGE_KEY);
            const parsed = raw ? JSON.parse(raw) : [];
            if (!Array.isArray(parsed)) {
                return [];
            }
            // Defensive: only keep non-empty strings of plausible UUID length.
            return parsed.filter((x): x is string => typeof x === 'string' && x.length >= 32 && x.length <= 64);
        } catch {
            return [];
        }
    }

    private persist(): void {
        if (!this.comp) {
            return;
        }

        try {
            const data = (this.comp as any).getData?.('participantIds') ?? (this.comp as any).props?.participantIds;
            if (Array.isArray(data)) {
                localStorage.setItem(
                    STORAGE_KEY,
                    JSON.stringify(data.filter((x: unknown): x is string => typeof x === 'string')),
                );
            }
        } catch {
            // localStorage may be unavailable (private mode quota etc.) — ignore.
        }
    }
}
