import { createStore as K } from "zustand";
import { devtools as x } from "zustand/middleware";
import { immer as I } from "zustand/middleware/immer";
import { STEPPER_STORE_ID as A } from "../../constants.js";
import { findStepIndexByKey as D } from "../../helpers/findStepIndexByKey/index.js";
import { evaluateVisibilityStepCondition as g } from "../../helpers/evaluateVisibilityStepCondition/index.js";
import { findAllVisibleStepsBefore as E } from "../../helpers/findAllVisibleStepsBefore/index.js";
import { findNextVisibleValidStep as b } from "../../helpers/findNextVisibleValidStep/index.js";
import { findPrevVisibleValidStep as $ } from "../../helpers/findPrevVisibleValidStep/index.js";
const h = (u, f) => {
  const { enabled: V = !1 } = f;
  return V && process.env.NODE_ENV === "development" ? x(u, f) : u;
}, j = (u, f = !1) => {
  const V = {
    currentStep: 0,
    stepValidationStatus: {},
    isValidating: !1,
    initialStepKeyApplied: !1,
    ...u
  };
  return K(
    h(
      /**
       * immer es un middleware de Zustand que permite trabajar con el estado de manera inmutable
       */
      I((n, y) => ({
        ...V,
        actions: {
          /**
           * init es la acción que se ejecuta al inicializar el store
           */
          init: (t, i = !1) => {
            n((a) => {
              if (a.steps = t, i || (a.stepValidationStatus = {}), !i) {
                const e = b(
                  -1,
                  // Comenzar desde -1 para encontrar el primer step visible
                  t,
                  {},
                  a.visibilityData
                );
                e !== 0 && e < t.length && (a.currentStep = e);
              }
            });
          },
          /**
           * setCurrentStep es la acción que se ejecuta para cambiar el step actual
           */
          setCurrentStep: (t) => {
            n((i) => {
              i.currentStep = t;
            });
          },
          /**
           * setStepValidationStatus es la acción que se ejecuta para establecer el estado de validación de un paso
           * @param stepIndex
           * @param isValid
           */
          setStepValidationStatus: (t, i) => {
            n((a) => {
              a.stepValidationStatus[t] = i;
            });
          },
          /**
           * prevStep - Función que retrocede al paso anterior válido del Stepper.
           * @param formData Datos del formulario actual para evaluar las conditions de los pasos
           * @param visibilityData Datos adicionales para evaluar las conditions (opcional, usa el del store si no se proporciona)
           */
          prevStep: (t = {}, i) => {
            const a = y(), { currentStep: e, steps: p } = a, S = i ?? a.visibilityData, c = $(
              e,
              p,
              t,
              S
            );
            c < 0 || n((r) => {
              r.currentStep = c;
            });
          },
          /**
           * nextStep - Función que valida el paso actual y avanza al siguiente paso del Stepper.
           * @param validateFn Función de validación externa que debe retornar una promesa que resuelve a true o false
           * @param formData Datos del formulario actual para evaluar las conditions de los pasos
           * @param visibilityData Datos adicionales para evaluar las conditions (opcional, usa el del store si no se proporciona)
           * @returns Promise<boolean> Retorna true si se avanzó al siguiente paso, false en caso contrario
           */
          nextStep: async (t, i = {}, a) => {
            const e = y(), { currentStep: p, steps: S } = e, c = a ?? e.visibilityData, r = await t(), m = b(
              p,
              S,
              i,
              c
            );
            return r ? (n((l) => {
              l.isValidating = !1, l.stepValidationStatus[p] = !0, l.currentStep = m;
            }), !0) : (n((l) => {
              l.isValidating = !1, l.stepValidationStatus[p] = !1;
            }), !1);
          },
          /**
           * resetStepper - Resetea el Stepper a su estado inicial
           */
          resetStepper: () => {
            n((t) => {
              t.stepValidationStatus = {}, t.isValidating = !1, t.initialStepKeyApplied = !1;
              const i = b(
                -1,
                // Comenzar desde -1 para encontrar el primer step visible
                t.steps,
                {},
                t.visibilityData
              );
              t.currentStep = i < t.steps.length ? i : 0;
            });
          },
          /**
           * applyInitialStepKey - Valida los steps anteriores y navega al step indicado por initialStepKey.
           * Si algún step anterior tiene errores, navega al primer step con errores.
           */
          applyInitialStepKey: async (t, i) => {
            const a = y(), { initialStepKey: e, steps: p, visibilityData: S, initialStepKeyApplied: c } = a;
            if (!e || e.trim() === "" || c)
              return;
            const r = D(e, p);
            if (r === -1) {
              const s = p.map((d) => d.key).join(", ");
              throw new Error(
                `Stepper: initialStepKey "${e}" no corresponde a ningún step. Keys disponibles: [${s}]`
              );
            }
            const m = p[r];
            if (!g(m, i, S)) {
              console.warn(
                `Stepper: initialStepKey "${e}" apunta a un step oculto. Iniciando en step 0.`
              ), n((s) => {
                s.initialStepKeyApplied = !0;
              });
              return;
            }
            if (r === 0) {
              n((s) => {
                s.initialStepKeyApplied = !0;
              });
              return;
            }
            const l = E(
              r,
              p,
              i,
              S
            );
            for (const { step: s, originalIndex: d } of l) {
              const v = s.validationFields || [];
              if (v.length === 0) {
                n((o) => {
                  o.stepValidationStatus[d] = !0;
                });
                continue;
              }
              if (!await t(v)) {
                n((o) => {
                  o.currentStep = d, o.stepValidationStatus[d] = !1, o.initialStepKeyApplied = !0;
                });
                return;
              }
              n((o) => {
                o.stepValidationStatus[d] = !0;
              });
            }
            n((s) => {
              s.currentStep = r, s.initialStepKeyApplied = !0;
            });
          }
        }
      })),
      {
        name: `${A}: ${u.storeId}`,
        enabled: f
      }
    )
  );
};
export {
  j as createStepperStore
};
