<script lang="ts">
  import Stack from "../stack/Stack.svelte";
  import { getInputValidationContext } from "../../stores/inputValidation";
  import { getLocalizationContext } from "../../stores/localization";
  import { getPaywallContext } from "../../stores/paywall";
  import { getSelectedStateContext } from "../../stores/selected";
  import type { ButtonProps } from "../../types/components/button";
  import type {
    ButtonInteractionData,
    PackageSelectionSheetInteractionData,
  } from "../../types/paywall-component-interaction";
  import { getActiveStateProps } from "../../utils/style-utils";
  import { readable } from "svelte/store";

  const props: ButtonProps = $props();
  type SheetAction = Extract<
    ButtonProps["action"],
    { type: "navigate_to"; destination: "sheet" }
  >;

  const selectedState = getSelectedStateContext();
  const { action } = $derived.by(() => {
    return {
      ...props,
      ...getActiveStateProps($selectedState, props.overrides),
    };
  });

  const {
    emitComponentInteraction,
    onButtonAction,
    hideBackButtons,
    selectedPackageId,
  } = getPaywallContext();
  const validationContext = getInputValidationContext();
  const { getLocalizedString } = getLocalizationContext();

  // Reactive store for input satisfaction (defaults to true if no validation context)
  const inputSatisfied = validationContext?.isSatisfied ?? readable(true);

  // Button is disabled when it's a workflow (continue) or complete_workflow action and inputs aren't satisfied
  const isDisabled = $derived(
    (action.type === "workflow" || action.type === "complete_workflow") &&
      !$inputSatisfied,
  );

  const getButtonInteractionData = (): ButtonInteractionData => {
    switch (action.type) {
      case "workflow":
        return {
          componentType: "button",
          componentName: props.name,
          componentValue: "workflow",
        };
      case "complete_workflow": {
        const url = getLocalizedString(action.url.url_lid);
        return {
          componentType: "button",
          componentName: props.name,
          componentValue: "navigate_to_url",
          ...(url ? { componentURL: url } : {}),
        };
      }
      case "navigate_back":
        return {
          componentType: "button",
          componentName: props.name,
          componentValue: "navigate_back",
        };
      case "close_workflow":
        return {
          componentType: "button",
          componentName: props.name,
          componentValue: "close_workflow",
        };
      case "restore_purchases":
        return {
          componentType: "button",
          componentName: props.name,
          componentValue: "restore_purchases",
        };
    }

    switch (action.destination) {
      case "customer_center":
        return {
          componentType: "button",
          componentName: props.name,
          componentValue: "navigate_to_customer_center",
        };
      case "screen_redirect":
        return {
          componentType: "button",
          componentName: props.name,
          componentValue: "screen_redirect",
        };
      case "privacy_policy":
      case "terms":
      case "url": {
        const url = getLocalizedString(action.url.url_lid);
        return {
          componentType: "button",
          componentName: props.name,
          componentValue:
            action.destination === "privacy_policy"
              ? "navigate_to_privacy_policy"
              : action.destination === "terms"
                ? "navigate_to_terms"
                : "navigate_to_url",
          ...(url ? { componentURL: url } : {}),
        };
      }
      case "sheet":
        // Unreachable: sheet open/close paths short-circuit in onclick above
        // and emit via getSheetOpenInteractionData() / Paywall.onButtonAction.
        // Kept to preserve switch exhaustiveness over Action["destination"].
        throw new Error(
          "Sheet actions must be handled by the sheet branches in onclick",
        );
      case "offer_code":
        return {
          componentType: "button",
          componentName: props.name,
          componentValue: "navigate_to_offer_code",
        };
      case "web_paywall_link":
        return {
          componentType: "button",
          componentName: props.name,
          componentValue: "navigate_to_web_paywall_link",
        };
    }
  };

  const getSheetOpenInteractionData = (
    sheetAction: SheetAction,
  ): PackageSelectionSheetInteractionData => ({
    componentType: "package_selection_sheet",
    componentName: sheetAction.sheet?.name ?? props.name,
    componentValue: "open",
    currentPackageId: $selectedPackageId,
  });

  const onclick = () => {
    if (isDisabled) return;
    // For "workflow" actions, pass the component's own id so Workflow.svelte
    // can look it up in the step's triggers array (component ID → action ID).
    const actionId = action.type === "workflow" ? props.id : undefined;
    if (action.type === "navigate_to" && action.destination === "sheet") {
      if (action.sheet != null) {
        emitComponentInteraction(getSheetOpenInteractionData(action));
      }

      onButtonAction(action, actionId);
      return;
    }

    emitComponentInteraction(getButtonInteractionData());
    onButtonAction(action, actionId);
  };

  const visible = $derived.by(() => {
    switch (action.type) {
      case "workflow":
        return true;
      case "complete_workflow":
        return true;
      case "restore_purchases":
        return false;
      case "navigate_back":
        return !hideBackButtons;
      case "close_workflow":
        return true;
      case "navigate_to":
        return action.destination !== "web_paywall_link";
      default:
        return true;
    }
  });

  const style = $derived(
    isDisabled
      ? { opacity: "0.4", "pointer-events": "none", cursor: "not-allowed" }
      : undefined,
  );
</script>

{#if visible}
  <Stack {...props.stack} {onclick} {style} testId={`button-${action.type}`} />
{/if}
