/* Marketing CMS schema migrator (TS). Mirrors `app/Support/MarketingMigrator.php`
 * — both sides MUST stay byte-equivalent for the same input.
 *
 * Server runs the migrator at every read boundary so admin-edit + public-render
 * always see current-shape docs. This client-side twin is defense in depth:
 * a stale browser cache or partially-deployed worker could ship a doc the
 * server hasn't migrated yet, and the renderer survives by re-running the
 * chain locally.
 *
 * Adding a new schema version:
 *   1. Bump CURRENT_X_VERSION
 *   2. Append `{from, to, migrate}` to the relevant MIGRATIONS array
 *   3. Mirror the same bump + step in MarketingMigrator.php
 */

export const CURRENT_NAV_VERSION = 1;
export const CURRENT_FOOTER_VERSION = 1;
export const CURRENT_WELCOME_VERSION = 1;
export const CURRENT_PRICING_VERSION = 1;
export const CURRENT_TEMPLATES_VERSION = 1;
export const CURRENT_ABOUT_VERSION = 1;
export const CURRENT_CONTACT_VERSION = 1;
export const CURRENT_PRIVACY_VERSION = 2;
export const CURRENT_TERMS_VERSION = 2;
export const CURRENT_REFUND_VERSION = 2;

type MigrationStep = {
    from: number;
    to: number;
    migrate: (doc: Record<string, unknown>) => Record<string, unknown>;
};

const NAV_MIGRATIONS: MigrationStep[] = [];
const FOOTER_MIGRATIONS: MigrationStep[] = [];
const WELCOME_MIGRATIONS: MigrationStep[] = [];
const PRICING_MIGRATIONS: MigrationStep[] = [];
const TEMPLATES_MIGRATIONS: MigrationStep[] = [];
const ABOUT_MIGRATIONS: MigrationStep[] = [];
const CONTACT_MIGRATIONS: MigrationStep[] = [];
const PRIVACY_MIGRATIONS: MigrationStep[] = [];
const TERMS_MIGRATIONS: MigrationStep[] = [];
const REFUND_MIGRATIONS: MigrationStep[] = [];

export function migrateNav<T extends object>(doc: T): T {
    return runChain(doc, NAV_MIGRATIONS, CURRENT_NAV_VERSION);
}

export function migrateFooter<T extends object>(doc: T): T {
    return runChain(doc, FOOTER_MIGRATIONS, CURRENT_FOOTER_VERSION);
}

export function migrateWelcome<T extends object>(doc: T): T {
    return runChain(doc, WELCOME_MIGRATIONS, CURRENT_WELCOME_VERSION);
}

export function migratePricing<T extends object>(doc: T): T {
    return runChain(doc, PRICING_MIGRATIONS, CURRENT_PRICING_VERSION);
}

export function migrateTemplates<T extends object>(doc: T): T {
    return runChain(doc, TEMPLATES_MIGRATIONS, CURRENT_TEMPLATES_VERSION);
}

export function migrateAbout<T extends object>(doc: T): T {
    return runChain(doc, ABOUT_MIGRATIONS, CURRENT_ABOUT_VERSION);
}

export function migrateContact<T extends object>(doc: T): T {
    return runChain(doc, CONTACT_MIGRATIONS, CURRENT_CONTACT_VERSION);
}

export function migratePrivacy<T extends object>(doc: T): T {
    return runChain(doc, PRIVACY_MIGRATIONS, CURRENT_PRIVACY_VERSION);
}

export function migrateTerms<T extends object>(doc: T): T {
    return runChain(doc, TERMS_MIGRATIONS, CURRENT_TERMS_VERSION);
}

export function migrateRefund<T extends object>(doc: T): T {
    return runChain(doc, REFUND_MIGRATIONS, CURRENT_REFUND_VERSION);
}

function runChain<T extends object>(
    doc: T,
    migrations: MigrationStep[],
    currentVersion: number,
): T {
    const record = { ...(doc as Record<string, unknown>) };
    let version = typeof record.version === 'number' ? record.version : 0;
    if (version < 1) {
        // v0 (no version key) → v1: stamp the version. Legacy fields untouched.
        record.version = 1;
        version = 1;
    }

    if (version === currentVersion) {
        return record as T;
    }

    // Future-version doc (admin downgraded the deployment): pass through.
    if (version > currentVersion) {
        return record as T;
    }

    let current: Record<string, unknown> = record;
    for (const step of migrations) {
        if (version !== step.from) continue;
        current = step.migrate(current);
        current.version = step.to;
        version = step.to;
        if (version === currentVersion) break;
    }

    return current as T;
}
