(() => {
    'use strict';

    window.FotogenicAI = window.FotogenicAI || {};
    const Studio = window.FotogenicAI.Studio = window.FotogenicAI.Studio || {};
    const Shared = window.FotogenicAI.Shared = window.FotogenicAI.Shared || {};
    const { __, sprintf } = Studio.i18n;

    const vm = Studio.viewModel;
    const { isRecord } = Studio.store;
    const STORAGE_KEY = 'fotogenic-ai-studio-run-v1';
    const BULK_RECOVERY_STORAGE_KEY = 'fotogenic-ai-studio-bulk-recovery-v1';
    const RECORD_VERSION = 1;
    const UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i;
    const RUN_STATUSES = new Set([
		'queued', 'starting', 'processing', 'finalizing', 'saving', 'pausing', 'paused', 'stopping', 'stopped', 'uncertain', 'partial', 'completed', 'failed', 'removed',
    ]);
    const TERMINAL_STATUSES = new Set(['completed', 'partial', 'failed', 'timeout', 'stale', 'stopped', 'removed']);
    const BULK_SERVER_STATUSES = new Set(['starting', 'processing', 'paused', 'stopping', 'stopped', 'completed', 'failed']);
    const BULK_ACTIVE_STATUSES = new Set(['starting', 'processing', 'stopping']);
    const HISTORY_STATUSES = new Set(['queued', 'starting', 'processing', 'paused', 'stopping', 'uncertain', 'partial', 'completed', 'failed', 'stopped', 'removed']);
    const BULK_PAGE_SIZE = 25;
	const STORE_QUEUE_PAGE_SIZE = 25;
	const STORE_QUEUE_ITEM_LIMIT = 100000;
	const STORE_QUEUE_OUTPUT_LIMIT = 600000;
	const DELIVERY_MODES = new Set(['media_library', 'review', 'gallery_append', 'featured_review', 'mixed']);
	const normalizeDeliveryMode = (value, fallback = 'media_library') => {
		const normalized = vm.cleanText(value, 32).toLowerCase();
		return DELIVERY_MODES.has(normalized) ? normalized : fallback;
	};
	const deliveryModeFromDraft = (draft = {}) => {
		if (draft.workflow === 'campaign_set' && Array.isArray(draft.sourcePolicy?.groups)) {
			const modes = new Set(draft.sourcePolicy.groups.map((group) => (
				String(group?.resultPolicy?.assignmentMode || 'review') === 'gallery_append'
					? 'gallery_append'
					: 'review'
			)));
			return modes.size === 1 ? [...modes][0] : 'mixed';
		}
		if (draft.sourceType !== 'product' || draft.workflow === 'increase_resolution') return 'media_library';
		const assignmentMode = String(draft.resultPolicy?.assignmentMode || 'review');
		if (assignmentMode === 'gallery_append') return 'gallery_append';
		if (assignmentMode === 'featured_replace') return 'featured_review';
		return 'review';
	};

    const strictPositiveInteger = (value, maximum) => {
        const number = Number(value);
        return Number.isSafeInteger(number) && number > 0 && number <= maximum ? number : 0;
    };

	const normalizeOperationalLimits = (value) => {
		if (
			!isRecord(value)
			|| Object.keys(value).sort().join(',') !== 'maxOutputsPerItem,maxRunItems,maxRunOutputs'
		) return null;
		const limits = {
			maxRunItems: strictPositiveInteger(value.maxRunItems, Number.MAX_SAFE_INTEGER),
			maxOutputsPerItem: strictPositiveInteger(value.maxOutputsPerItem, Number.MAX_SAFE_INTEGER),
			maxRunOutputs: strictPositiveInteger(value.maxRunOutputs, Number.MAX_SAFE_INTEGER),
		};
		return limits.maxRunItems
			&& limits.maxOutputsPerItem
			&& limits.maxRunOutputs === limits.maxRunItems * limits.maxOutputsPerItem
			? limits
			: null;
	};

	const pollDelayMs = (attempt, scope = 'single') => {
		const normalizedAttempt = Number.isSafeInteger(Number(attempt)) && Number(attempt) > 0
			? Number(attempt)
			: 0;
		if (normalizedAttempt < 2) return ['bulk', 'store_queue'].includes(scope) ? 2200 : 2000;
		return normalizedAttempt < 6 ? 5000 : 8000;
	};

    const normalizeJobIds = (values) => [...new Set((Array.isArray(values) ? values : [])
        .filter((value) => typeof value === 'string' || Number.isInteger(value))
        .map((value) => vm.cleanText(value, 64))
        .filter(Boolean))].slice(0, 10);

    const normalizeTargetHint = (value, subjectId, sourceType) => {
        if (!isRecord(value)) return null;
        const target = {
            targetType: vm.cleanText(value.targetType, 20).toLowerCase(),
            targetId: vm.positiveInteger(value.targetId),
            parentProductId: vm.nonNegativeInteger(value.parentProductId, 0),
            variationId: vm.nonNegativeInteger(value.variationId, 0),
        };
        const productTarget = sourceType === 'product' && (
            (target.targetType === 'product' && target.parentProductId === 0 && target.variationId === 0)
            || (target.targetType === 'variation' && target.parentProductId > 0 && target.variationId === target.targetId)
        );
        const wordPressTarget = ['media', 'post', 'page'].includes(sourceType)
            && target.targetType === sourceType
            && target.parentProductId === 0
            && target.variationId === 0;
        return target.targetId === subjectId && (productTarget || wordPressTarget) ? target : null;
    };

    const normalizeTargetIdentity = (value, subjectId, sourceType) => {
        if (
            !isRecord(value)
            || Object.keys(value).sort().join(',') !== 'destinationCapabilities,eligible,ineligibilityReason,label,parentProductId,schemaVersion,sku,sourceType,targetId,targetType,variationId'
            || value.schemaVersion !== 1
            || value.sourceType !== sourceType
            || typeof value.sku !== 'string'
            || typeof value.label !== 'string'
            || typeof value.eligible !== 'boolean'
            || typeof value.ineligibilityReason !== 'string'
            || !isRecord(value.destinationCapabilities)
            || Object.keys(value.destinationCapabilities).sort().join(',') !== 'addGallery,applyFeatured,setFeatured,setFeaturedAndGallery'
            || Object.values(value.destinationCapabilities).some((capability) => typeof capability !== 'boolean')
        ) return null;
        const hint = normalizeTargetHint(value, subjectId, sourceType);
        if (!hint) return null;
        return {
            schemaVersion: 1,
            sourceType,
            ...hint,
            sku: vm.cleanText(value.sku, 100),
            label: vm.cleanText(value.label, 255),
            eligible: value.eligible,
            ineligibilityReason: vm.safeCode(value.ineligibilityReason),
            destinationCapabilities: {
                setFeatured: value.destinationCapabilities.setFeatured,
                addGallery: value.destinationCapabilities.addGallery,
                setFeaturedAndGallery: value.destinationCapabilities.setFeaturedAndGallery,
                applyFeatured: value.destinationCapabilities.applyFeatured,
            },
        };
    };

    const normalizeIdentity = (value, operationalLimits) => {
        const limits = normalizeOperationalLimits(operationalLimits);
        if (!limits) return null;
        if (!isRecord(value) || value.version !== RECORD_VERSION) return null;
        const rawWorkflow = vm.cleanText(value.workflow, 64).toLowerCase();
        const rawSourceType = vm.cleanText(value.sourceType, 64).toLowerCase();
        const rawScope = vm.cleanText(value.scope, 64).toLowerCase();
        if (!vm.WORKFLOWS.has(rawWorkflow) || !vm.SOURCE_TYPES.has(rawSourceType) || !vm.SCOPES.has(rawScope)) return null;
        const route = vm.normalizeRoute(value);
        const status = vm.knownValue(value.status, RUN_STATUSES, 'uncertain');
		if (rawScope === 'store_queue') {
			const queueUuid = vm.cleanText(value.queueUuid, 36).toLowerCase();
			const selectedCount = strictPositiveInteger(value.selectedCount, STORE_QUEUE_ITEM_LIMIT);
			const expectedOutputCount = strictPositiveInteger(value.expectedOutputCount, STORE_QUEUE_OUTPUT_LIMIT);
			const revision = strictPositiveInteger(value.revision, Number.MAX_SAFE_INTEGER);
			if (
				rawWorkflow !== 'product_images'
				|| rawSourceType !== 'product'
				|| !UUID_PATTERN.test(queueUuid)
				|| !selectedCount
				|| !expectedOutputCount
				|| !revision
			) return null;
			return {
				version: RECORD_VERSION,
				...route,
				status,
				deliveryMode: normalizeDeliveryMode(value.deliveryMode),
				queueUuid,
				selectedCount,
				expectedOutputCount,
				revision,
			};
		}
        const common = {
			version: RECORD_VERSION,
			...route,
			status,
			deliveryMode: normalizeDeliveryMode(value.deliveryMode),
			expectedOutputCount: strictPositiveInteger(
				value.expectedOutputCount,
				route.scope === 'bulk' ? limits.maxRunOutputs : limits.maxOutputsPerItem
			),
        };
		if (route.scope === 'bulk') {
			const runUuid = vm.cleanText(value.runUuid, 36).toLowerCase();
			const selectedCount = strictPositiveInteger(value.selectedCount, limits.maxRunItems);
			const outputsPerItem = strictPositiveInteger(value.outputsPerItem, limits.maxOutputsPerItem);
			if (!UUID_PATTERN.test(runUuid) || !selectedCount || !common.expectedOutputCount) return null;
			return {
				...common,
				runUuid,
				selectedCount,
				...(outputsPerItem ? { outputsPerItem } : {}),
            };
        }
        const requestId = vm.cleanText(value.requestId, 36).toLowerCase();
        const subjectId = vm.positiveInteger(value.subjectId);
        if (!UUID_PATTERN.test(requestId) || !subjectId || !common.expectedOutputCount) return null;
        const runItemId = vm.cleanText(value.runItemId, 36).toLowerCase();
        const campaignGroupId = vm.cleanText(value.campaignGroupId, 36).toLowerCase();
		const itemOrdinal = strictPositiveInteger(value.itemOrdinal, limits.maxRunItems);
        const targetIdentity = normalizeTargetHint(value.targetIdentity, subjectId, route.sourceType);
        const hasItemIdentity = runItemId || campaignGroupId || itemOrdinal || targetIdentity;
        if (hasItemIdentity && (
            !UUID_PATTERN.test(runItemId)
            || (route.workflow === 'campaign_set' ? !UUID_PATTERN.test(campaignGroupId) : Boolean(campaignGroupId))
            || itemOrdinal !== 1
            || !targetIdentity
            || targetIdentity.targetId !== subjectId
        )) return null;
        return {
            ...common,
            subjectId,
            requestId,
            ...(hasItemIdentity ? { runItemId, campaignGroupId, itemOrdinal, targetIdentity } : {}),
            runId: vm.cleanText(value.runId, 64),
            jobIds: normalizeJobIds(value.jobIds),
        };
    };

	const routeFromIdentity = (value) => {
		if (!isRecord(value)) return null;
		const identityScope = vm.cleanText(value.scope, 64).toLowerCase();
		const route = {
			workflow: vm.cleanText(value.workflow, 64).toLowerCase(),
			sourceType: vm.cleanText(value.sourceType, 64).toLowerCase(),
			scope: identityScope === 'store_queue' ? 'bulk' : identityScope,
		};
		return vm.WORKFLOWS.has(route.workflow)
			&& vm.SOURCE_TYPES.has(route.sourceType)
			&& vm.SCOPES.has(route.scope)
			? route
			: null;
	};

    const readStoredIdentity = (storage = window.sessionStorage, operationalLimits) => {
        try {
            const raw = storage?.getItem?.(STORAGE_KEY);
            return raw ? normalizeIdentity(JSON.parse(raw), operationalLimits) : null;
        } catch (_) {
            return null;
        }
    };

    const writeStoredIdentity = (storage, identity, operationalLimits) => {
        const normalized = normalizeIdentity(identity, operationalLimits);
        if (!normalized) return false;
        try {
            storage?.setItem?.(STORAGE_KEY, JSON.stringify(normalized));
            return true;
        } catch (_) {
            return false;
        }
    };

    const clearStoredIdentity = (storage) => {
        try {
            storage?.removeItem?.(STORAGE_KEY);
        } catch (_) {
            return;
        }
    };

	const normalizePendingBulkRecovery = (value, operationalLimits) => {
		const limits = normalizeOperationalLimits(operationalLimits);
		if (!limits) return null;
		if (!isRecord(value) || Object.keys(value).sort().join(',') !== 'runUuid,selectedCount,sourceType,workflow') return null;
		const recovery = {
			runUuid: vm.cleanText(value.runUuid, 36).toLowerCase(),
			workflow: vm.cleanText(value.workflow, 64).toLowerCase(),
			sourceType: vm.cleanText(value.sourceType, 64).toLowerCase(),
			selectedCount: strictPositiveInteger(value.selectedCount, limits.maxRunItems),
		};
		return UUID_PATTERN.test(recovery.runUuid)
			&& vm.WORKFLOWS.has(recovery.workflow)
			&& vm.SOURCE_TYPES.has(recovery.sourceType)
			&& recovery.selectedCount
			? recovery
			: null;
	};

	const readPendingBulkRecovery = (storage = window.sessionStorage, operationalLimits) => {
		try {
			const raw = storage?.getItem?.(BULK_RECOVERY_STORAGE_KEY);
			return raw ? normalizePendingBulkRecovery(JSON.parse(raw), operationalLimits) : null;
		} catch (_) {
			return null;
		}
	};

	const writePendingBulkRecovery = (storage, value, operationalLimits) => {
		const normalized = normalizePendingBulkRecovery(value, operationalLimits);
		if (!normalized) return false;
		try {
			storage?.setItem?.(BULK_RECOVERY_STORAGE_KEY, JSON.stringify(normalized));
			return true;
		} catch (_) {
			return false;
		}
	};

	const clearPendingBulkRecovery = (storage) => {
		try {
			storage?.removeItem?.(BULK_RECOVERY_STORAGE_KEY);
		} catch (_) {
			return;
		}
	};

    const exactPreflightIsCurrent = (exact, operationalLimits) => {
		const limits = normalizeOperationalLimits(operationalLimits);
		return Boolean(limits
        && isRecord(exact)
        && Object.keys(exact).sort().join(',') === 'authority,authorityEvidence,balance,balanceAfter,draftFingerprint,pricing,sourceFingerprint,totalCredits,totalItems,totalOutputs'
        && /^[a-f0-9]{64}$/.test(String(exact.draftFingerprint || ''))
        && /^[a-f0-9]{64}$/.test(String(exact.sourceFingerprint || ''))
        && Number.isSafeInteger(Number(exact.totalItems))
        && Number(exact.totalItems) >= 1
        && Number.isInteger(Number(exact.totalOutputs))
        && Number(exact.totalOutputs) >= 1
        && Number(exact.totalOutputs) <= limits.maxRunOutputs
        && Number.isFinite(Number(exact.totalCredits))
        && Number(exact.totalCredits) >= 0
        && Number.isFinite(Number(exact.balance))
        && Number(exact.balance) >= 0
        && Number.isFinite(Number(exact.balanceAfter))
        && Number(exact.balanceAfter) >= 0
        && isRecord(exact.pricing)
        && Object.keys(exact.pricing).sort().join(',') === 'creditsPerOutput,quality,workflow'
        && vm.WORKFLOWS.has(exact.pricing.workflow)
        && Number.isFinite(Number(exact.pricing.creditsPerOutput))
        && Number(exact.pricing.creditsPerOutput) >= 0
        && typeof exact.pricing.quality === 'string'
        && isRecord(exact.authorityEvidence)
        && Object.keys(exact.authorityEvidence).sort().join(',') === 'configurationFingerprint,contextFingerprint,creditsFingerprint,pricingFingerprint'
        && ['contextFingerprint', 'configurationFingerprint', 'pricingFingerprint', 'creditsFingerprint']
            .every((key) => /^[a-f0-9]{64}$/.test(String(exact.authorityEvidence[key] || '')))
        && isRecord(exact.authority)
        && Object.keys(exact.authority).sort().join(',') === 'expiresAt,fingerprint,version'
        && exact.authority.version === 1
        && /^[a-f0-9]{64}$/.test(String(exact.authority.fingerprint || ''))
        && Number.isSafeInteger(Number(exact.authority.expiresAt))
        && Number(exact.authority.expiresAt) > Math.floor(Date.now() / 1000));
	};

    const singleDraftIsStartable = (draft) => (
        isRecord(draft)
        && draft.scope === 'single'
        && Array.isArray(draft.selection?.selectedIds)
        && draft.selection.selectedIds.length === 1
	);

    const canStartSingle = ({ draft, preflightCurrent, exact } = {}, operationalLimits) => {
	const limits = normalizeOperationalLimits(operationalLimits);
		return Boolean(limits
		&& singleDraftIsStartable(draft)
        && preflightCurrent === true
        && exactPreflightIsCurrent(exact, limits)
		&& exact.pricing.workflow === draft.workflow
		&& Number(exact.totalItems) === 1
        && Number(exact.totalOutputs) <= limits.maxOutputsPerItem);
	};

    const bulkItemCount = (draft) => draft?.workflow === 'campaign_set' && Array.isArray(draft?.sourcePolicy?.groups)
        ? draft.sourcePolicy.groups.length
        : (Array.isArray(draft?.selection?.selectedIds) ? draft.selection.selectedIds.length : 0);

	const plannedOutputCount = (draft) => {
		const itemCount = bulkItemCount(draft);
		if (draft?.workflow === 'increase_resolution') return itemCount;
		return draft?.workflow === 'campaign_set'
			? (Array.isArray(draft?.sourcePolicy?.groups)
				? draft.sourcePolicy.groups.reduce((total, group) => total + Number(group?.recipe?.count || 0), 0)
				: 0)
			: itemCount * Number(draft?.recipe?.count || 0);
	};

	const bulkDraftIsStartable = (draft, expectedOutputs, operationalLimits) => {
		const limits = normalizeOperationalLimits(operationalLimits);
		if (!limits) return false;
		const itemCount = bulkItemCount(draft);
		const plannedOutputs = plannedOutputCount(draft);
		const campaignGroupsValid = draft?.workflow !== 'campaign_set' || (
            Array.isArray(draft.sourcePolicy?.groups)
            && draft.sourcePolicy.groups.length === itemCount
            && draft.sourcePolicy.groups.every((group, index) => (
                isRecord(group)
                && UUID_PATTERN.test(vm.cleanText(group.id, 36).toLowerCase())
                && Number(group.ordinal) === index + 1
				&& Number.isSafeInteger(Number(group.subjectId))
				&& draft.selection.selectedIds.map(Number).includes(Number(group.subjectId))
				&& isRecord(group.recipe)
				&& Number.isSafeInteger(Number(group.recipe.count))
				&& Number(group.recipe.count) >= 2
				&& Number(group.recipe.count) <= 6
				&& isRecord(group.resultPolicy)
			))
        );
        return (
        isRecord(draft)
        && draft.schemaVersion === 1
        && vm.WORKFLOWS.has(draft.workflow)
        && vm.SOURCE_TYPES.has(draft.sourceType)
        && draft.scope === 'bulk'
        && draft.selection?.strategy === 'explicit'
        && Array.isArray(draft.selection?.selectedIds)
        && draft.selection.selectedIds.length >= 1
		&& draft.selection.selectedIds.length <= limits.maxRunItems
        && draft.selection.selectedIds.every((id) => Number.isSafeInteger(Number(id)) && Number(id) > 0)
        && new Set(draft.selection.selectedIds.map(Number)).size === draft.selection.selectedIds.length
        && isRecord(draft.sourcePolicy)
        && isRecord(draft.recipe)
        && isRecord(draft.resultPolicy)
		&& campaignGroupsValid
		&& plannedOutputs === Number(expectedOutputs)
        && itemCount >= (draft.workflow === 'product_images' ? 2 : 1)
		&& Number(expectedOutputs) >= itemCount
		&& (draft.workflow === 'campaign_set' || Number(expectedOutputs) % itemCount === 0)
        );
    };

	const canStartBulk = ({ draft, preflightCurrent, exact } = {}, operationalLimits) => (
		bulkDraftIsStartable(draft, exact?.totalOutputs, operationalLimits)
		&& preflightCurrent === true
		&& exactPreflightIsCurrent(exact, operationalLimits)
		&& exact.pricing.workflow === draft.workflow
		&& Number(exact.totalItems) === bulkItemCount(draft)
	);

    const buildStartEnvelope = (draft, requestId, itemIdentity) => {
        if (!singleDraftIsStartable(draft) || !UUID_PATTERN.test(requestId) || !isRecord(itemIdentity)) return null;
        const runItemId = vm.cleanText(itemIdentity.runItemId, 36).toLowerCase();
        const campaignGroupId = vm.cleanText(itemIdentity.campaignGroupId, 36).toLowerCase();
		const sourceFingerprint = vm.cleanText(itemIdentity.sourceFingerprint, 64).toLowerCase();
		const authority = isRecord(itemIdentity.authority) ? itemIdentity.authority : null;
        const target = isRecord(itemIdentity.target) ? itemIdentity.target : null;
        const subjectId = Number(draft.selection.selectedIds[0]);
        if (
            !UUID_PATTERN.test(runItemId)
            || (draft.workflow === 'campaign_set' ? !UUID_PATTERN.test(campaignGroupId) : Boolean(campaignGroupId))
            || Number(itemIdentity.itemOrdinal) !== 1
			|| !/^[a-f0-9]{64}$/.test(sourceFingerprint)
			|| !authority
			|| authority.version !== 1
			|| !/^[a-f0-9]{64}$/.test(String(authority.fingerprint || ''))
			|| !Number.isSafeInteger(Number(authority.expiresAt))
			|| Number(authority.expiresAt) <= Math.floor(Date.now() / 1000)
            || !target
            || !['product', 'variation', 'media', 'post', 'page'].includes(String(target.targetType || ''))
            || Number(target.targetId) !== subjectId
            || !Number.isSafeInteger(Number(target.parentProductId))
            || Number(target.parentProductId) < 0
            || !Number.isSafeInteger(Number(target.variationId))
            || Number(target.variationId) < 0
        ) return null;
        return {
            requestId: requestId.toLowerCase(),
            runItemId,
            campaignGroupId: campaignGroupId || null,
            itemOrdinal: 1,
			sourceFingerprint,
			authority: {
				version: 1,
				fingerprint: String(authority.fingerprint),
				expiresAt: Number(authority.expiresAt),
			},
            workflow: draft.workflow,
            sourceType: draft.sourceType,
            scope: 'single',
            subject: {
                id: subjectId,
                targetType: String(target.targetType),
                targetId: Number(target.targetId),
                parentProductId: Number(target.parentProductId),
                variationId: Number(target.variationId),
            },
            sourcePolicy: isRecord(draft.sourcePolicy) ? draft.sourcePolicy : {},
            recipe: draft.workflow === 'campaign_set' && isRecord(draft.sourcePolicy?.groups?.[0]?.recipe)
                ? draft.sourcePolicy.groups[0].recipe
                : (isRecord(draft.recipe) ? draft.recipe : {}),
            resultPolicy: draft.workflow === 'campaign_set' && isRecord(draft.sourcePolicy?.groups?.[0]?.resultPolicy)
                ? draft.sourcePolicy.groups[0].resultPolicy
                : (isRecord(draft.resultPolicy) ? draft.resultPolicy : {}),
        };
    };

	const buildBulkStartEnvelope = (draft, runUuid, snapshotFingerprint, authority, operationalLimits) => {
        const selectedCount = bulkItemCount(draft);
		if (!bulkDraftIsStartable(draft, plannedOutputCount(draft), operationalLimits)
			|| !UUID_PATTERN.test(runUuid)
			|| !/^[a-f0-9]{64}$/.test(String(snapshotFingerprint || ''))
			|| !isRecord(authority)
		) return null;
        try {
            return {
				runUuid: runUuid.toLowerCase(),
				snapshotFingerprint: String(snapshotFingerprint),
				authority: JSON.parse(JSON.stringify(authority)),
				draft: JSON.parse(JSON.stringify(draft)),
            };
        } catch (_) {
            return null;
        }
    };

    const normalizeServerResponse = (raw, identity, operationalLimits) => {
		const limits = normalizeOperationalLimits(operationalLimits);
        if (!limits) return null;
        const value = raw;
        if (!isRecord(value)) return null;
        const responseRequestId = vm.cleanText(value.requestId, 36).toLowerCase();
        const responseWorkflow = vm.cleanText(value.workflow, 64).toLowerCase();
        const responseTarget = vm.cleanText(value.sourceType, 64).toLowerCase();
        const responseSubjectId = vm.positiveInteger(value.subjectId);
        const responseRunItemId = vm.cleanText(value.runItemId, 36).toLowerCase();
        const responseCampaignGroupId = value.campaignGroupId === null
            ? ''
            : vm.cleanText(value.campaignGroupId, 36).toLowerCase();
        const responseItemOrdinal = vm.positiveInteger(value.itemOrdinal);
        const responseTargetIdentity = normalizeTargetIdentity(value.targetIdentity, identity.subjectId, identity.sourceType);
        if (
            (responseRequestId && responseRequestId !== identity.requestId)
            || (responseWorkflow && responseWorkflow !== identity.workflow)
            || (responseTarget && responseTarget !== identity.sourceType)
            || (responseSubjectId && responseSubjectId !== identity.subjectId)
            || (identity.runItemId && (
                responseRunItemId !== identity.runItemId
                || responseCampaignGroupId !== (identity.campaignGroupId || '')
                || responseItemOrdinal !== identity.itemOrdinal
                || !responseTargetIdentity
                || JSON.stringify(normalizeTargetHint(responseTargetIdentity, identity.subjectId, identity.sourceType)) !== JSON.stringify(identity.targetIdentity)
            ))
        ) return null;
        const rawStatus = vm.cleanText(value.status, 32).toLowerCase();
		const attachments = Array.isArray(value.attachments)
			? value.attachments.slice(0, limits.maxOutputsPerItem)
			: [];
        const failedJobIds = normalizeJobIds(value.failedJobIds);
        const jobIds = normalizeJobIds(value.jobIds ?? identity.jobIds);
        const expectedOutputCount = vm.positiveInteger(
            value.expectedOutputCount ?? identity.expectedOutputCount,
            identity.expectedOutputCount,
            10
        );
        return {
            raw: value,
            status: rawStatus || (value.hasActive === true ? 'processing' : ''),
            hasActive: value.hasActive === true,
            runId: vm.cleanText(value.runId ?? identity.runId, 64),
            jobIds,
            failedJobIds,
            attachments,
            expectedOutputCount,
            availableActions: Array.isArray(value.availableActions) ? value.availableActions : [],
            message: vm.cleanText(value.message ?? value.errorMessage, 400),
            errorCode: vm.safeCode(value.errorCode),
            uncertain: value.uncertain === true,
            finalizationPending: value.finalizationPending === true,
            targetIdentity: responseTargetIdentity,
        };
    };

    const normalizeGlobalHistoryPayload = (raw, operationalLimits) => {
		const limits = normalizeOperationalLimits(operationalLimits);
		if (!limits) return {
			page: 1,
			perPage: 5,
			totalPages: 1,
			totalItems: 0,
			query: '',
			status: 'all',
			statusCounts: {},
			runs: [],
		};
        const value = raw;
        const runs = (Array.isArray(value?.runs) ? value.runs : []).slice(0, 50).map((run) => {
            if (!isRecord(run)) return null;
            const resumeIdentity = normalizeIdentity(run.resumeIdentity, limits);
            const runId = vm.cleanText(run.runId, 64);
            const rawWorkflow = vm.cleanText(run.workflow, 64).toLowerCase();
            const rawSourceType = vm.cleanText(run.sourceType, 64).toLowerCase();
            const rawScope = vm.cleanText(run.scope, 64).toLowerCase();
            if (!runId || !vm.WORKFLOWS.has(rawWorkflow) || !vm.SOURCE_TYPES.has(rawSourceType) || !vm.SCOPES.has(rawScope)) return null;
			const route = vm.normalizeRoute(run);
            return {
                ...run,
				...route,
                runId,
                subjectId: vm.nonNegativeInteger(run.subjectId, 0, Number.MAX_SAFE_INTEGER),
                requestId: vm.cleanText(run.requestId, 36).toLowerCase(),
                resumeIdentity,
                detailAvailable: resumeIdentity !== null && run.detailAvailable !== false,
                aggregateOnly: run.aggregateOnly === true,
                attachments: Array.isArray(run.attachments) ? run.attachments.slice(0, 12) : [],
                availableActions: Array.isArray(run.availableActions) ? run.availableActions.slice(0, 10) : [],
                groups: Array.isArray(run.groups) ? run.groups.slice(0, 50) : [],
                source: isRecord(run.source) ? run.source : null,
				quality: vm.normalizeOutputQuality(run.quality, route.workflow),
            };
        }).filter(Boolean);
        const rawStatus = vm.cleanText(value?.status, 32).toLowerCase();
        const statusCounts = Object.fromEntries(Object.entries(
            isRecord(value?.statusCounts) ? value.statusCounts : {}
        ).filter(([status]) => HISTORY_STATUSES.has(status)).map(([status, count]) => [
            status,
            vm.nonNegativeInteger(count, 0, 100000),
        ]));
        return {
            page: vm.positiveInteger(value?.page, 1, 1000),
            perPage: vm.positiveInteger(value?.perPage, 5, 48),
            totalPages: vm.positiveInteger(value?.totalPages, 1, 1000),
            totalItems: vm.nonNegativeInteger(value?.totalItems, 0, 100000),
            query: vm.cleanText(value?.query, 200),
            status: rawStatus === 'all' || HISTORY_STATUSES.has(rawStatus) ? rawStatus : 'all',
            statusCounts,
            runs,
        };
    };

    const historyBackLabelForView = (view) => ({
        select: __( 'Back to Select', 'fotogenic-ai' ),
        configure: __( 'Back to Configure', 'fotogenic-ai' ),
        review: __( 'Back to Generate', 'fotogenic-ai' ),
        progress: __( 'Back to Generate', 'fotogenic-ai' ),
        error: __( 'Back to Generate', 'fotogenic-ai' ),
        results: __( 'Back to Summary', 'fotogenic-ai' ),
    }[view] || __( 'Back', 'fotogenic-ai' ));

    const normalizeBulkActive = (raw, identity) => {
        const value = raw;
        if (value === null) return { active: false };
        if (!isRecord(value)) return null;
        const runUuid = vm.cleanText(value.runUuid, 36).toLowerCase();
        const workflow = vm.cleanText(value.workflow, 64).toLowerCase();
        const status = vm.cleanText(value.status, 32).toLowerCase();
        if (
            runUuid !== identity.runUuid
            || workflow !== identity.workflow
            || !BULK_SERVER_STATUSES.has(status)
        ) return null;
        return { active: BULK_ACTIVE_STATUSES.has(status) || status === 'paused', status };
    };

	const normalizeBulkRecoveryIdentity = (raw, operationalLimits) => {
		const value = raw;
		if (!isRecord(value)) return null;
		const recovered = normalizeIdentity(value.recoveryIdentity, operationalLimits);
		return recovered?.scope === 'bulk' ? recovered : null;
	};

    const normalizeBulkProgress = (raw, identity, { page = 1, hasNext = false } = {}, operationalLimits) => {
		const limits = normalizeOperationalLimits(operationalLimits);
		if (!limits) return null;
        const value = raw;
        if (!isRecord(value) || !isRecord(value.run) || !Array.isArray(value.items)) return null;
        const run = value.run;
        const runUuid = vm.cleanText(run.runUuid, 36).toLowerCase();
        const workflow = vm.cleanText(run.workflow, 64).toLowerCase();
        const serverStatus = vm.cleanText(run.status, 32).toLowerCase();
		const selectedCount = strictPositiveInteger(run.selectedCount, limits.maxRunItems);
		const expectedOutputCount = strictPositiveInteger(identity.expectedOutputCount, limits.maxRunOutputs);
        if (
            runUuid !== identity.runUuid
            || workflow !== identity.workflow
            || !BULK_SERVER_STATUSES.has(serverStatus)
            || selectedCount !== identity.selectedCount
			|| !expectedOutputCount
			|| value.items.length !== selectedCount
        ) return null;

        const rawCounts = isRecord(run.counts) ? run.counts : {};
        const count = (name) => vm.nonNegativeInteger(rawCounts[name], 0, 100000);
		const completed = count('completed') + count('partial');
		const failed = count('failed') + count('skipped') + count('uncertain');
		const inFlight = count('starting') + count('processing');
		const processing = count('queued') + count('starting') + count('processing');
        if (count('total') !== selectedCount || completed + failed + processing !== selectedCount) return null;
		const itemStatuses = new Set(['queued', 'starting', 'processing', 'completed', 'partial', 'failed', 'skipped', 'uncertain', 'removed']);
        const seenItems = new Set();
        const items = [];
        for (const [index, item] of value.items.slice(0, limits.maxRunItems).entries()) {
            if (!isRecord(item)) return null;
            const itemId = vm.positiveInteger(item.id);
			const subjectId = vm.positiveInteger(item.subjectId);
			const subjectType = vm.cleanText(item.subjectType, 32).toLowerCase();
            const rawItemStatus = vm.cleanText(item.status, 32).toLowerCase();
			const status = itemStatuses.has(rawItemStatus) ? rawItemStatus : '';
            if (!itemId || !subjectId || subjectType !== identity.sourceType || !status || seenItems.has(itemId)) return null;
            seenItems.add(itemId);
			const runItemId = vm.cleanText(item.runItemId, 36).toLowerCase();
			const campaignGroupId = vm.cleanText(item.campaignGroupId, 36).toLowerCase();
			const itemOrdinal = vm.positiveInteger(item.itemOrdinal);
			const target = normalizeTargetIdentity(item.targetIdentity, subjectId, subjectType);
            const hasItemIdentity = Boolean(runItemId || campaignGroupId || itemOrdinal || target);
            if (hasItemIdentity && (
                !UUID_PATTERN.test(runItemId)
                || (identity.workflow === 'campaign_set' ? !UUID_PATTERN.test(campaignGroupId) : Boolean(campaignGroupId))
                || !itemOrdinal
                || !target
            )) return null;
            let result = null;
            if (isRecord(item.result)) {
                const resultRequestId = vm.cleanText(item.result.requestId, 36).toLowerCase();
				const resultRunId = vm.cleanText(item.result.runId, 64);
                const resultBulkUuid = vm.cleanText(item.result.bulkRunUuid, 36).toLowerCase();
                const resultBulkItemId = vm.positiveInteger(item.result.bulkItemId);
                const resultWorkflow = vm.cleanText(item.result.workflow, 64).toLowerCase();
                const resultSourceType = vm.cleanText(item.result.sourceType, 32).toLowerCase();
                const resultSubjectId = vm.positiveInteger(item.result.subjectId);
                const resultRunItemId = vm.cleanText(item.result.runItemId, 36).toLowerCase();
                const resultCampaignGroupId = vm.cleanText(item.result.campaignGroupId, 36).toLowerCase();
                const resultItemOrdinal = vm.positiveInteger(item.result.itemOrdinal);
                const resultTarget = normalizeTargetIdentity(item.result.targetIdentity, resultSubjectId, resultSourceType);
                if (
                    UUID_PATTERN.test(resultRequestId)
                    && resultRunId
                    && resultBulkUuid === identity.runUuid
                    && resultBulkItemId === itemId
                    && resultWorkflow === identity.workflow
                    && resultSourceType === identity.sourceType
                    && item.result.scope === 'bulk'
                    && resultSubjectId === subjectId
					&& ['completed', 'partial', 'removed'].includes(vm.cleanText(item.result.status, 32).toLowerCase())
                    && (!hasItemIdentity || (
                        resultRunItemId === runItemId
                        && resultCampaignGroupId === campaignGroupId
                        && resultItemOrdinal === itemOrdinal
                        && Studio.store.stableStringify(resultTarget) === Studio.store.stableStringify(target)
                    ))
                ) {
                    result = {
                        identity: {
                            version: RECORD_VERSION,
                            workflow: resultWorkflow,
                            sourceType: resultSourceType,
                            scope: 'bulk',
                            subjectId,
                            requestId: resultRequestId,
                            runId: resultRunId,
                            bulkRunUuid: resultBulkUuid,
                            bulkItemId: resultBulkItemId,
                            ...(UUID_PATTERN.test(resultRunItemId) ? {
                                runItemId: resultRunItemId,
                                campaignGroupId: resultCampaignGroupId,
                                itemOrdinal: resultItemOrdinal,
                                targetIdentity: resultTarget,
                            } : {}),
                        },
                        raw: item.result,
                        status: vm.cleanText(item.result.status, 32).toLowerCase(),
                        attachments: Array.isArray(item.result.attachments) ? item.result.attachments.slice(0, 10) : [],
                        availableActions: Array.isArray(item.result.availableActions) ? item.result.availableActions : [],
                        message: vm.cleanText(item.result.message, 400),
                    };
                }
            }
			const attachments = vm.normalizeAttachments(item.attachments, 10);
			const attachmentCount = result?.attachments.length || attachments.length;
			const expectedOutputs = strictPositiveInteger(item.expectedOutputCount, limits.maxOutputsPerItem)
				|| strictPositiveInteger(identity.outputsPerItem, limits.maxOutputsPerItem);
			const completedOutputs = vm.nonNegativeInteger(item.completedOutputs, 0, expectedOutputs);
			const failedOutputs = vm.nonNegativeInteger(item.failedOutputs, 0, expectedOutputs);
			if (!expectedOutputs || completedOutputs !== attachmentCount || completedOutputs + failedOutputs > expectedOutputs) return null;
			if (
				(status === 'removed' && (
					result?.status !== 'removed'
					|| attachmentCount !== 0
					|| completedOutputs !== 0
					|| failedOutputs !== 0
					|| result.availableActions.length !== 0
				))
				|| (status !== 'removed' && result?.status === 'removed')
			) return null;
			const presentationStatus = serverStatus === 'paused' && status === 'queued'
				? 'paused'
				: status;
			items.push({
                key: `item-${itemId}`,
                itemId,
                subjectId,
                runItemId,
                campaignGroupId,
                itemOrdinal,
                targetIdentity: target,
                label: identity.workflow === 'campaign_set' && itemOrdinal
                    ? sprintf( __( 'Campaign Set %d', 'fotogenic-ai' ), itemOrdinal )
                    : sprintf( __( 'Item %d', 'fotogenic-ai' ), index + 1 ),
				status: presentationStatus,
				totalOutputs: expectedOutputs,
				completedOutputs,
				failedOutputs,
				message: vm.cleanText(item.errorMessage, 300),
				result,
				attachments,
				updatedAt: vm.nonNegativeInteger(item.updatedAt, 0, Number.MAX_SAFE_INTEGER),
				finishedAt: vm.nonNegativeInteger(item.finishedAt, 0, Number.MAX_SAFE_INTEGER),
			});
        }
		items.sort((left, right) => {
			return left.itemOrdinal - right.itemOrdinal || left.itemId - right.itemId;
		});
		if (items.reduce((total, item) => total + item.totalOutputs, 0) !== expectedOutputCount) return null;
		const allResultsRemoved = items.length > 0 && items.every((item) => item.status === 'removed');

		let status = serverStatus === 'completed' && failed > 0 ? 'partial' : serverStatus;
		if (status === 'completed' && vm.cleanText(run.statusReason, 64).toLowerCase() === 'partial') status = 'partial';
        const normalizedPage = vm.positiveInteger(page, 1, 1000);
		return {
            status,
            serverStatus,
			allResultsRemoved,
			statusReason: vm.safeCode(run.statusReason),
            items,
			outputCounts: {
				total: expectedOutputCount,
				completed: items.reduce((total, item) => total + item.completedOutputs, 0),
				failed: items.reduce((total, item) => total + item.failedOutputs, 0),
			},
            page: normalizedPage,
            totalPages: normalizedPage + (hasNext ? 1 : 0),
            totalItems: selectedCount,
            hasNext,
            inFlight,
            counts: { total: selectedCount, completed, failed, processing },
			controls: {
				checkStatus: true,
				pause: serverStatus === 'processing',
				resume: serverStatus === 'paused' && vm.safeCode(run.statusReason) !== 'authority_changed',
				reviewAuthority: serverStatus === 'paused' && vm.safeCode(run.statusReason) === 'authority_changed',
				stop: ['processing', 'paused'].includes(serverStatus),
            },
        };
    };

	const normalizeStoreQueueProgress = (raw, identity, operationalLimits) => {
		if (!isRecord(raw) || !isRecord(raw.queue) || !isRecord(raw.counts) || !isRecord(raw.items)) return null;
		const queue = raw.queue;
		const queueUuid = vm.cleanText(queue.queueUuid, 36).toLowerCase();
		if (identity?.scope !== 'store_queue' || queueUuid !== identity.queueUuid) return null;
		const statusMap = {
			preparing: 'starting', reviewing: 'starting', ready: 'queued', running: 'processing', paused: 'paused',
			stopping: 'stopping', stopped: 'stopped', completed: 'completed', partial: 'partial', failed: 'failed', uncertain: 'uncertain', expired: 'stopped',
		};
		const serverQueueStatus = vm.safeCode(queue.status);
		const status = statusMap[serverQueueStatus];
		if (!status) return null;
		const selectedCount = strictPositiveInteger(queue.selectedCount, STORE_QUEUE_ITEM_LIMIT) || identity.selectedCount;
		const expectedOutputCount = strictPositiveInteger(queue.expectedOutputCount, STORE_QUEUE_OUTPUT_LIMIT) || identity.expectedOutputCount;
		const outputsPerItem = selectedCount > 0 && expectedOutputCount % selectedCount === 0
			? expectedOutputCount / selectedCount
			: 0;
		let child = null;
		if (isRecord(raw.currentChild) && isRecord(raw.currentChild.run) && Array.isArray(raw.currentChild.items)) {
			const childSelected = strictPositiveInteger(raw.currentChild.run.selectedCount, 12);
			const childExpected = raw.currentChild.items.reduce((total, item) => total + Math.max(0, Math.floor(Number(item?.expectedOutputCount)) || 0), 0)
				|| childSelected * outputsPerItem;
			if (childSelected && childExpected) {
				child = normalizeBulkProgress(raw.currentChild, {
					version: 1,
					workflow: 'product_images',
					sourceType: 'product',
					scope: 'bulk',
					runUuid: vm.cleanText(raw.currentChild.run.runUuid, 36).toLowerCase(),
					status,
					selectedCount: childSelected,
					expectedOutputCount: childExpected,
					...(outputsPerItem ? { outputsPerItem } : {}),
				}, {}, operationalLimits);
			}
		}
		const childBySubject = new Map((child?.items || []).map((item) => [item.subjectId, item]));
		const itemStatusMap = {
			ready: 'queued', ineligible: 'skipped', reserved: 'starting', admitted: 'processing', review_required: 'uncertain',
			completed: 'completed', partial: 'partial', failed: 'failed', skipped: 'skipped', uncertain: 'uncertain',
		};
		const pageItems = Array.isArray(raw.items.items) ? raw.items.items : [];
		const items = pageItems.map((item, index) => {
			const subjectId = vm.positiveInteger(item?.subjectId);
			const childItem = childBySubject.get(subjectId) || null;
			const itemStatus = itemStatusMap[vm.safeCode(item?.status)] || 'uncertain';
			return {
				key: `queue-item-${vm.positiveInteger(item?.id, index + 1)}`,
				itemId: vm.positiveInteger(item?.id, index + 1),
				subjectId,
				itemOrdinal: vm.positiveInteger(item?.ordinal, index + 1),
				label: vm.cleanText(item?.label, 200) || sprintf(__( 'Product %d', 'fotogenic-ai' ), subjectId),
				meta: vm.cleanText(item?.sku, 100) ? sprintf(__( 'SKU %s', 'fotogenic-ai' ), vm.cleanText(item.sku, 100)) : sprintf(__( 'ID %d', 'fotogenic-ai' ), subjectId),
				imageUrl: vm.safeUrl(item?.imageUrl),
				status: childItem?.status || itemStatus,
				totalOutputs: itemStatus === 'skipped' ? 0 : (childItem?.totalOutputs || outputsPerItem),
				completedOutputs: childItem?.completedOutputs || (itemStatus === 'completed' ? outputsPerItem : 0),
				failedOutputs: childItem?.failedOutputs || (['failed', 'partial'].includes(itemStatus) ? outputsPerItem : 0),
				message: vm.cleanText(item?.statusReason, 200),
				result: childItem?.result || null,
				attachments: childItem?.attachments || [],
			};
		}).filter((item) => item.subjectId > 0);
		const count = (name) => vm.nonNegativeInteger(raw.counts[name], 0, STORE_QUEUE_ITEM_LIMIT);
		const totalItems = vm.nonNegativeInteger(raw.items.totalItems, items.length, STORE_QUEUE_ITEM_LIMIT);
		const completed = count('completed') + count('partial');
		const failed = count('failed') + count('skipped') + count('uncertain') + count('review_required') + count('ineligible');
		const processing = Math.max(0, totalItems - completed - failed);
		return {
			status,
			serverStatus: serverQueueStatus,
			statusReason: vm.safeCode(queue.statusReason),
			items,
			page: vm.positiveInteger(raw.items.page, 1, 100000),
			totalPages: vm.positiveInteger(raw.items.totalPages, 1, 100000),
			hasNext: Number(raw.items.page) < Number(raw.items.totalPages),
			totalItems,
			outputCounts: {
				total: expectedOutputCount,
				completed: Math.min(expectedOutputCount, completed * outputsPerItem),
				failed: Math.min(expectedOutputCount, failed * outputsPerItem),
			},
			counts: { total: totalItems, completed, failed, processing },
			inFlight: count('reserved') + count('admitted'),
			controls: {
				checkStatus: true,
				pause: raw.controls?.canPause === true,
				resume: raw.controls?.canResume === true,
				reviewAuthority: raw.controls?.requiresReview === true,
				stop: raw.controls?.canStop === true,
			},
		};
	};

	const paginateBulkProgress = (model, page = 1, pageSize = BULK_PAGE_SIZE) => {
		if (!isRecord(model) || !Array.isArray(model.items)) return null;
		const normalizedPageSize = strictPositiveInteger(pageSize, 100) || BULK_PAGE_SIZE;
		const totalPages = Math.max(1, Math.ceil(model.items.length / normalizedPageSize));
		const normalizedPage = Math.min(totalPages, vm.positiveInteger(page, 1, 1000));
		const offset = (normalizedPage - 1) * normalizedPageSize;
		return {
			...model,
			items: model.items.slice(offset, offset + normalizedPageSize),
			page: normalizedPage,
			totalPages,
			hasNext: normalizedPage < totalPages,
		};
	};

	const buildBulkPreparingItems = ({ draft = null, selectedCount = 0, outputCounts = [] } = {}) => {
		const count = strictPositiveInteger(selectedCount, 100000) || 0;
		const groups = Array.isArray(draft?.sourcePolicy?.groups) ? draft.sourcePolicy.groups : [];
		const selectedIds = Array.isArray(draft?.selection?.selectedIds)
			? draft.selection.selectedIds.map((id) => vm.positiveInteger(id)).filter(Boolean)
			: [];
		return Array.from({ length: count }, (_unused, index) => {
			const group = groups[index] || null;
			const subjectId = vm.positiveInteger(group?.subjectId) || selectedIds[index] || 0;
			const targetLabel = vm.cleanText(group?.target?.label, 200);
			return {
				key: `preparing-${index + 1}`,
				itemId: 0,
				subjectId,
				itemOrdinal: index + 1,
				targetIdentity: isRecord(group?.target) ? group.target : null,
				label: targetLabel || sprintf(__( 'Run item %d', 'fotogenic-ai' ), index + 1),
				status: 'starting',
				totalOutputs: vm.nonNegativeInteger(outputCounts[index], 0, 100),
				completedOutputs: 0,
				failedOutputs: 0,
				attachments: [],
			};
		});
	};

	const projectBulkControlModel = (model, action) => {
		if (!isRecord(model) || !Array.isArray(model.items) || !['pause', 'resume', 'stop'].includes(action)) return null;
		const status = { pause: 'pausing', resume: 'processing', stop: 'stopping' }[action];
		const items = model.items.map((item) => {
			if (!isRecord(item)) return item;
			if (action === 'pause' && item.status === 'queued') return { ...item, status: 'paused' };
			if (action === 'resume' && item.status === 'paused') return { ...item, status: 'queued' };
			if (action === 'stop' && ['queued', 'paused'].includes(item.status)) return { ...item, status: 'stopping' };
			return item;
		});
		return {
			...model,
			status,
			serverStatus: status,
			items,
			controls: { checkStatus: false, pause: false, resume: false, reviewAuthority: false, stop: false },
		};
	};

	const buildBulkSummaryGroups = (model, getSource = () => null) => {
		if (!isRecord(model) || !Array.isArray(model.items)) return [];
		return model.items.map((item) => {
			const raw = isRecord(item.result?.raw) ? item.result.raw : {};
			const attachments = item.result?.attachments || item.attachments || [];
			const selectedSource = getSource(item.subjectId);
			const source = isRecord(raw.source)
				? raw.source
				: (selectedSource?.imageUrl && vm.positiveInteger(selectedSource.attachmentId)
					? {
						attachmentId: selectedSource.attachmentId,
						fullUrl: selectedSource.imageUrl,
						thumbUrl: selectedSource.imageUrl,
						label: selectedSource.label,
					}
					: null);
			return {
				key: item.key,
				label: item.targetIdentity?.label || item.label,
				status: raw.deliveryFailed === true
					? 'partial'
					: (['completed', 'partial', 'failed', 'skipped', 'uncertain', 'removed'].includes(item.status)
					? item.status
					: (item.result ? 'completed' : 'failed')),
				message: item.message || item.result?.message || '',
				attachments,
				availableActions: item.result?.availableActions || [],
				unappliedActions: Array.isArray(raw.unappliedActions) ? raw.unappliedActions : [],
					appliedAction: vm.cleanText(raw.appliedAction, 64).toLowerCase(),
					appliedAttachmentId: vm.positiveInteger(raw.appliedAttachmentId),
					appliedAttachmentIds: Array.isArray(raw.appliedAttachmentIds) ? raw.appliedAttachmentIds : [],
				deliveryPending: raw.deliveryPending === true,
				deliveryFailed: raw.deliveryFailed === true,
				deliveryRetryAvailable: raw.deliveryRetryAvailable === true,
				source,
				sources: Array.isArray(raw.sources) ? raw.sources : [],
				sourceMissing: raw.sourceMissing === true || !source,
					currentProduct: isRecord(raw.currentProduct) ? raw.currentProduct : null,
					currentProductMissing: raw.currentProductMissing === true,
					targetIdentity: item.targetIdentity,
					targetLinks: isRecord(raw.targetLinks) ? raw.targetLinks : null,
					quality: vm.normalizeOutputQuality(raw.quality, raw.workflow),
					deliveryLabel: vm.cleanText(raw.deliveryLabel, 120),
					requestedOutputCount: item.totalOutputs,
				savedOutputCount: attachments.length,
			};
		});
	};

    const createRunController = ({
        transport,
        shell,
		operationalLimits,
        mounts = {},
        storage = window.sessionStorage,
        uuidFactory = () => Shared.identity?.createSecureUuid?.() || '',
        schedule = (callback, delay) => window.setTimeout(callback, delay),
        cancelSchedule = (timer) => window.clearTimeout(timer),
        confirmAction = window.confirm?.bind(window),
		onCreateAnother = () => {},
		onBackToCompose = () => {},
        onReturnToReview = null,
		onNavigationStateChange = () => {},
		getSource = () => null,
		onCreditsRefreshRequested = () => {},
		onRunLifecycle = () => {},
    } = {}) => {
		const limits = normalizeOperationalLimits(operationalLimits);
		if (!limits) throw new Error('invalid_operational_limits');
        let identity = readStoredIdentity(storage, limits);
        let pollTimer = null;
        let pollPending = false;
		let pollAttempt = 0;
        let startPending = false;
        let destroyed = false;
        let lastResults = null;
        let lastResultHandlers = {};
        let currentResultsReturn = null;
        let lastBulkProgress = null;
		let latestBulkProgress = null;
		let bulkPage = 1;
		let globalHistoryReturn = null;
		let globalHistoryLoadSequence = 0;
		let pendingBulkRecovery = readPendingBulkRecovery(storage, limits);
		let singleCreditsRefreshEnabled = false;
		let singleAcceptedCreditsRefreshed = false;
		let singleTerminalCreditsRefreshed = false;
		let bulkCreditsRefreshEnabled = false;
		let bulkAcceptedItemCount = 0;
        let bulkTerminalCreditsRefreshed = false;
		let bulkProgressSequence = 0;
		let bulkControlPending = false;
		let storeQueueControlPending = false;
		let summaryTransition = null;
		const lifecycleEvents = new Set();

		const runEpisode = () => vm.cleanText(
			identity?.scope === 'store_queue'
				? identity.queueUuid
				: (identity?.scope === 'bulk' ? identity.runUuid : (identity?.runId || identity?.requestId)),
			64
		).toLowerCase();
		const notifyRunLifecycle = (status) => {
			const lifecycleStatus = vm.cleanText(status, 32).toLowerCase();
			if (!['started', 'completed', 'partial', 'failed', 'stopped'].includes(lifecycleStatus)) return;
			const runId = runEpisode();
			if (!runId) return;
			const key = `${runId}:${lifecycleStatus}`;
			if (lifecycleEvents.has(key)) return;
			lifecycleEvents.add(key);
			onRunLifecycle({
				status: lifecycleStatus,
				runId,
				workflow: identity?.workflow || '',
				sourceType: identity?.sourceType || '',
				scope: identity?.scope || '',
			});
		};

        const progressView = Studio.progress.createProgressView({
            mount: mounts.progress,
            errorMount: mounts.error,
            announce: shell.announce,
            confirmAction,
        });
        const bulkView = Studio.bulk.createBulkView({ announce: shell.announce, confirmAction });
        const resultsView = Studio.results.createResultsView({
            mount: mounts.results,
            announce: shell.announce,
        });
        const historyView = Studio.history.createHistoryView({
            mount: mounts.results,
            announce: shell.announce,
        });

        const persist = (updates = {}) => {
            if (!identity) return false;
            identity = normalizeIdentity({ ...identity, ...updates }, limits);
            return identity ? writeStoredIdentity(storage, identity, limits) : false;
        };

		const getNavigationState = () => ({
			stored: Boolean(identity),
			blocking: Boolean(identity) && !TERMINAL_STATUSES.has(identity.status),
			summaryAvailable: typeof summaryTransition === 'function',
		});

		const notifyNavigationState = () => onNavigationStateChange(getNavigationState());

        const clearPoll = () => {
            if (pollTimer !== null) cancelSchedule(pollTimer);
            pollTimer = null;
        };

		const clearIdentity = ({ preserveRecovery = false } = {}) => {
			clearPoll();
			identity = null;
			if (!preserveRecovery) {
				pendingBulkRecovery = null;
				clearPendingBulkRecovery(storage);
			}
            bulkPage = 1;
			pollAttempt = 0;
			latestBulkProgress = null;
			singleCreditsRefreshEnabled = false;
			singleAcceptedCreditsRefreshed = false;
			singleTerminalCreditsRefreshed = false;
			bulkCreditsRefreshEnabled = false;
			bulkAcceptedItemCount = 0;
			bulkTerminalCreditsRefreshed = false;
            currentResultsReturn = null;
			summaryTransition = null;
            clearStoredIdentity(storage);
			notifyNavigationState();
        };

		const requestCreditsRefresh = (reason) => {
			onCreditsRefreshRequested({
				scope: identity?.scope || '',
				reason,
			});
		};

		const refreshCreditsForSingleResponse = (response) => {
			if (
				!singleCreditsRefreshEnabled
				|| singleTerminalCreditsRefreshed
				|| identity?.scope !== 'single'
				|| !isRecord(response)
				|| response.finalizationPending === true
				|| !TERMINAL_STATUSES.has(response.status)
			) return;
			const acceptedJobIds = Array.isArray(response.jobIds) && response.jobIds.length
				? response.jobIds
				: identity.jobIds;
			if (!Array.isArray(acceptedJobIds) || !acceptedJobIds.length) return;
			singleTerminalCreditsRefreshed = true;
			requestCreditsRefresh('terminal');
		};

		const refreshCreditsForBulkProgress = (model) => {
			if (!bulkCreditsRefreshEnabled || !isRecord(model) || !Array.isArray(model.items)) return;
			const acceptedItemCount = model.items.filter((item) => (
				['processing', 'completed', 'partial'].includes(item.status)
			)).length;
			const terminal = ['completed', 'partial', 'failed', 'stopped'].includes(model.status);
			if (terminal) {
				bulkAcceptedItemCount = Math.max(bulkAcceptedItemCount, acceptedItemCount);
				if (!bulkTerminalCreditsRefreshed) {
					bulkTerminalCreditsRefreshed = true;
					requestCreditsRefresh('terminal');
				}
				return;
			}
			if (acceptedItemCount > bulkAcceptedItemCount) {
				bulkAcceptedItemCount = acceptedItemCount;
				requestCreditsRefresh('accepted_item_count');
			}
		};

		const progressModel = (response = {}) => {
			const completed = response.attachments?.length || 0;
			const failed = response.failedJobIds?.length || 0;
			const total = response.expectedOutputCount || identity?.expectedOutputCount || 1;
			const selectedSource = getSource(identity?.subjectId) || null;
			const serverSource = isRecord(response.raw?.source) ? response.raw.source : null;
			const durableLabel = identity?.sourceType === 'media'
				? serverSource?.label || response.targetIdentity?.label
				: response.targetIdentity?.label;
			const sourceLabel = vm.cleanText(
				durableLabel || selectedSource?.label,
				200
			);
			const sourceImageUrl = vm.safeUrl(
				serverSource?.thumbUrl || serverSource?.fullUrl || selectedSource?.imageUrl
			);
			const status = RUN_STATUSES.has(response.status)
				? response.status
				: 'processing';
			return {
				...identity,
				status,
				counts: { total, completed, failed, processing: Math.max(0, total - completed - failed) },
				activeSource: sourceLabel || sourceImageUrl
					? { label: sourceLabel, imageUrl: sourceImageUrl }
					: null,
				message: response.message,
                pollIntervalSeconds: pollDelayMs(Math.max(0, pollAttempt - 1), 'single') / 1000,
                controls: { checkStatus: false },
            };
        };

        const showProgress = (response = {}, handlers = {}) => {
			summaryTransition = typeof handlers.openSummary === 'function' ? handlers.openSummary : null;
            const model = progressModel(response);
            const rendered = progressView.render({
                ...model,
                controls: {
                    ...model.controls,
                    viewResults: typeof handlers.openSummary === 'function',
                },
            }, {
                checkStatus: () => checkStatus(),
                openSummary: handlers.openSummary,
            });
            bulkView.setMount(rendered?.bulkMount || null);
            shell.setView('progress', { announcement: __( 'Generation progress.', 'fotogenic-ai' ) });
			notifyNavigationState();
        };

		const showBulkProgress = (model, { summaryModel = null } = {}) => {
			summaryTransition = summaryModel ? () => renderBulkSummary(summaryModel) : null;
            lastBulkProgress = model;
			const totalOutputs = vm.nonNegativeInteger(
				model.outputCounts?.total,
				identity?.expectedOutputCount || 0,
				Number.MAX_SAFE_INTEGER,
			);
			const progressCounts = {
				total: totalOutputs,
				completed: Math.min(totalOutputs, vm.nonNegativeInteger(model.outputCounts?.completed, 0, Number.MAX_SAFE_INTEGER)),
				failed: Math.min(totalOutputs, vm.nonNegativeInteger(model.outputCounts?.failed, 0, Number.MAX_SAFE_INTEGER)),
			};
            const rendered = progressView.render({
                ...identity,
				scope: 'bulk',
                status: model.status,
				allResultsRemoved: model.allResultsRemoved,
				counts: progressCounts,
				pollIntervalSeconds: pollDelayMs(Math.max(0, pollAttempt - 1), 'bulk') / 1000,
				message: model.statusReason === 'authority_changed'
					? __( 'The connected account, API environment, pricing, or configuration changed. Review this exact saved request again before any pending billable item can start.', 'fotogenic-ai' )
					: '',
                controls: { checkStatus: model.status === 'uncertain' },
            }, { checkStatus: () => checkStatus() });
            bulkView.setMount(rendered?.bulkMount || null);
            const items = model.items.map((item) => {
                const source = getSource(item.subjectId);
				const sourceLabel = item.targetIdentity?.label
                    || source?.label
					|| item.label
                    || sprintf( __( '%1$s %2$d', 'fotogenic-ai' ), Studio.i18n.labels[identity.sourceType] || identity.sourceType, item.subjectId );
                return {
                    ...item,
					imageUrl: source?.imageUrl || item.imageUrl || '',
					meta: item.targetIdentity?.sku
						? sprintf( __( 'SKU %s', 'fotogenic-ai' ), item.targetIdentity.sku )
						: (item.meta || (item.subjectId ? sprintf( __( 'ID %d', 'fotogenic-ai' ), item.subjectId ) : '')),
                    label: identity.workflow === 'campaign_set' && item.itemOrdinal
                        ? sprintf( __( 'Campaign Set %1$d · %2$s', 'fotogenic-ai' ), item.itemOrdinal, sourceLabel )
                        : sourceLabel,
                };
            });
			bulkView.render({ ...identity, scope: 'bulk', ...model, pollIntervalSeconds: pollDelayMs(Math.max(0, pollAttempt - 1), 'bulk') / 1000, items }, {
				checkStatus: () => checkStatus(),
				pause: () => identity?.scope === 'store_queue' ? controlStoreQueue('pause') : controlBulkRun('pause'),
				resume: () => identity?.scope === 'store_queue' ? controlStoreQueue('resume') : controlBulkRun('resume'),
				reviewAuthority() {
					if (!identity || identity.scope !== 'bulk' || model.statusReason !== 'authority_changed') throw new Error('unsupported');
					const recovery = {
						runUuid: identity.runUuid,
						workflow: identity.workflow,
						sourceType: identity.sourceType,
						selectedCount: identity.selectedCount,
					};
					if (!writePendingBulkRecovery(storage, recovery, limits)) throw new Error('recovery_identity_not_saved');
					pendingBulkRecovery = recovery;
					clearIdentity({ preserveRecovery: true });
					onBackToCompose();
					shell.setView('configure', { announcement: __( 'Configure step. Review the current saved Bulk request.', 'fotogenic-ai' ) });
				},
                stop: () => identity?.scope === 'store_queue' ? controlStoreQueue('stop') : controlBulkRun('stop'),
				page: (page) => identity?.scope === 'store_queue' ? loadStoreQueueProgress(page) : loadBulkProgress(page),
				viewItem(item) {
					clearPoll();
					if (!item?.result) throw new Error('missing_result');
					renderResults(item.result, {
                        remember: false,
						back() {
							if (lastBulkProgress) showBulkProgress(lastBulkProgress);
							void (identity?.scope === 'store_queue' ? loadStoreQueueProgress(bulkPage) : loadBulkProgress(bulkPage));
						},
					});
				},
				openSummary: summaryTransition || undefined,
            });
            shell.setView('progress', { announcement: __( 'Bulk generation progress.', 'fotogenic-ai' ) });
			notifyNavigationState();
        };

        const backToConfigure = () => {
            clearIdentity();
            onBackToCompose();
            shell.setView('configure', { announcement: __( 'Configure step.', 'fotogenic-ai' ) });
        };

        const showRecovery = (kind, message, code = '') => {
			summaryTransition = null;
            progressView.renderError({ kind, message, code }, {
                checkStatus: ['uncertain', 'finalization_delay', 'partial_result'].includes(kind) ? () => checkStatus() : undefined,
                backToCompose: ['uncertain', 'finalization_delay'].includes(kind) ? undefined : backToConfigure,
                viewResults: kind === 'partial_result' && lastResults ? () => renderResults(lastResults) : undefined,
            });
            shell.setView('error', { announcement: __( 'Generation needs attention.', 'fotogenic-ai' ) });
			notifyNavigationState();
        };

		const openSummary = () => {
			if (typeof summaryTransition !== 'function') return false;
			summaryTransition();
			return true;
		};

		const leaveTerminalRun = () => {
			if (!identity || !TERMINAL_STATUSES.has(identity.status)) return false;
			const route = routeFromIdentity(identity);
			if (!route || onCreateAnother(route) === false) return false;
			clearIdentity();
			return true;
		};

        const resultAction = async (action, payload, actionIdentity = identity) => {
            if (!actionIdentity || !['apply_featured', 'apply_gallery', 'apply_both', 'add_selected_to_gallery', 'add_all_to_gallery'].includes(action)) throw new Error('unsupported');
            const attachmentIds = Array.isArray(payload?.attachmentIds)
                ? payload.attachmentIds
                : [payload?.attachmentId];
            const result = await transport.applyResult(actionIdentity, action, attachmentIds);
            if (!result.ok) throw new Error('failed');
            return result.data;
        };

        const openGlobalHistoryRun = async (run, page, perPage, query = '', status = 'all') => {
            const resumed = normalizeIdentity(run?.resumeIdentity, limits);
            if (!resumed) throw new Error('invalid_history_identity');
            clearPoll();
            identity = resumed;
            if (!writeStoredIdentity(storage, identity, limits)) throw new Error('history_identity_not_saved');
			if (identity.scope === 'store_queue') {
				showBulkProgress({
					status: identity.status,
					serverStatus: identity.status === 'paused' ? 'paused' : 'running',
					items: [],
					page: 1,
					totalPages: Math.max(1, Math.ceil(identity.selectedCount / STORE_QUEUE_PAGE_SIZE)),
					totalItems: identity.selectedCount,
					hasNext: identity.selectedCount > STORE_QUEUE_PAGE_SIZE,
					outputCounts: { total: identity.expectedOutputCount, completed: 0, failed: 0 },
					counts: { total: identity.selectedCount, completed: 0, failed: 0, processing: identity.selectedCount },
					controls: { checkStatus: true, pause: false, resume: false, stop: false },
				});
				await loadStoreQueueProgress(1);
				return;
			}
            if (identity.scope === 'bulk') {
                showBulkProgress({
                    status: identity.status,
                    serverStatus: identity.status === 'paused' ? 'paused' : 'starting',
					items: buildBulkPreparingItems({
						selectedCount: identity.selectedCount,
						outputCounts: Array(identity.selectedCount).fill(identity.outputsPerItem || 0),
					}),
                    page: 1,
                    totalPages: 1,
                    totalItems: identity.selectedCount,
                    hasNext: false,
                    counts: { total: identity.selectedCount, completed: 0, failed: 0, processing: identity.selectedCount },
                    controls: { checkStatus: true, pause: false, resume: false, stop: false },
                });
                await loadBulkProgress(1);
                return;
            }
			if (identity.status === 'stopped' && (!Array.isArray(run.attachments) || !run.attachments.length)) {
				throw new Error('stopped_run_has_no_saved_results');
			}
			if (identity.status === 'failed' && (!Array.isArray(run.attachments) || !run.attachments.length)) {
				const route = routeFromIdentity(identity);
				if (!route || onCreateAnother(route) === false) throw new Error('unsupported_route');
				clearIdentity();
				return;
			}
			if (identity.status === 'removed' || (['completed', 'partial', 'failed', 'stopped'].includes(identity.status) && Array.isArray(run.attachments) && run.attachments.length)) {
                renderResults({
                    raw: run,
                    status: run.status,
                    attachments: run.attachments,
                    availableActions: run.availableActions,
                    message: run.message,
                }, { remember: false, back: () => loadGlobalHistory(page, {
                    preserveReturn: true,
                    perPage,
                    query,
                    status,
                }) });
                return;
            }
            showProgress({ status: identity.status, expectedOutputCount: identity.expectedOutputCount });
            await reconcile();
        };

        const loadGlobalHistory = async (page = 1, {
            preserveReturn = false,
            perPage = 5,
            reset = false,
            query = '',
            status = 'all',
        } = {}) => {
            if (typeof transport.getGlobalHistory !== 'function') return false;
            const normalizedQuery = vm.cleanText(query, 200);
            const requestedStatus = vm.cleanText(status, 32).toLowerCase();
            const normalizedStatus = HISTORY_STATUSES.has(requestedStatus) ? requestedStatus : 'all';
            const loadSequence = ++globalHistoryLoadSequence;
            if (!preserveReturn) {
                const returnView = shell.getCurrentView();
                const returnToView = returnView === 'review' && typeof onReturnToReview === 'function'
                    ? onReturnToReview
                    : () => shell.setView(returnView, { announcement: __( 'Returned to the previous Studio step.', 'fotogenic-ai' ) });
                const returnResults = returnView === 'results' && typeof currentResultsReturn === 'function'
                    ? currentResultsReturn
                    : returnToView;
                globalHistoryReturn = {
                    callback: () => {
                        globalHistoryLoadSequence += 1;
                        return returnResults();
                    },
                    label: historyBackLabelForView(returnView),
                };
            }
            historyView.render({ loading: true, runs: [], page, perPage, query: normalizedQuery, status: normalizedStatus }, {
                back: globalHistoryReturn?.callback,
                backLabel: globalHistoryReturn?.label,
            }, { reset });
            shell.setView('results', { announcement: __( 'Loading run history.', 'fotogenic-ai' ) });
            const response = await transport.getGlobalHistory({
                page,
                perPage,
                query: normalizedQuery,
                status: normalizedStatus,
            });
            if (destroyed || loadSequence !== globalHistoryLoadSequence) return false;
            if (!response.ok) {
                historyView.render({
                    error: __( 'Run history is unavailable.', 'fotogenic-ai' ),
                    runs: [],
                    page,
                    perPage,
                    query: normalizedQuery,
                    status: normalizedStatus,
                }, {
                    back: globalHistoryReturn?.callback,
                    backLabel: globalHistoryReturn?.label,
                    filter: (criteria) => loadGlobalHistory(1, { preserveReturn: true, ...criteria }),
                });
                return false;
            }
            const model = normalizeGlobalHistoryPayload(response.data, limits);
            historyView.render(model, {
                back: globalHistoryReturn?.callback,
                backLabel: globalHistoryReturn?.label,
                filter: (criteria) => loadGlobalHistory(1, { preserveReturn: true, ...criteria }),
                page: (criteria) => loadGlobalHistory(criteria.page, { preserveReturn: true, ...criteria }),
                pageSize: (criteria) => loadGlobalHistory(1, { preserveReturn: true, ...criteria }),
                openRun: (run) => openGlobalHistoryRun(run, model.page, model.perPage, model.query, model.status),
            }, { focus: true });
            return true;
        };

		const openGlobalHistoryRunById = async (runId) => {
			const exactId = vm.cleanText(runId, 64).toLowerCase();
			if (!exactId || typeof transport.getGlobalHistory !== 'function') return false;
			const response = await transport.getGlobalHistory({ page: 1, perPage: 12, query: exactId, status: 'all' });
			if (destroyed || !response.ok) return false;
			const model = normalizeGlobalHistoryPayload(response.data, limits);
			const exact = model.runs.find((run) => [
				run.runId,
				run.requestId,
				run.resumeIdentity?.runId,
				run.resumeIdentity?.requestId,
				run.resumeIdentity?.runUuid,
				run.resumeIdentity?.queueUuid,
			].some((value) => vm.cleanText(value, 64).toLowerCase() === exactId));
			if (!exact) return loadGlobalHistory(1, { reset: true, query: exactId, status: 'all', perPage: 12 });
			return openGlobalHistoryRun(exact, model.page, model.perPage, model.query, model.status);
		};

        const buildResultHandlers = (response, actionIdentity = identity) => {
            const handlers = {};
            const bulk = actionIdentity?.scope === 'bulk';
            if (!bulk) {
                handlers.createAnother = () => {
					const route = routeFromIdentity(actionIdentity);
					if (!route || onCreateAnother(route) === false) throw new Error('unsupported_route');
                    clearIdentity();
                };
                handlers.openHistory = () => loadGlobalHistory(1, { reset: true });
            }
            if (response.finalizationPending === true) {
                handlers.checkStatus = () => checkStatus();
            }
            if (bulk && (!UUID_PATTERN.test(actionIdentity.bulkRunUuid || '') || !vm.positiveInteger(actionIdentity.bulkItemId))) return handlers;
            ['apply_featured', 'apply_gallery', 'apply_both', 'add_selected_to_gallery', 'add_all_to_gallery'].forEach((action) => {
                if (response.availableActions?.includes(action)) handlers[action] = (payload) => resultAction(action, payload, actionIdentity);
            });
            handlers.delete_attachment = async (payload) => {
                const attachmentId = vm.positiveInteger(payload?.attachmentId);
                if (!attachmentId) throw new Error('missing_attachment');
                const result = await transport.removeResult(actionIdentity, attachmentId);
                if (!result.ok) throw new Error('failed');
                if (result.data?.status !== 'removed' || typeof result.data?.changed !== 'boolean') throw new Error('invalid_remove_response');
                return {
                    status: 'removed',
                    changed: result.data.changed,
                    removedAttachmentId: attachmentId,
                };
            };
            return handlers;
        };

		const renderBulkSummary = (model) => {
			if (!identity || !['bulk', 'store_queue'].includes(identity.scope) || !isRecord(model) || !Array.isArray(model.items)) return false;
			const itemByKey = new Map(model.items.map((item) => [item.key, item]));
			const groups = buildBulkSummaryGroups(model, getSource);
			const resultHandlers = {
				back() {
					showBulkProgress(paginateBulkProgress(model, bulkPage));
				},
				openHistory: () => loadGlobalHistory(1, { reset: true }),
				createAnother() {
					const route = routeFromIdentity(identity);
					if (!route || onCreateAnother(route) === false) throw new Error('unsupported_route');
					clearIdentity();
				},
			};
			['apply_featured', 'apply_gallery', 'apply_both', 'add_selected_to_gallery', 'add_all_to_gallery'].forEach((action) => {
				if (!model.items.some((item) => item.result?.availableActions.includes(action))) return;
				resultHandlers[action] = (payload) => {
					const item = itemByKey.get(payload?.groupKey);
					if (!item?.result?.identity || !item.result.availableActions.includes(action)) throw new Error('unsupported');
					return resultAction(action, payload, item.result.identity);
				};
			});
			resultHandlers.delete_attachment = async (payload) => {
				const item = itemByKey.get(payload?.groupKey);
				const attachmentId = vm.positiveInteger(payload?.attachmentId);
				if (!item?.result?.identity || !attachmentId) throw new Error('missing_attachment');
				const result = await transport.removeResult(item.result.identity, attachmentId);
				if (!result.ok) throw new Error('failed');
				if (result.data?.status !== 'removed' || typeof result.data?.changed !== 'boolean') throw new Error('invalid_remove_response');
				item.result.attachments = item.result.attachments.filter((attachment) => (
					vm.positiveInteger(attachment.attachmentId) !== attachmentId
				));
				if (!item.result.attachments.length) {
					item.result.status = 'removed';
					item.result.availableActions = [];
				}
				return {
					status: 'removed',
					changed: result.data.changed,
					removedAttachmentId: attachmentId,
				};
			};
			resultsView.render({
				...identity,
				status: model.counts.failed > 0 ? 'partial' : 'completed',
				message: model.counts.failed > 0
					? __( 'Available saved results are shown. Items that need attention remain exact and recoverable.', 'fotogenic-ai' )
					: __( 'Every completed item is represented by its exact saved Media Library attachments.', 'fotogenic-ai' ),
				resultKey: `${identity.scope}:${identity.runUuid || identity.queueUuid}:${model.status}:${model.items.map((item) => `${item.itemId}:${item.status}`).join(',')}`,
				groups,
				totalItems: model.totalItems,
			}, resultHandlers);
			currentResultsReturn = () => renderBulkSummary(model);
			lastBulkProgress = model;
			latestBulkProgress = model;
			shell.setView('results', { announcement: model.counts.failed > 0 ? __( 'Partial Bulk results.', 'fotogenic-ai' ) : __( 'Bulk results.', 'fotogenic-ai' ) });
			return true;
		};

		const openGlobalHistory = () => loadGlobalHistory(1, { reset: true });

        const renderResults = (response, { remember = true, back } = {}) => {
            if (!identity) return;
            const displayIdentity = isRecord(response.identity) ? response.identity : identity;
            const selectedSource = getSource(displayIdentity.subjectId);
            const serverSource = isRecord(response.raw?.source) ? response.raw.source : null;
            const resultModel = {
                ...displayIdentity,
                status: ['partial', 'failed', 'removed'].includes(response.status) ? response.status : 'completed',
                message: response.message,
                resultKey: displayIdentity.runId || displayIdentity.requestId,
                groups: Array.isArray(response.raw?.groups) ? response.raw.groups : undefined,
                attachments: response.attachments,
                availableActions: response.availableActions,
				unappliedActions: Array.isArray(response.raw?.unappliedActions) ? response.raw.unappliedActions : [],
					appliedAction: vm.cleanText(response.raw?.appliedAction, 64).toLowerCase(),
					appliedAttachmentId: vm.positiveInteger(response.raw?.appliedAttachmentId),
					appliedAttachmentIds: Array.isArray(response.raw?.appliedAttachmentIds) ? response.raw.appliedAttachmentIds : [],
				deliveryPending: response.raw?.deliveryPending === true,
				deliveryFailed: response.raw?.deliveryFailed === true,
				deliveryRetryAvailable: response.raw?.deliveryRetryAvailable === true,
                source: serverSource || (selectedSource?.imageUrl ? {
                    attachmentId: selectedSource.attachmentId || displayIdentity.subjectId,
                    fullUrl: selectedSource.imageUrl,
                    thumbUrl: selectedSource.imageUrl,
                    label: selectedSource.label,
                } : null),
				sources: Array.isArray(response.raw?.sources) ? response.raw.sources : [],
				sourceMissing: response.raw?.sourceMissing === true || response.raw?.source?.missing === true,
				currentProduct: isRecord(response.raw?.currentProduct) ? response.raw.currentProduct : null,
				currentProductMissing: response.raw?.currentProductMissing === true || response.raw?.currentProduct?.missing === true,
					targetIdentity: response.raw?.targetIdentity || displayIdentity.targetIdentity,
					targetLinks: isRecord(response.raw?.targetLinks) ? response.raw.targetLinks : null,
					quality: vm.normalizeOutputQuality(response.raw?.quality, displayIdentity.workflow),
					deliveryLabel: vm.cleanText(response.raw?.deliveryLabel, 120),
					totalItems: 1,
            };
            if (remember) {
                persist({ status: resultModel.status });
                lastResults = response;
            }
            lastResultHandlers = buildResultHandlers(response, displayIdentity);
            if (typeof back === 'function') lastResultHandlers.back = back;
            resultsView.render(resultModel, lastResultHandlers);
            currentResultsReturn = () => renderResults(response, { remember: false, back });
            shell.setView('results', { announcement: resultModel.status === 'partial' ? __( 'Partial results.', 'fotogenic-ai' ) : __( 'Generation results.', 'fotogenic-ai' ) });
        };

        const schedulePoll = () => {
            clearPoll();
			const delay = pollDelayMs(pollAttempt, identity?.scope);
			pollAttempt += 1;
            pollTimer = schedule(() => {
                pollTimer = null;
                if (identity?.scope === 'store_queue') {
					void loadStoreQueueProgress(bulkPage);
				} else if (identity?.scope === 'bulk') {
                    void loadBulkProgress(bulkPage);
                } else {
                    void poll();
                }
            }, delay);
        };

        const acceptResponse = (raw) => {
            if (!identity) return null;
            const response = normalizeServerResponse(raw, identity, limits);
            if (!response) {
                persist({ status: 'uncertain' });
                showRecovery('uncertain', __( 'The server response could not be matched to this request.', 'fotogenic-ai' ), 'status_unconfirmed');
                return null;
            }
            persist({
				status: ['partial', 'completed', 'removed'].includes(response.status)
					? response.status
					: (['queued', 'starting', 'processing', 'finalizing', 'saving'].includes(response.status) ? response.status : 'processing'),
                runId: response.runId,
                jobIds: response.jobIds,
                expectedOutputCount: response.expectedOutputCount,
            });
			if (
				singleCreditsRefreshEnabled
				&& !singleAcceptedCreditsRefreshed
				&& identity?.scope === 'single'
				&& response.jobIds.length
			) {
				singleAcceptedCreditsRefreshed = true;
				requestCreditsRefresh('accepted_start');
			}
			refreshCreditsForSingleResponse(response);
            if (response.finalizationPending === true) {
				persist({ status: 'finalizing' });
				showProgress({ ...response, status: 'finalizing' });
				schedulePoll();
                return response;
            }
            if (response.status === 'removed') {
                persist({ status: 'removed' });
                renderResults(response);
                return response;
            }
            if (TERMINAL_STATUSES.has(response.status) && response.attachments.length) {
                const resultResponse = {
                    ...response,
                    status: ['completed', 'partial'].includes(response.status) ? response.status : 'partial',
                };
                persist({ status: response.status === 'stopped' ? 'stopped' : resultResponse.status });
				notifyRunLifecycle(response.status === 'stopped' ? 'stopped' : resultResponse.status);
                showProgress(response, { openSummary: () => renderResults(resultResponse) });
                return response;
            }
            if (['completed', 'partial'].includes(response.status)) {
                persist({ status: 'uncertain' });
                showRecovery(
                    'finalization_delay',
                    response.message || __( 'Generation finished, but saved Media Library results are not confirmed yet.', 'fotogenic-ai' ),
                    response.errorCode
                );
                return response;
            }
            if (TERMINAL_STATUSES.has(response.status)) {
                const terminalStatus = response.status === 'stopped' ? 'stopped' : 'failed';
                const resultResponse = {
                    ...response,
                    status: 'failed',
                    message: response.message || __( 'No generated attachment was saved. The exact source remains available for review.', 'fotogenic-ai' ),
                };
                persist({ status: terminalStatus });
				notifyRunLifecycle(terminalStatus);
                showProgress({ ...response, status: terminalStatus }, { openSummary: () => renderResults(resultResponse) });
                return response;
            }
            if (response.jobIds.length) {
                showProgress(response);
                schedulePoll();
                return response;
            }
            persist({ status: 'uncertain' });
            showRecovery('uncertain', response.message || __( 'The generation identity is saved, but its current status is not confirmed.', 'fotogenic-ai' ), response.errorCode);
            return response;
        };

        const poll = async () => {
            if (!identity || pollPending || destroyed) return;
            pollPending = true;
            const response = await transport.pollRun(identity);
            pollPending = false;
            if (destroyed || !identity) return;
            if (!response.ok) {
                persist({ status: 'uncertain' });
                showRecovery('finalization_delay', __( 'The current run status could not be confirmed. Check this same request again.', 'fotogenic-ai' ), response.code);
                return;
            }
            acceptResponse(response.data);
        };

        const reconcile = async () => {
            if (!identity || pollPending || destroyed) return;
            pollPending = true;
            const response = await transport.getActiveRun(identity);
            pollPending = false;
            if (destroyed || !identity) return;
            if (!response.ok) {
                persist({ status: 'uncertain' });
                showRecovery('uncertain', __( 'The saved request could not be reconciled. Check its status again.', 'fotogenic-ai' ), response.code);
                return;
            }
            const normalized = normalizeServerResponse(response.data, identity, limits);
            if (!normalized || (!normalized.hasActive && !normalized.status && !normalized.attachments.length)) {
                persist({ status: 'uncertain' });
                showRecovery('uncertain', __( 'No confirmed status is available for this saved request yet.', 'fotogenic-ai' ), 'status_unconfirmed');
                return;
            }
            acceptResponse(response.data);
        };

        const reconcileMissingBulk = async () => {
            const active = await transport.getActiveBulk();
            if (destroyed || !identity || identity.scope !== 'bulk') return false;
            const normalized = active.ok ? normalizeBulkActive(active.data, identity) : null;
            if (!normalized) {
                persist({ status: 'uncertain' });
                showRecovery('uncertain', __( 'The saved Bulk identity could not be matched to an authoritative active run.', 'fotogenic-ai' ), active.code || 'status_unconfirmed');
                return false;
            }
            persist({ status: normalized.status === 'paused' ? 'paused' : 'uncertain' });
            showRecovery(
                'uncertain',
                normalized.active
                    ? __( 'The Bulk run exists, but its queue status is not available yet. Check this same run again.', 'fotogenic-ai' )
                    : __( 'No active queue is reported for this saved Bulk identity. Keep this identity and check its status again.', 'fotogenic-ai' ),
                'status_unconfirmed'
            );
            return false;
        };

		const loadBulkProgress = async (page = bulkPage) => {
			if (!identity || identity.scope !== 'bulk' || pollPending || destroyed) return false;
			const nextPage = vm.positiveInteger(page, 1, 1000);
			const requestSequence = ++bulkProgressSequence;
			pollPending = true;
			const response = await transport.getBulkProgress({
				runUuid: identity.runUuid,
			});
			if (requestSequence !== bulkProgressSequence) return false;
			pollPending = false;
			if (destroyed || !identity || identity.scope !== 'bulk') return false;
            if (!response.ok) {
                if (response.status === 404) return reconcileMissingBulk();
                persist({ status: 'uncertain' });
                showRecovery('uncertain', __( 'The Bulk queue status could not be confirmed. Check this same run again.', 'fotogenic-ai' ), response.code);
                return false;
            }
            const raw = response.data;
            const rawItems = Array.isArray(raw?.items) ? raw.items : [];
			const completeModel = normalizeBulkProgress(response.data, identity, {}, limits);
			const model = paginateBulkProgress(completeModel, nextPage);
			if (!model || rawItems.length !== completeModel.items.length) {
                persist({ status: 'uncertain' });
                showRecovery('uncertain', __( 'The Bulk queue response could not be matched to this saved run.', 'fotogenic-ai' ), 'status_unconfirmed');
                return false;
			}
			latestBulkProgress = completeModel;
            bulkPage = nextPage;
			refreshCreditsForBulkProgress(completeModel);
            persist({ status: model.status });
			if (['completed', 'partial', 'failed', 'stopped'].includes(model.status)) notifyRunLifecycle(model.status);
            if (['completed', 'partial', 'failed', 'stopped'].includes(model.status)) {
                showBulkProgress(model, { summaryModel: completeModel });
            } else {
                showBulkProgress(model);
            }
            if (BULK_ACTIVE_STATUSES.has(model.serverStatus) || (model.serverStatus === 'paused' && model.inFlight > 0)) {
                schedulePoll();
            }
            return true;
        };

		const loadStoreQueueProgress = async (page = bulkPage) => {
			if (!identity || identity.scope !== 'store_queue' || pollPending || destroyed) return false;
			const nextPage = vm.positiveInteger(page, 1, 100000);
			const requestSequence = ++bulkProgressSequence;
			pollPending = true;
			const response = await transport.getStoreQueueProgress({
				queueUuid: identity.queueUuid,
				page: nextPage,
				perPage: STORE_QUEUE_PAGE_SIZE,
			});
			if (requestSequence !== bulkProgressSequence) return false;
			pollPending = false;
			if (destroyed || !identity || identity.scope !== 'store_queue') return false;
			if (!response.ok) {
				persist({ status: 'uncertain' });
				showRecovery('uncertain', __( 'The Product queue status could not be confirmed. Check this same queue again.', 'fotogenic-ai' ), response.code);
				return false;
			}
			const model = normalizeStoreQueueProgress(response.data, identity, limits);
			if (!model) {
				persist({ status: 'uncertain' });
				showRecovery('uncertain', __( 'The Product queue response could not be matched to this saved queue.', 'fotogenic-ai' ), 'status_unconfirmed');
				return false;
			}
			latestBulkProgress = model;
			bulkPage = nextPage;
			refreshCreditsForBulkProgress(model);
			persist({
				status: model.status,
				revision: vm.positiveInteger(response.data?.queue?.revision, identity.revision, Number.MAX_SAFE_INTEGER),
			});
			if (['completed', 'partial', 'failed', 'stopped'].includes(model.status)) notifyRunLifecycle(model.status);
			if (['completed', 'partial', 'failed', 'stopped'].includes(model.status)) {
				showBulkProgress(model, { summaryModel: model.totalPages === 1 ? model : null });
			} else {
				showBulkProgress(model);
			}
			if (['preparing', 'reviewing', 'ready', 'running', 'stopping'].includes(model.serverStatus)
				|| (model.serverStatus === 'paused' && model.inFlight > 0)) schedulePoll();
			return true;
		};

        const controlBulkRun = async (action) => {
            if (!identity || identity.scope !== 'bulk' || !['pause', 'resume', 'stop'].includes(action)) throw new Error('unsupported');
			if (bulkControlPending) throw new Error('pending');
            const method = { pause: 'pauseBulk', resume: 'resumeBulk', stop: 'stopBulk' }[action];
			const previous = latestBulkProgress || lastBulkProgress;
			const projected = projectBulkControlModel(previous, action);
			bulkControlPending = true;
			clearPoll();
			bulkProgressSequence += 1;
			pollPending = false;
			if (projected) showBulkProgress(paginateBulkProgress(projected, bulkPage));
			try {
				const response = await transport[method](identity.runUuid);
				if (!response.ok) throw new Error('failed');
				const payload = response.data;
				const responseRunUuid = vm.cleanText(payload?.runUuid, 36).toLowerCase();
				if (responseRunUuid !== identity.runUuid) throw new Error('identity');
				bulkControlPending = false;
				await loadBulkProgress(bulkPage);
			} catch (error) {
				bulkControlPending = false;
				if (previous) {
					showBulkProgress(paginateBulkProgress(previous, bulkPage));
					if (BULK_ACTIVE_STATUSES.has(previous.serverStatus) || (previous.serverStatus === 'paused' && previous.inFlight > 0)) schedulePoll();
				}
				throw error;
			}
        };

		const controlStoreQueue = async (action) => {
			if (!identity || identity.scope !== 'store_queue' || !['pause', 'resume', 'stop'].includes(action)) throw new Error('unsupported');
			if (storeQueueControlPending) throw new Error('pending');
			const method = { pause: 'pauseStoreQueue', resume: 'resumeStoreQueue', stop: 'stopStoreQueue' }[action];
			const previous = latestBulkProgress || lastBulkProgress;
			const projected = projectBulkControlModel(previous, action);
			storeQueueControlPending = true;
			clearPoll();
			bulkProgressSequence += 1;
			pollPending = false;
			if (projected) showBulkProgress(projected);
			try {
				const response = await transport[method](identity.queueUuid);
				if (!response.ok || vm.cleanText(response.data?.queueUuid, 36).toLowerCase() !== identity.queueUuid) throw new Error('failed');
				storeQueueControlPending = false;
				await loadStoreQueueProgress(bulkPage);
			} catch (error) {
				storeQueueControlPending = false;
				if (previous) showBulkProgress(previous);
				throw error;
			}
		};

        const checkStatus = () => (
            identity?.scope === 'store_queue'
				? loadStoreQueueProgress(bulkPage)
				: identity?.scope === 'bulk'
                ? loadBulkProgress(bulkPage)
                : (identity?.jobIds?.length ? poll() : reconcile())
        );

        const startSingle = async ({ draft, exact, preflightCurrent, target } = {}) => {
            if (startPending || identity || !canStartSingle({ draft, exact, preflightCurrent }, limits)) return false;
			pollAttempt = 0;
            const requestId = vm.cleanText(uuidFactory(), 36).toLowerCase();
            const runItemId = vm.cleanText(uuidFactory(), 36).toLowerCase();
			const campaignGroupId = draft.workflow === 'campaign_set'
				? vm.cleanText(draft.sourcePolicy?.groups?.[0]?.id, 36).toLowerCase()
				: '';
            const envelope = buildStartEnvelope(draft, requestId, {
                runItemId,
                campaignGroupId,
                itemOrdinal: 1,
				sourceFingerprint: exact.sourceFingerprint,
				authority: exact.authority,
				target,
            });
            if (!envelope) {
                showRecovery('validation', __( 'A secure request identity could not be created. Return to Review and try again.', 'fotogenic-ai' ));
                return false;
            }
            identity = normalizeIdentity({
                version: RECORD_VERSION,
                workflow: draft.workflow,
                sourceType: draft.sourceType,
                scope: 'single',
                subjectId: envelope.subject.id,
                requestId,
                runItemId,
                campaignGroupId,
                itemOrdinal: 1,
                targetIdentity: envelope.subject,
                status: 'starting',
                runId: '',
				jobIds: [],
				expectedOutputCount: exact.totalOutputs,
				deliveryMode: deliveryModeFromDraft(draft),
            }, limits);
            if (!identity || !writeStoredIdentity(storage, identity, limits)) {
                identity = null;
                showRecovery('validation', __( 'The request identity could not be saved before generation. No generation was started.', 'fotogenic-ai' ));
                return false;
            }
			notifyRunLifecycle('started');
            startPending = true;
			singleCreditsRefreshEnabled = true;
			singleAcceptedCreditsRefreshed = false;
			singleTerminalCreditsRefreshed = false;
            showProgress({ status: 'starting', expectedOutputCount: identity.expectedOutputCount });
            const response = await transport.startSingle(envelope);
            startPending = false;
            if (destroyed || !identity) return true;
            if (!response.ok) {
                if (response.uncertain) {
                    persist({ status: 'uncertain' });
                    showRecovery('uncertain', __( 'The start response was not confirmed. Check this same request status; do not submit it again.', 'fotogenic-ai' ), response.code);
                } else {
					singleCreditsRefreshEnabled = false;
                    persist({ status: 'failed' });
					notifyRunLifecycle('failed');
                    showRecovery(
                        response.status === 402 ? 'insufficient_credits' : 'rejected_start',
                        response.status === 402 ? __( 'The current balance is not enough for this generation.', 'fotogenic-ai' ) : __( 'The request was rejected before a billable start was confirmed.', 'fotogenic-ai' ),
                        response.code
                    );
                }
                return true;
            }
            acceptResponse(response.data);
            return true;
        };

        const startBulk = async ({ draft, exact, preflightCurrent, snapshotFingerprint } = {}) => {
			if (startPending || identity || !canStartBulk({ draft, exact, preflightCurrent }, limits)) return false;
			pollAttempt = 0;
			const selectedCount = bulkItemCount(draft);
			const recoveringSavedRun = pendingBulkRecovery
				&& pendingBulkRecovery.workflow === draft.workflow
				&& pendingBulkRecovery.sourceType === draft.sourceType
				&& pendingBulkRecovery.selectedCount === selectedCount
				&& UUID_PATTERN.test(pendingBulkRecovery.runUuid);
			const runUuid = recoveringSavedRun
				? pendingBulkRecovery.runUuid
				: vm.cleanText(uuidFactory(), 36).toLowerCase();
			const envelope = buildBulkStartEnvelope(draft, runUuid, snapshotFingerprint, exact.authority, limits);
			const outputCounts = draft.workflow === 'campaign_set'
				? draft.sourcePolicy.groups.map((group) => Number(group.recipe?.count || 0))
				: Array(selectedCount).fill(draft.workflow === 'increase_resolution' ? 1 : Number(draft.recipe?.count || 0));
			const uniformOutputs = outputCounts.every((count) => count === outputCounts[0]) ? outputCounts[0] : 0;
			if (!envelope || outputCounts.reduce((total, count) => total + count, 0) !== Number(exact.totalOutputs)) {
				showRecovery('validation', __( 'A secure Bulk identity could not be created. Return to Review and check the exact output totals.', 'fotogenic-ai' ));
				return false;
            }
            identity = normalizeIdentity({
                version: RECORD_VERSION,
                workflow: draft.workflow,
                sourceType: draft.sourceType,
                scope: 'bulk',
                runUuid,
                status: 'starting',
                selectedCount,
				...(uniformOutputs ? { outputsPerItem: uniformOutputs } : {}),
				expectedOutputCount: exact.totalOutputs,
				deliveryMode: deliveryModeFromDraft(draft),
            }, limits);
            if (!identity || !writeStoredIdentity(storage, identity, limits)) {
                identity = null;
                showRecovery('validation', __( 'The Bulk run identity could not be saved before admission. No generation was started.', 'fotogenic-ai' ));
                return false;
            }
			notifyRunLifecycle('started');
            bulkPage = 1;
            startPending = true;
			const preparingItems = buildBulkPreparingItems({ draft, selectedCount, outputCounts });
            showBulkProgress({
                status: 'starting',
                serverStatus: 'starting',
                items: preparingItems,
                page: 1,
                totalPages: 1,
                totalItems: selectedCount,
                hasNext: false,
                counts: { total: selectedCount, completed: 0, failed: 0, processing: selectedCount },
                controls: { checkStatus: false, pause: false, resume: false, stop: false },
            });
            const response = await transport.startBulk(envelope);
            startPending = false;
            if (destroyed || !identity || identity.scope !== 'bulk') return true;
			if (!response.ok) {
				if (response.uncertain) {
                    persist({ status: 'uncertain' });
                    showRecovery('uncertain', __( 'The Bulk admission response was not confirmed. Check this same run status; do not submit it again.', 'fotogenic-ai' ), response.code);
				} else if (recoveringSavedRun) {
					persist({ status: 'paused' });
					await loadBulkProgress(1);
                } else {
                    persist({ status: 'failed' });
					notifyRunLifecycle('failed');
                    showRecovery(
                        response.status === 402 ? 'insufficient_credits' : 'rejected_start',
                        response.status === 402
                            ? __( 'The current balance is not enough for this Bulk run.', 'fotogenic-ai' )
                            : __( 'The Bulk request was rejected before a billable run was confirmed.', 'fotogenic-ai' ),
                        response.code
                    );
                }
                return true;
            }
            const payload = response.data;
            const responseRunUuid = vm.cleanText(payload?.runUuid, 36).toLowerCase();
            const responseWorkflow = vm.cleanText(payload?.workflow, 64).toLowerCase();
            const responseStatus = vm.cleanText(payload?.status, 32).toLowerCase();
			const responseSelectedCount = strictPositiveInteger(payload?.selectedCount, limits.maxRunItems);
            if (
                responseRunUuid !== identity.runUuid
                || responseWorkflow !== identity.workflow
                || responseSelectedCount !== identity.selectedCount
                || payload?.dispatchReady !== true
                || !BULK_SERVER_STATUSES.has(responseStatus)
            ) {
                persist({ status: 'uncertain' });
                showRecovery('uncertain', __( 'The Bulk admission response could not be matched to this saved run.', 'fotogenic-ai' ), 'status_unconfirmed');
                return true;
            }
			persist({
                status: responseStatus === 'paused'
                    ? 'paused'
                    : (['completed', 'stopped'].includes(responseStatus) ? responseStatus : 'processing'),
			});
			bulkCreditsRefreshEnabled = true;
			bulkAcceptedItemCount = 0;
			bulkTerminalCreditsRefreshed = false;
			pendingBulkRecovery = null;
			clearPendingBulkRecovery(storage);
			await loadBulkProgress(1);
            return true;
        };

		const startStoreQueue = async ({ draft, exact, allowPartialBalance = false } = {}) => {
			if (startPending || identity || exact?.storeQueue !== true || !isRecord(exact.authority)) return false;
			identity = normalizeIdentity({
				version: RECORD_VERSION,
				workflow: 'product_images',
				sourceType: 'product',
				scope: 'store_queue',
				queueUuid: exact.queueUuid,
				status: 'starting',
				selectedCount: exact.totalItems,
				expectedOutputCount: exact.totalOutputs,
				revision: exact.revision,
				deliveryMode: deliveryModeFromDraft(draft),
			}, limits);
			if (!identity || !writeStoredIdentity(storage, identity, limits)) {
				identity = null;
				showRecovery('validation', __( 'The Product queue identity could not be saved before admission. No generation was started.', 'fotogenic-ai' ));
				return false;
			}
			notifyRunLifecycle('started');
			bulkPage = 1;
			pollAttempt = 0;
			startPending = true;
			showBulkProgress({
				status: 'starting',
				serverStatus: 'ready',
				items: [],
				page: 1,
				totalPages: Math.max(1, Math.ceil(identity.selectedCount / STORE_QUEUE_PAGE_SIZE)),
				totalItems: identity.selectedCount,
				hasNext: identity.selectedCount > STORE_QUEUE_PAGE_SIZE,
				outputCounts: { total: identity.expectedOutputCount, completed: 0, failed: 0 },
				counts: { total: identity.selectedCount, completed: 0, failed: 0, processing: identity.selectedCount },
				controls: { checkStatus: false, pause: false, resume: false, stop: false },
			});
			const response = await transport.startStoreQueue({
				queueUuid: identity.queueUuid,
				authority: exact.authority,
				allowPartialBalance: allowPartialBalance === true,
			});
			startPending = false;
			if (destroyed || !identity || identity.scope !== 'store_queue') return true;
			if (!response.ok) {
				if (response.uncertain) {
					persist({ status: 'uncertain' });
					showRecovery('uncertain', __( 'The Product queue admission response was not confirmed. Check this same queue; do not submit it again.', 'fotogenic-ai' ), response.code);
				} else {
					persist({ status: 'failed' });
					notifyRunLifecycle('failed');
					showRecovery(
						response.status === 402 ? 'insufficient_credits' : 'rejected_start',
						response.message || __( 'The Product queue was rejected before a billable batch was admitted.', 'fotogenic-ai' ),
						response.code
					);
				}
				return true;
			}
			const payload = response.data;
			if (vm.cleanText(payload?.queueUuid, 36).toLowerCase() !== identity.queueUuid) {
				persist({ status: 'uncertain' });
				showRecovery('uncertain', __( 'The Product queue admission response could not be matched to this saved queue.', 'fotogenic-ai' ), 'status_unconfirmed');
				return true;
			}
			persist({
				status: vm.cleanText(payload?.status, 32).toLowerCase() === 'paused' ? 'paused' : 'processing',
				revision: vm.positiveInteger(payload?.revision, identity.revision, Number.MAX_SAFE_INTEGER),
			});
			bulkCreditsRefreshEnabled = true;
			bulkAcceptedItemCount = 0;
			bulkTerminalCreditsRefreshed = false;
			await loadStoreQueueProgress(1);
			return true;
		};

		const discoverBulkIdentity = async () => {
			if (typeof transport.getActiveBulk !== 'function') return null;
			const response = await transport.getActiveBulk({});
			if (!response.ok) return null;
			const payload = response.data;
			if (payload === null) return null;
			const recovered = normalizeBulkRecoveryIdentity(response.data, limits);
			if (!recovered || !writeStoredIdentity(storage, recovered, limits)) return null;
			return recovered;
		};

		const discoverStoreQueueIdentity = async () => {
			if (typeof transport.getActiveStoreQueue !== 'function') return null;
			const response = await transport.getActiveStoreQueue({});
			const queue = response.ok ? response.data?.queue : null;
			if (!queue || Number(queue.selectedCount) < 1 || Number(queue.expectedOutputCount) < 1) return null;
			const statusMap = { preparing: 'starting', reviewing: 'starting', ready: 'queued', running: 'processing', paused: 'paused', stopping: 'stopping' };
			const recovered = normalizeIdentity({
				version: 1,
				workflow: 'product_images',
				sourceType: 'product',
				scope: 'store_queue',
				queueUuid: queue.queueUuid,
				status: statusMap[vm.safeCode(queue.status)] || 'uncertain',
				selectedCount: queue.selectedCount,
				expectedOutputCount: queue.expectedOutputCount,
				revision: queue.revision,
			}, limits);
			if (!recovered || !writeStoredIdentity(storage, recovered, limits)) return null;
			return recovered;
		};

        const restore = async () => {
            identity = readStoredIdentity(storage, limits);
			if (!identity) identity = await discoverStoreQueueIdentity();
			if (!identity) identity = await discoverBulkIdentity();
            if (!identity) return false;
            if (identity.scope === 'store_queue') {
				bulkCreditsRefreshEnabled = ['starting', 'processing', 'paused', 'stopping', 'uncertain'].includes(identity.status);
				showBulkProgress({
					status: identity.status,
					serverStatus: identity.status === 'paused' ? 'paused' : 'running',
					items: [],
					page: 1,
					totalPages: Math.max(1, Math.ceil(identity.selectedCount / STORE_QUEUE_PAGE_SIZE)),
					totalItems: identity.selectedCount,
					hasNext: identity.selectedCount > STORE_QUEUE_PAGE_SIZE,
					outputCounts: { total: identity.expectedOutputCount, completed: 0, failed: 0 },
					counts: { total: identity.selectedCount, completed: 0, failed: 0, processing: identity.selectedCount },
					controls: { checkStatus: true, pause: false, resume: false, stop: false },
				});
				await loadStoreQueueProgress(1);
			} else if (identity.scope === 'bulk') {
				bulkCreditsRefreshEnabled = ['starting', 'processing', 'paused', 'stopping', 'uncertain'].includes(identity.status);
				bulkAcceptedItemCount = 0;
				bulkTerminalCreditsRefreshed = false;
				const preparingOutputs = Array(identity.selectedCount).fill(identity.outputsPerItem || 0);
				showBulkProgress({
                    status: identity.status,
                    serverStatus: identity.status === 'paused' ? 'paused' : 'starting',
					items: buildBulkPreparingItems({ selectedCount: identity.selectedCount, outputCounts: preparingOutputs }),
                    page: 1,
                    totalPages: 1,
                    totalItems: identity.selectedCount,
                    hasNext: false,
                    counts: { total: identity.selectedCount, completed: 0, failed: 0, processing: identity.selectedCount },
                    controls: { checkStatus: true, pause: false, resume: false, stop: false },
                });
                await loadBulkProgress(1);
            } else {
				singleCreditsRefreshEnabled = ['starting', 'processing', 'finalizing', 'saving', 'uncertain', 'completed', 'partial', 'failed', 'stopped'].includes(identity.status);
				singleAcceptedCreditsRefreshed = identity.jobIds.length > 0;
				singleTerminalCreditsRefreshed = false;
                showProgress({
                    status: identity.status === 'removed' ? 'loading' : identity.status,
                    expectedOutputCount: identity.expectedOutputCount,
                });
                if (identity.status === 'removed' && identity.jobIds.length) {
                    await poll();
                } else {
                    await reconcile();
                }
            }
            return true;
        };

        return Object.freeze({
            startSingle,
            startBulk,
			startStoreQueue,
            restore,
            checkStatus,
			openGlobalHistory,
			openGlobalHistoryRunById,
            getIdentity: () => identity ? {
                ...identity,
                ...(Array.isArray(identity.jobIds) ? { jobIds: identity.jobIds.slice() } : {}),
            } : null,
            hasStoredRun: () => Boolean(identity),
			hasBlockingRun: () => getNavigationState().blocking,
			canOpenSummary: () => getNavigationState().summaryAvailable,
			openSummary,
			leaveTerminalRun,
            clear: clearIdentity,
            destroy() {
                destroyed = true;
                clearPoll();
                progressView.destroy();
                bulkView.destroy();
                resultsView.destroy();
                historyView.destroy();
            },
        });
    };

    Studio.runController = Object.freeze({
        STORAGE_KEY,
        createRunController,
        normalizeOperationalLimits,
		pollDelayMs,
        readStoredIdentity,
        normalizeIdentity,
        normalizeServerResponse,
        normalizeGlobalHistoryPayload,
        historyBackLabelForView,
        normalizeBulkActive,
		normalizeBulkRecoveryIdentity,
        normalizeBulkProgress,
		normalizeStoreQueueProgress,
		paginateBulkProgress,
		buildBulkPreparingItems,
		projectBulkControlModel,
		buildBulkSummaryGroups,
        exactPreflightIsCurrent,
        canStartSingle,
        canStartBulk,
        plannedOutputCount,
        normalizePendingBulkRecovery,
        readPendingBulkRecovery,
        writePendingBulkRecovery,
        clearPendingBulkRecovery,
        buildStartEnvelope,
        buildBulkStartEnvelope,
    });
})();
