import {
  SectionType,
  StoryPageSection,
  TabSection,
} from '../../typings/story-section';
import { StoryConfig } from '../../typings/story-config';
import { Example, Tabs, IncludedComponent } from '../../typings/story';
import React from 'react';
import { width } from '../../ui/Tabs/core/constants/tab-prop-types';

const example = (props: { source: string; loading?: boolean }) => {
  return {
    type: SectionType.Example,
    title: 'Demo',
    source: props.source,
    compact: true,
    hideCodeEditor: true,
    loading: props.loading,
    wide: true,
  };
};

const examples = (
  examplesContent: Example[],
  examplesCode: Record<string, string>,
  examplesConfig: Record<string, any>,
) => {
  if (!examplesContent || !examplesContent.length) {
    return [];
  }

  return examplesContent
    .map((item, index) => ({
      type: SectionType.Example,
      key: index,
      title: item.title,
      text: item.description,
      source: examplesCode[item.example],
      compact: true,
      wide: item.wide,
      figmaLink: item.figmaLink,
      examplesPreviewWrapper: examplesConfig?.examplesPreviewWrapper,
    }))
    .filter(example => example.source);
};

const description = (props: {
  title?: string;
  description?: string;
  loading?: boolean;
  width?: string;
}) => ({
  type: SectionType.Description,
  text: props.description,
  title: props.title,
  loading: props.loading,
  width,
});

const importExample = (
  storyConfig: StoryConfig,
  props: { loading?: boolean },
) => ({
  title: 'Import',
  type: SectionType.ImportExample,
  source: storyConfig.exampleImport,
  loading: props.loading,
});

const demo = (props: { demo: React.ReactNode; loading?: boolean }) => {
  const { demo: Demo, loading } = props;

  if (!Demo) {
    return null;
  }
  return {
    title: 'Demo',
    type: SectionType.Demo,
    loading,
    component: Demo,
  };
};

const doDont = (props: { do: string[]; dont: string[]; loading?: boolean }) => {
  if (!props.do?.length && !props.dont?.length) {
    return null;
  }
  return {
    type: SectionType.DoDont,
    do: props.do && { list: props.do },
    dont: props.dont && { list: props.dont },
    loading: props.loading,
  };
};

const divider = () => ({ type: SectionType.Divider });
const title = (text: string) => ({ type: SectionType.Title, title: text });

const includedComponents = (props: IncludedComponent[]) => ({
  title: 'Included Components',
  type: SectionType.IncludedComponents,
  component: props,
});

const designTab = (props: StoryPageSection, storyConfig: StoryConfig) => {
  const { content } = props;
  const showCommonUseCaseExamples = props.content.commonUseCaseExamples?.length;
  const showIncludedComponents = props.content.includedComponents?.length;
  const showDeveloperExamples = props.content.developerExamples?.length;
  const showAccessibilityExamples = props.content.accessibilityExamples?.length;

  const examplesConfig = {
    examplesPreviewWrapper: storyConfig.story?.examplesPreviewWrapper,
  };

  return {
    title: 'Design',
    type: SectionType.Tab,
    sections: [
      typeof props.demo === 'string'
        ? example({ source: props.demo, loading: props.loading })
        : demo({ demo: props.demo, loading: props.loading }),
      description({
        title: content.title || 'Usage',
        description: content.description,
        loading: props.loading,
        width: '60%',
      }),
      doDont({ do: content.do, dont: content.dont, loading: props.loading }),
      importExample(storyConfig, { loading: props.loading }),
      showIncludedComponents && includedComponents(content.includedComponents),
      divider(),
      title('Variations'),
      ...examples(
        props.content.featureExamples,
        props.examples,
        examplesConfig,
      ),
      showDeveloperExamples && divider(),
      showDeveloperExamples && title('Developer examples'),
      ...examples(
        props.content.developerExamples,
        props.examples,
        examplesConfig,
      ),
      showAccessibilityExamples && divider(),
      showAccessibilityExamples && title('Accessibility considerations'),
      ...examples(
        props.content.accessibilityExamples,
        props.examples,
        examplesConfig,
      ),
      showCommonUseCaseExamples && divider(),
      showCommonUseCaseExamples && title('Common use cases'),
      ...examples(
        props.content.commonUseCaseExamples,
        props.examples,
        examplesConfig,
      ),
      divider(),
      title('Feedback'),
      description({ description: storyConfig.config.feedbackText }),
    ].filter(item => !!item),
  };
};

const apiTab = () => ({
  title: 'API',
  type: SectionType.Tab,
  sections: [
    {
      type: SectionType.Api,
    },
  ],
});

const testkitTab = () => ({
  title: 'Testkit',
  type: SectionType.Tab,
  sections: [
    {
      type: SectionType.Testkit,
    },
  ],
});

const playgroundTab = (props: StoryPageSection, storyConfig: StoryConfig) => ({
  title: 'Playground',
  type: SectionType.Tab,
  sections: [
    {
      type: SectionType.Playground,
    },
  ],
});

const tabs = (props: StoryPageSection, storyConfig: StoryConfig) => {
  const defaultTabs = {
    design: designTab(props, storyConfig),
    api: apiTab(),
    testkit: testkitTab(),
    playground: playgroundTab(props, storyConfig),
  };

  const defaultUserTabsValue = (defaultabs: Tabs) => [
    defaultabs.design,
    defaultabs.api,
    defaultabs.testkit,
  ];

  const { tabs: userTabs = defaultUserTabsValue } = props;
  return userTabs(defaultTabs)
    .filter(item => !(item.title === 'Testkit' && storyConfig?.config?.story?.testkit === false))
    .reduce((result, tab) => {
      if (!tab.title) {
        return result;
      }

    if (defaultTabs[tab.title.toLowerCase()]) {
      return [...result, defaultTabs[tab.title.toLowerCase()]];
    }

    const pluginSection = tab.node && {
      type: SectionType.Plugin,
      handler: () => tab.node,
    };

    return [
      ...result,
      {
        title: tab.title,
        type: SectionType.Tab,
        sections: [
          ...(tab.sections ? tab.sections : []),
          ...(tab.node ? [pluginSection] : []),
        ],
      },
    ];
  }, [] as TabSection[]);
};

export const storyPage = (
  props: StoryPageSection,
  storyConfig: StoryConfig,
) => [
  {
    type: SectionType.Header,
    sourceUrl: `${storyConfig.config.repoBaseURL}/${storyConfig.storyName}`,
    source: storyConfig.config.story?.source,
    loading: props.loading,
  },
  {
    type: SectionType.Tabs,
    tabs: tabs(props, storyConfig),
  },
];
