// @flow
import React, { useMemo } from 'react';
import type { ComponentType } from 'react';
import styled from 'styled-components';
import marked from 'marked';
import decamelize from 'decamelize';
import SyntaxHighlighter from 'react-syntax-highlighter';
import { tomorrowNight } from 'react-syntax-highlighter/dist/cjs/styles/hljs';

const getFlowPropsSource = (Subject: ComponentType<*>): string | void => {
  const propTypesFile = `${decamelize(
    Subject.displayName || '',
    '-',
  )}.proptypes.js`;

  // $FlowFixMe: flow can't analyze dynamic requires.
  const requireTypedefSource = require.context(
    '!!raw-loader!../src',
    true,
    /\.proptypes\.js$/,
  );

  const propTypesPath = requireTypedefSource
    .keys()
    .find((k) => k.includes(`/${propTypesFile}`));

  return propTypesPath
    ? requireTypedefSource(propTypesPath)?.default
    : undefined;
};

export const PropDefinitions = (Subject?: ComponentType<*>) => () => {
  if (!Subject) return null;
  // Don't do this in storyshots mode.
  if (process.env.JEST_WORKER_ID != null) return null;

  const s = Subject;
  const propTypesSource = useMemo(() => getFlowPropsSource(s), []);
  if (propTypesSource != null) {
    return (
      <SyntaxHighlighter language="flow" style={tomorrowNight}>
        {propTypesSource}
      </SyntaxHighlighter>
    );
  }

  return (
    <p>
      Could not find proptypes file.
      <ul>
        <li>Are you following patchwork file naming conventions properly?</li>
        <li>
          Does your component have a <code>displayName</code> set?
        </li>
      </ul>
    </p>
  );
};

const NullComponent = () => null;

export const configDocs = (docs: string, Subject?: ComponentType<*>) => ({
  text: docs,
  source: true,
  propTables: Subject ? [Subject] : [],
  TableComponent: PropDefinitions(Subject),
  styles: {},
});
