"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/reasoning/programmerV1.ts
var programmerV1_exports = {};
__export(programmerV1_exports, {
  default: () => programmerV1_default
});
module.exports = __toCommonJS(programmerV1_exports);
var import_xstate = require("xstate");

// src/utils/uuid.ts
function uuidv4() {
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
    const r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
    return v.toString(16);
  });
}

// src/utils/StateMachines.ts
function getUniqueStateIds(inputArray, parent) {
  let statesArray = [...inputArray];
  if (statesArray[0]?.id.indexOf("|") >= 0) {
    return statesArray;
  }
  statesArray = statesArray.map((state, index, original) => {
    switch (state.id) {
      // these states only hve one occurance in all machines
      case "success":
      case "failure":
      case "pause":
        break;
      default:
        state.id = `${state.id}|${uuidv4()}`;
        if (parent) {
          state.parentId = parent.id;
        }
        break;
    }
    return state;
  });
  statesArray = statesArray.map((state, index) => {
    switch (state.id) {
      // these states only hve one occurance in all machines
      case "success":
      case "failure":
      case "pause":
        break;
      default:
        const futureStates = statesArray.slice(index + 1);
        state.transitions = state.transitions?.map((stateTranistion) => {
          const targetState = futureStates.find((futureState) => futureState.id.indexOf(stateTranistion.target) >= 0);
          stateTranistion.target = targetState ? targetState.id : stateTranistion.target;
          return stateTranistion;
        });
        if (state.onDone) {
          if (state.onDone instanceof Array) {
            state.onDone = state.onDone[0].target;
          }
          if (state.onDone instanceof Object) {
            state.onDone = state.onDone.target;
          }
          const targetState = futureStates.find((futureState) => futureState.id.indexOf(state.onDone) >= 0);
          state.onDone = targetState ? targetState.id : state.onDone;
        }
        if (state.states) {
          getUniqueStateIds(state.states, state);
        }
        break;
    }
    return state;
  });
  return statesArray;
}

// src/reasoning/programmerV1.ts
function getTransition(transition, task, transitionEvent) {
  const transitionConfig = {
    target: transition.target,
    actions: transition.actions || "saveResult"
  };
  const genericStateId = transition.target.split("|")[0];
  if (task.transitions?.get(transitionEvent)) {
    transitionConfig.cond = (context, event) => {
      return task.transitions.get(transitionEvent)(context, event);
    };
  } else if (task.transitions?.get(`${transitionEvent}|${genericStateId}`)) {
    transitionConfig.cond = (context, event) => {
      return task.transitions.get(`${transitionEvent}|${genericStateId}`)(context, event);
    };
  }
  return transitionConfig;
}
function generateStateConfig(state, functionCatalog, context, parallel = false, isNestedState = false) {
  if (parallel) {
    const stateConfig2 = {};
    stateConfig2.type = "parallel";
    stateConfig2.states = {};
    stateConfig2.id = state.id;
    stateConfig2.onDone = state.onDone;
    state.states?.forEach((state2) => {
      if (state2.id !== "success" && state2.id !== "failure" && state2.id !== "pause") {
        stateConfig2.states[state2.id] = {
          initial: "pending",
          id: state2.id,
          states: {
            pending: generateStateConfig(state2, functionCatalog, context, false, true),
            success: {
              type: "final"
            },
            failure: {
              type: "final"
            },
            pause: {
              type: "final"
            }
          }
        };
      }
    });
    return stateConfig2;
  }
  if (state.parentId) {
    context.childToParentStateMap[state.id] = state.parentId;
  }
  const functionName = state.id.split("|")?.[0];
  if (state.type === "final") {
    return {
      // for some reason the entry property is not defined when we return here
      // we have to manuall push the final state onto the stack so the next state is correctly returned
      // TODO: fix me
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-expect-error
      entry: (context2, event) => {
        console.log("Received Event:", event.type);
        context2.stack?.push(state.id);
      },
      type: state.type
    };
  }
  const retrievedFunction = functionCatalog.get(functionName);
  if (!retrievedFunction) {
    throw new Error(`function implementation for stateId: ${state.id} functionName: ${functionName} not found`);
  }
  const stateConfig = !isNestedState ? {
    entry: (context2, event) => {
      console.log("Received Event:", event.type);
      context2.stack?.push(state.id);
      console.log("Executing function:", functionName);
      retrievedFunction.implementation(context2, event, state.task);
    }
  } : {
    invoke: {
      src: async (context2, event) => {
        console.log("Received Event:", event.type);
        context2.stack?.push(state.id);
        console.log("Executing nested state function:", functionName);
        const result = await retrievedFunction.implementation(context2, event, state.task);
        console.log(`received result from nested state function: ${result}`);
        const returnValue = {
          stateId: state.id,
          [state.id]: {
            // we destructure to preserve other keys like result which holds values from user interaction
            ...context2[state.id],
            ...result
          }
        };
        return returnValue;
      },
      onDone: {
        target: "success",
        actions: "saveResult"
      },
      onError: {
        "target": "failure"
      }
    }
  };
  stateConfig.id = state.id;
  if (state.transitions && !isNestedState) {
    stateConfig.on = {
      pause: {
        target: "pause",
        actions: "saveResult"
      },
      success: {
        target: "success",
        actions: "saveResult"
      },
      failure: {
        target: "failure",
        actions: "saveResult"
      }
    };
    state.transitions.filter((transition) => transition.on === "CONTINUE").forEach((transition) => {
      stateConfig.on[transition.target] = {
        target: transition.target,
        actions: transition.actions || "saveResult"
      };
    });
    stateConfig.on.CONTINUE = state.transitions.filter((transition) => transition.on === "CONTINUE").map((transition) => getTransition(transition, retrievedFunction, "CONTINUE"));
    stateConfig.on.ERROR = state.transitions.filter((transition) => transition.on === "ERROR").map((transition) => getTransition(transition, retrievedFunction, "ERROR"));
  }
  stateConfig.on?.CONTINUE?.sort((a, b) => {
    const aHasCond = typeof a.cond !== "undefined";
    const bHasCond = typeof b.cond !== "undefined";
    if (aHasCond && !bHasCond) return -1;
    if (!aHasCond && bHasCond) return 1;
    return 0;
  });
  return stateConfig;
}
function generateStateMachineConfig(statesArray, functionCatalog) {
  const states = {
    // pause is a special state that allows functions to dispatch pause event that will not show up in the stack
    // this allows for the machine to progress through the states and pause when needed
    pause: { type: "final" }
  };
  const context = {
    requestId: uuidv4(),
    // Replace with actual uniqueId function
    status: 0,
    childToParentStateMap: {}
    // ... other context properties
  };
  const deduplicatedStates = getUniqueStateIds(statesArray);
  deduplicatedStates.forEach((state) => {
    states[state.id] = generateStateConfig(state, functionCatalog, context, state.type === "parallel");
  });
  return {
    id: uuidv4(),
    predictableActionArguments: true,
    initial: deduplicatedStates[0]?.id,
    context,
    states
  };
}
function program(statesArray, functionCatalog) {
  const states = generateStateMachineConfig(statesArray, functionCatalog);
  return (0, import_xstate.createMachine)(states, {
    actions: {
      saveResult: (0, import_xstate.assign)((context, event) => {
        const data = event.payload ?? event.data;
        return {
          ...context,
          ...data
        };
      })
    }
  });
}
var programmerV1_default = program;
