(function initFivaStateMachine(global) {
  "use strict";

  if (global.FIVA?.FivaStateMachine) return;

  const STATES = Object.freeze({
    IDLE: "IDLE",
    UPLOADING: "UPLOADING",
    PARSING: "PARSING",
    READY: "READY",
    RUNNING: "RUNNING",
    RETRYING: "RETRYING",
    PARTIAL_SUCCESS: "PARTIAL_SUCCESS",
    SUCCESS: "SUCCESS",
    FAILED: "FAILED",
    STOPPED: "STOPPED"
  });

  const STATUS_LABELS = Object.freeze({
    [STATES.IDLE]: "READY",
    [STATES.UPLOADING]: "UPLOADING",
    [STATES.PARSING]: "PARSING",
    [STATES.READY]: "READY",
    [STATES.RUNNING]: "FILLING FORM",
    [STATES.RETRYING]: "RETRYING",
    [STATES.PARTIAL_SUCCESS]: "PARTIAL SUCCESS",
    [STATES.SUCCESS]: "AUTOFILL COMPLETE",
    [STATES.FAILED]: "FAILED",
    [STATES.STOPPED]: "STOPPED"
  });

  const UPLOAD_LABELS = Object.freeze({
    [STATES.IDLE]: "Upload PDF or Passport",
    [STATES.UPLOADING]: "Uploading document...",
    [STATES.PARSING]: "Analyzing document...",
    [STATES.READY]: "Document analyzed successfully",
    [STATES.FAILED]: "Document parsing failed"
  });

  function normalizeState(state) {
    return Object.hasOwn(STATES, state) ? STATES[state] : Object.values(STATES).includes(state) ? state : STATES.IDLE;
  }

  function statusFor(state, explicitStatus = "") {
    return String(explicitStatus || STATUS_LABELS[normalizeState(state)] || STATUS_LABELS[STATES.IDLE]).trim();
  }

  function uploadLabelFor(state, fallback = "") {
    return String(UPLOAD_LABELS[normalizeState(state)] || fallback || UPLOAD_LABELS[STATES.IDLE]).trim();
  }

  function createRuntime(patch = {}) {
    const state = normalizeState(patch.state || STATES.IDLE);
    return {
      state,
      status: statusFor(state, patch.status),
      failedFields: Array.isArray(patch.failedFields) ? patch.failedFields.slice(0, 12) : [],
      active: state === STATES.RUNNING || state === STATES.RETRYING || state === STATES.PARSING || state === STATES.UPLOADING,
      updatedAt: patch.updatedAt || Date.now()
    };
  }

  function nextRuntime(current = {}, patch = {}) {
    return {
      ...createRuntime(current),
      ...patch,
      ...createRuntime({ ...current, ...patch }),
      updatedAt: Date.now()
    };
  }

  const FivaStateMachine = Object.freeze({
    STATES,
    STATUS_LABELS,
    UPLOAD_LABELS,
    createRuntime,
    nextRuntime,
    normalizeState,
    statusFor,
    uploadLabelFor
  });

  global.FIVA = Object.assign(global.FIVA || {}, { FivaStateMachine });

  if (typeof module !== "undefined" && module.exports) {
    module.exports = FivaStateMachine;
  }
})(typeof globalThis !== "undefined" ? globalThis : this);
