<script lang="ts">
  import Screen from "./Screen.svelte";
  import type { CompleteWorkflowNavigateArgs } from "../../types/components/button";
  import type { ColorScheme } from "../../types/colors";
  import type { InitialInputSelections } from "../../stores/inputValidation";
  import type { OnComponentInteraction } from "../../types/paywall-component-interaction";
  import type { VariableDictionary } from "../../types/variables";
  import type { WalletButtonRender } from "../../types/wallet";
  import type { UIConfig } from "../../types/ui-config";
  import type { ReservedAttribute } from "../../types/components/input-text";
  import type { WorkflowNavData } from "../../types/workflow-nav";
  import type {
    WorkflowStepTriggerAction,
    WorkflowStep,
  } from "../../types/workflow";

  type TriggerActionValue = WorkflowStep["trigger_actions"][string];

  function isStepTriggerAction(
    a: TriggerActionValue,
  ): a is WorkflowStepTriggerAction {
    return (
      a.type === "step" &&
      typeof (a as WorkflowStepTriggerAction).step_id === "string"
    );
  }

  interface Props {
    workflow: WorkflowNavData;
    uiConfig: UIConfig;
    selectedLocale?: string;
    globalVariables?: VariableDictionary;
    variablesPerPackage?: Record<string, VariableDictionary>;
    maxContentWidth?: string;
    initialInputSelections?: InitialInputSelections;
    containerId?: string;
    walletButtonRender?: WalletButtonRender;
    safeAreaFallbackColor?: ColorScheme | null;
    onPurchaseClicked?: (
      packageId: string,
      actionId: string,
    ) => void | Promise<void>;
    onActionTriggered?: (actionId: string) => void;
    onInputChanged?: (
      fieldId: string,
      value: string,
      actionId?: string,
    ) => void;
    onReservedAttributeChanged?: (
      reservedAttribute: ReservedAttribute,
      value: string,
    ) => void;
    onCompleteWorkflowNavigate?: (
      args: CompleteWorkflowNavigateArgs,
    ) => void | Promise<void>;
    onNavigateToUrlClicked?: (url: string) => void;
    onRestorePurchasesClicked?: () => void;
    onVisitCustomerCenterClicked?: () => void;
    onComponentInteraction?: OnComponentInteraction;
    onClose?: () => void;
    onExitBack?: () => void;
  }

  const {
    workflow,
    uiConfig,
    selectedLocale,
    globalVariables,
    variablesPerPackage,
    maxContentWidth,
    initialInputSelections,
    containerId,
    walletButtonRender,
    safeAreaFallbackColor,
    onPurchaseClicked,
    onActionTriggered,
    onInputChanged,
    onReservedAttributeChanged,
    onCompleteWorkflowNavigate,
    onNavigateToUrlClicked,
    onRestorePurchasesClicked,
    onVisitCustomerCenterClicked,
    onComponentInteraction,
    onClose,
    onExitBack,
  }: Props = $props();

  // ── Nav stack ─────────────────────────────────────────────────────────────
  // Each entry pairs the screen ID (used to look up the page to render) with
  // the step ID (used to resolve trigger_actions on button press). The current
  // page is always the last entry; workflow actions push, navigate_back pops.
  //
  // We key the reset off workflow.initial_page_id (a stable string) rather
  // than workflow object identity, so hosts that recompute the prop object on
  // unrelated reactive updates don't accidentally snap the user back to the
  // first page mid-flow.
  interface NavEntry {
    pageId: string;
    stepId: string;
  }
  let navStack = $state<NavEntry[]>([]);
  let trackedInitialPageId = $state<string>();

  const current = $derived(
    navStack[navStack.length - 1] ?? {
      pageId: workflow.initial_page_id,
      stepId: workflow.initial_step_id,
    },
  );
  const currentScreen = $derived(workflow.pages[current.pageId]);

  $effect.pre(() => {
    if (trackedInitialPageId !== workflow.initial_page_id) {
      trackedInitialPageId = workflow.initial_page_id;
      navStack = [
        {
          pageId: workflow.initial_page_id,
          stepId: workflow.initial_step_id,
        },
      ];
    }
  });

  /**
   * Resolves a "workflow"-type button action and navigates to the next screen.
   *
   * Flow: component ID → step.triggers[].action_id → trigger_actions[action_id]
   *       → step_id → step.screen_id → push onto nav stack.
   */
  function handleActionTriggered(actionId: string) {
    const currentStep = workflow.steps[current.stepId];
    if (!currentStep) {
      console.warn(
        `[Workflow] onActionTriggered: no current step found for step_id "${current.stepId}"`,
      );
      return;
    }

    // Resolve the component ID to an action ID via the step's triggers array.
    const resolvedActionId = currentStep.triggers.find(
      (t) => t.component_id === actionId,
    )?.action_id;

    if (!resolvedActionId) {
      console.warn(
        `[Workflow] onActionTriggered: no trigger entry found for component "${actionId}" on step "${current.stepId}"`,
      );
      onActionTriggered?.(actionId);
      return;
    }

    const triggerAction = currentStep.trigger_actions[resolvedActionId];
    if (!triggerAction) {
      console.warn(
        `[Workflow] onActionTriggered: no trigger_action found for action_id "${resolvedActionId}" on step "${current.stepId}"`,
      );
      onActionTriggered?.(actionId);
      return;
    }

    if (!isStepTriggerAction(triggerAction)) {
      // Condition-based actions require a full workflow engine — fall back to
      // the host's onActionTriggered for anything we can't resolve client-side.
      console.warn(
        `[Workflow] onActionTriggered: trigger_action is not a simple step action, falling back to onActionTriggered`,
      );
      onActionTriggered?.(actionId);
      return;
    }

    const nextStep = workflow.steps[triggerAction.step_id];
    if (!nextStep) {
      console.warn(
        `[Workflow] onActionTriggered: step_id "${triggerAction.step_id}" not found in workflow steps`,
      );
      return;
    }

    const nextPageId = nextStep.screen_id;
    if (!nextPageId) {
      console.warn(
        `[Workflow] onActionTriggered: step "${triggerAction.step_id}" has no screen_id (logic/experiment step?)`,
      );
      return;
    }

    if (!workflow.pages[nextPageId]) {
      console.warn(
        `[Workflow] onActionTriggered: screen_id "${nextPageId}" not found in workflow pages`,
      );
      return;
    }

    navStack = [
      ...navStack,
      { pageId: nextPageId, stepId: triggerAction.step_id },
    ];
  }

  function handleBackClicked() {
    if (navStack.length > 1) {
      navStack = navStack.slice(0, -1);
    } else {
      // Already at root — bubble up to the host.
      onExitBack?.();
    }
  }
</script>

{#key current.pageId}
  <Screen
    paywallComponents={currentScreen}
    {uiConfig}
    {selectedLocale}
    {globalVariables}
    {variablesPerPackage}
    {maxContentWidth}
    {initialInputSelections}
    {containerId}
    {walletButtonRender}
    {safeAreaFallbackColor}
    {onPurchaseClicked}
    onActionTriggered={handleActionTriggered}
    {onInputChanged}
    {onReservedAttributeChanged}
    {onCompleteWorkflowNavigate}
    {onNavigateToUrlClicked}
    {onRestorePurchasesClicked}
    {onVisitCustomerCenterClicked}
    {onComponentInteraction}
    onBackClicked={handleBackClicked}
    {onClose}
  />
{/key}
