/**
 * store_versions.ts
 *
 * Single source of truth for persisted store schema versions.
 *
 * HOW IT WORKS:
 * This file is imported at the top of ae_stores.ts and ae_events_stores.ts.
 * ES modules resolve imports before running the importing module's body,
 * so the version check + localStorage wipe here runs BEFORE persisted() is
 * called — meaning stale data is cleared before svelte-persisted-store
 * can hydrate from it.
 *
 * HOW TO USE:
 * When a store schema changes in a breaking way (type change, required
 * restructure, field rename that code depends on), bump the relevant version
 * by 1. Any client with an older version will have that store silently wiped
 * on next page load. They re-initialize from the new defaults.
 *
 * WHAT COUNTS AS BREAKING:
 *   - Changing a field's type (e.g. string → object, or null → required object)
 *   - Renaming a field that code reads directly (not just a display label)
 *   - Restructuring a nested object that breaks existing property access
 *   DOES NOT require a bump:
 *   - Adding a new optional field (svelte-persisted-store deep-merges defaults)
 *   - Removing a field (old value is ignored, no error)
 *   - Changing a default value when the stored value being stale is acceptable
 *
 * localStorage keys:
 *   'ae_loc'        → AE_LOC_VERSION
 *   'ae_events_loc' → AE_EVENTS_LOC_VERSION
 */

export const AE_LOC_VERSION = 2; // Bumped 2026-03-30: force-clear stale site_cfg_json (novi_idaa_api_key missing bug)
export const AE_EVENTS_LOC_VERSION = 1;
export const AE_IDAA_LOC_VERSION = 2; // Bumped 2026-05-18: change default qry__limit from 150 to 100
export const AE_PRES_MGMT_LOC_VERSION = 2; // Bumped 2026-06-16: added show__session_qr / show__presenter_qr; removed limit__options + hide__launcher_link_legacy (Flask launcher retired)
export const AE_BADGES_LOC_VERSION = 1;     // Added 2026-04-02: promoted from events_loc.badges
export const AE_LEADS_LOC_VERSION = 1;      // Added 2026-04-03: promoted from events_loc.leads

/**
 * IDB_CONTENT_VERSIONS — per-table Dexie (IndexedDB) content version tracking.
 *
 * BACKGROUND:
 * Stale IDB records persisting across deploys were the root cause of the "no meetings
 * found" bug on the IDAA Recovery Meetings page — a ~1-year unresolved issue (2025-2026).
 * After a deploy that changed properties_to_save, old cached event records stayed in IDB
 * with wrong or missing fields. The fast path returned them, filtered to 0 (account_id
 * mismatch), the API call errored silently, and the error state showed the same message
 * as a genuinely empty result. Fixed 2026-05-16.
 *
 * WIRING STATUS (as of 2026-05-16):
 *   events.event        → ACTIVE — wired in src/routes/idaa/(idaa)/+layout.svelte
 *   All other tables    → NOT YET WIRED (see instructions below)
 *
 * HOW IT WORKS (for wired tables):
 * check_and_clear_idb_table() (bottom of this file) is called on module/page load.
 * It reads a localStorage key `ae_idb_ver__<db_name>__<table_name>` and compares it
 * to the version here. On mismatch, the Dexie table is cleared and the key is updated.
 * The SWR pattern then repopulates from the API on next access. On a version match
 * (the normal case after first load) the cost is a single localStorage read — free.
 *
 * HOW TO WIRE A NEW TABLE:
 * 1. Import check_and_clear_idb_table from '$lib/stores/store_versions' in the relevant
 *    layout or page (the one that owns that module's data lifecycle).
 * 2. Call it on mount, non-blocking:
 *      check_and_clear_idb_table(db_X.table_name, 'db_key', 'table_name').catch(() => {});
 *    Use top-level `if (browser) { ... }` or an `$effect` with no reactive deps.
 * 3. That's it. Bumping the version constant below is all that's needed for future clears.
 *
 * WHEN TO BUMP A VERSION:
 * Bump when properties_to_save in an object file changes in a way that makes existing
 * cached records stale — e.g. adding/removing stored fields, changing how a computed
 * field (like tmp_sort_1) is built, or a backend change that alters field semantics.
 * Do NOT bump for Dexie schema-only changes (new indexes, new tables) — those belong
 * in db.version() Dexie migrations in the db_*.ts file.
 *
 * IDAA NOTES:
 * IDAA tables (posts, archives, events) are already cleared aggressively via
 * indexedDB.deleteDatabase() on auth failure in (idaa)/+layout.svelte.
 * The content version check is a deploy-time complement — it handles the case where
 * auth succeeds but IDB data is stale from a prior deploy. Both mechanisms are needed.
 */
export const IDB_CONTENT_VERSIONS = {
    journals: {
        journal: 3,
        journal_entry: 3 // 2026-05-14: removed content_md_html + history_md_html from properties_to_save
    },
    events: {
        event: 3, // Bumped 2026-06-03: precautionary clear after sort-direction and account_id gate fixes
        event_session: 1,
        event_presenter: 1,
        event_badge: 1,
        event_device: 1,
        event_location: 1,
        event_file: 1
    },
    core: {
        site_domain: 1,
        person: 1,
        user: 1
    },
    // IDAA modules — see IDAA NOTES above before wiring these
    posts: {
        post: 1,
        post_comment: 1
    },
    archives: {
        archive: 1,
        archive_content: 1
    }
};

// Version check side-effect: runs on import, before any persisted() call.
// Guard presence of `localStorage` and its functions for safety (SSR, Node flags).
if (
    typeof localStorage !== 'undefined' &&
    typeof (localStorage as any).getItem === 'function' &&
    typeof (localStorage as any).removeItem === 'function'
) {
    _check_and_wipe('ae_loc', AE_LOC_VERSION);
    _check_and_wipe('ae_events_loc', AE_EVENTS_LOC_VERSION);
    _check_and_wipe('ae_idaa_loc', AE_IDAA_LOC_VERSION);
    // ae_leads_loc (PersistedState, runed) stamps __version itself in its custom
    // serializer — see ae_events_stores__leads.svelte.ts. FIXED 2026-06-16: this was
    // previously bare JSON.stringify with no __version field, so this check always saw
    // undefined !== expected and wiped ae_leads_loc on EVERY page load.
    _check_and_wipe('ae_leads_loc', AE_LEADS_LOC_VERSION);
    // ae_pres_mgmt_loc (PersistedState, runed) stamps __version itself in its custom
    // serializer — see ae_events_stores__pres_mgmt.svelte.ts. Importing that module runs
    // this file's side effects first (ES module order), so this check sees real stored
    // data, not a race against the PersistedState constructor.
    _check_and_wipe('ae_pres_mgmt_loc', AE_PRES_MGMT_LOC_VERSION);
}

function _check_and_wipe(key: string, expected_version: number): void {
    try {
        // Defensive: ensure methods still exist at call time.
        if (typeof (localStorage as any).getItem !== 'function') return;
        const raw = localStorage.getItem(key);
        if (!raw) return; // No stored value — nothing to wipe.

        const parsed = JSON.parse(raw);
        if (parsed?.__version !== expected_version) {
            if (typeof (localStorage as any).removeItem === 'function') {
                localStorage.removeItem(key);
            }
            console.info(
                `[store_versions] '${key}' wiped — schema v${parsed?.__version ?? 'none'} → v${expected_version}`
            );
        }
    } catch {
        // Corrupt JSON — wipe unconditionally if possible.
        if (typeof (localStorage as any).removeItem === 'function') {
            localStorage.removeItem(key);
        }
        console.warn(
            `[store_versions] '${key}' wiped — corrupt JSON in localStorage`
        );
    }
}

/**
 * Checks the IDB table content version against the expected version in IDB_CONTENT_VERSIONS.
 * If the stored version is stale (or missing), clears the entire table and records the new
 * version so the next call is a no-op.
 *
 * @param db_table    - A Dexie table reference (e.g. db_events.event)
 * @param db_name     - The top-level key in IDB_CONTENT_VERSIONS (e.g. 'events')
 * @param table_name  - The table key inside that group (e.g. 'event')
 *
 * WHY localStorage for version tracking (not a _meta IDB table):
 * Simpler — no Dexie schema migration needed. localStorage and IDB are cleared together
 * by Full Reset (e_app_help_tech.svelte), so they stay in sync across manual wipes.
 *
 * USAGE: call on mount, non-blocking. Example from (idaa)/+layout.svelte:
 *   check_and_clear_idb_table(db_events.event, 'events', 'event').catch(() => {});
 *
 * After clearing, the SWR pattern in the relevant page automatically re-fetches from
 * the API and repopulates the table. No explicit reload is needed.
 */
export async function check_and_clear_idb_table(
    db_table: { clear(): Promise<void> },
    db_name: string,
    table_name: string
): Promise<void> {
    if (typeof localStorage === 'undefined') return;

    const versions = IDB_CONTENT_VERSIONS as Record<string, Record<string, number>>;
    const expected_ver = versions[db_name]?.[table_name];
    if (expected_ver == null) return;

    const key = `ae_idb_ver__${db_name}__${table_name}`;
    const stored_ver = parseInt(localStorage.getItem(key) ?? '0', 10);

    if (stored_ver !== expected_ver) {
        try {
            await db_table.clear();
            localStorage.setItem(key, String(expected_ver));
            console.info(
                `[idb_versions] '${db_name}.${table_name}' cleared — v${stored_ver} → v${expected_ver}`
            );
        } catch (e) {
            console.warn(`[idb_versions] Failed to clear '${db_name}.${table_name}':`, e);
        }
    }
}
