import { useRef, useEffect } from 'preact/hooks';
import { ExtensionHasNoMethodError } from './errors.mjs';
import { useApi } from './api.mjs';
import { useSubscription } from './subscription.mjs';

/**
 * Returns the `buyerJourney` details on buyer progression in checkout.
 */
function useBuyerJourney() {
  const api = useApi();
  return api.buyerJourney;
}

/**
 * Returns true if the buyer completed submitting their order.
 *
 * For example, when viewing the **Order status** page after submitting payment, the buyer will have completed their order.
 */
function useBuyerJourneyCompleted() {
  const api = useApi();
  return useSubscription(api.buyerJourney.completed);
}

/**
 * Installs a function for intercepting and preventing progress on checkout.
 *
 * To block checkout progress, you must set the [block_progress](https://shopify.dev/docs/api/checkout-ui-extensions/configuration#block-progress)
 * capability in your extension's configuration.
 *
 * If you do, then you're expected to inform the buyer why navigation was blocked,
 * either by passing validation errors to the checkout UI or rendering the errors in your extension.
 *
 * `useBuyerJourneyIntercept()` should be called at the top level of the extension,
 * not within an embedded or child component, to avoid errors should the child component get destroyed.
 *
 * It is good practice to show a warning in the checkout editor when the merchant has not given permission for your extension
 * to block checkout progress.
 */
function useBuyerJourneyIntercept(interceptor) {
  const api = useApi();
  const interceptorRef = useRef(interceptor);
  interceptorRef.current = interceptor;
  return useEffect(() => {
    const teardownPromise = api.buyerJourney.intercept(interceptorProps => interceptorRef.current(interceptorProps));
    return () => {
      teardownPromise.then(teardown => teardown()).catch(() => {});
    };
  }, [api.buyerJourney]);
}

/**
 * Returns all possible steps a buyer can take to complete the checkout. These steps may vary depending on the type of checkout or the shop's configuration.
 */
function useBuyerJourneySteps() {
  const api = useApi();
  if (!('buyerJourney' in api) || !api.buyerJourney) {
    throw new ExtensionHasNoMethodError('buyerJourney', api.extension.target);
  }
  return useSubscription(api.buyerJourney.steps);
}

/**
 * Returns the buyer journey step that the buyer is currently on.
 */
function useBuyerJourneyActiveStep() {
  const api = useApi();
  if (!('buyerJourney' in api) || !api.buyerJourney) {
    throw new ExtensionHasNoMethodError('buyerJourney', api.extension.target);
  }
  const steps = useSubscription(api.buyerJourney.steps);
  const activeStep = useSubscription(api.buyerJourney.activeStep);
  return activeStep ? steps.find(({
    handle
  }) => handle === activeStep.handle) : undefined;
}

export { useBuyerJourney, useBuyerJourneyActiveStep, useBuyerJourneyCompleted, useBuyerJourneyIntercept, useBuyerJourneySteps };
