import { MINIMAL_VIEWPORTS } from '@storybook/addon-viewport';
import { StoryObj } from '@storybook/react';

export const viewports = {
  ...MINIMAL_VIEWPORTS,
  mobile3: {
    name: '400% Zoom',
    // 320x256 https://www.w3.org/WAI/WCAG21/Understanding/reflow.html
    styles: { height: '256px', width: '320px' },
    type: 'mobile',
  },
  desktop: {
    name: 'Desktop',
    styles: { height: '1024px', width: '1280px' },
    type: 'desktop',
  },
};

interface StoryConfig {
  /**
   * Creates variations of the component for the current story. Some
   * padding is applied to the variants for spacing.
   *
   * - `default` adds just the story itself with some padding.
   * - `light` adds a light theme variant.
   * - `dark` adds a dark theme variant.
   * - `rtl` adds a right-to-left writing mode variant.
   * - `mobile` sets the default viewport for the Story with mobile
   *   dimensions and uses those dimensions for snapshots.
   *
   * @default undefined
   */
  variants?: ('default' | 'light' | 'dark' | 'rtl' | 'mobile' | '400%')[];
}

const getViewportWidth = (viewport: (typeof viewports)[keyof typeof viewports]) => {
  if (viewport.styles && typeof viewport.styles === 'object') {
    return Number.parseInt(viewport.styles.width, 10);
  }
  throw new Error('Unknown viewport styles');
};

/**
 * The key to 'Large mobile' viewport {@link viewports.mobile2}
 */
const mobileViewportKey = 'mobile2';
// @ts-expect-error viewports has mobile2 property (comes from ...MINIMAL_VIEWPORTS)
const mobileViewportWidth = getViewportWidth(viewports.mobile2);

const zoom400perViewportKey = 'mobile3';
const zoom400perViewportWidth = getViewportWidth(viewports.mobile3);

/**
 * Utility function for creating variants of a CSFv3 story.
 */
export const storyConfig = <Args>(
  storyObject: StoryObj<Args>,
  { variants }: StoryConfig,
): StoryObj<Args> => {
  const isMobile = variants?.includes('mobile') || undefined;
  const is400Zoom = variants?.includes('400%') || undefined;

  return {
    ...storyObject,
    parameters: {
      ...storyObject.parameters,
      variants,
      chromatic: {
        ...storyObject.parameters?.chromatic,
        viewports: (isMobile && [mobileViewportWidth]) || (is400Zoom && [zoom400perViewportWidth]),
      },
      viewport: {
        ...storyObject.parameters?.viewport,
        /** Set defaultViewport if 'mobile' variant is used */
        defaultViewport: (isMobile && mobileViewportKey) || (is400Zoom && zoom400perViewportKey),
      },
    },
  };
};
