import classNames from 'classnames';
import css from 'styled-jsx/css';

import type { WithSpacingProps } from '~/src/lib/hocs/withSpacing';
import type { ReactNode } from 'react';
import type { TextProps } from '../Text';

import locales from '~/locales/fragments/inputLabel';
import useTheme from '~/src/hooks/useTheme';
import withSpacing from '~/src/lib/hocs/withSpacing';
import { useI18nStatic } from '~/src/lib/i18n';
import prettyWrap from '~/src/lib/utils/prettyWrap';
import Box from '../Box';
import Text from '../Text';

export interface InputLabelProps extends WithSpacingProps {
  value?: ReactNode;
  description?: ReactNode;
  textCentered?: boolean;
  renderAfter?: () => ReactNode;
  isOptional?: boolean;
  tag?: 'div';
  children: ReactNode;
}

export const INPUT_LABEL_FONT_SIZE = '1.35rem';

const descriptionStyle = css.resolve`
  .withLinkStyling :global(a),
  .withLinkStyling :global(button) {
    display: inline-block;
    color: #888;
    border-bottom: dotted 1px #666;
  }

  .withLinkStyling :global(a):hover,
  .withLinkStyling :global(button):hover {
    color: #fff;
  }
`;

export const InputLabelValue = ({
  value,
  textCentered,
  renderAfter,
}: Pick<InputLabelProps, 'value' | 'textCentered' | 'renderAfter'> & {
  value: ReactNode;
  withLinkStyling?: boolean;
}) => {
  const theme = useTheme();

  return (
    <Text
      flexRow
      className="title"
      isBold
      size={INPUT_LABEL_FONT_SIZE}
      color={theme.textColor70}
      letterSpacing={0.01}
      margin="0 0.1rem 0.8rem"
      centered={textCentered}
      style={{
        scrollMarginTop: '1.2rem',
      }}
    >
      {value}
      {renderAfter && <Box margin="0 0 0 auto">{renderAfter()}</Box>}
    </Text>
  );
};

export const InputLabelDescription = ({
  value,
  withLinkStyling = true,
  ...textProps
}: Omit<TextProps, 'children'> & {
  value: ReactNode;
  withLinkStyling?: boolean;
}) => {
  const theme = useTheme();

  return (
    <Text
      className={classNames(descriptionStyle.className, { withLinkStyling })}
      color={theme.textColor60}
      size={INPUT_LABEL_FONT_SIZE}
      lineHeight={1.3}
      letterSpacing={0.01}
      margin="0.7rem 0 0"
      {...textProps}
      style={{ overflowWrap: 'break-word', ...textProps.style }}
    >
      {prettyWrap(value)}
      {descriptionStyle.styles}
    </Text>
  );
};

const InputLabel = withSpacing<InputLabelProps>(
  ({
    style,
    className,
    value,
    description,
    children,
    textCentered,
    tag,
    renderAfter,
    isOptional,
  }) => {
    const theme = useTheme();
    const Tag = tag ?? 'label';
    const { t } = useI18nStatic<'inputLabel'>(locales);

    if (isOptional) {
      value = (
        <>
          {value}{' '}
          <Text
            color={theme.textColor40}
            weight="regular"
            margin="0 0 0 0.5rem"
          >
            {`݀• ${t('optional')}`}
          </Text>
        </>
      );
    }

    return (
      <Tag style={{ display: 'block', ...style }} className={className}>
        {value && (
          <InputLabelValue
            value={value}
            textCentered={textCentered}
            renderAfter={renderAfter}
          />
        )}
        {children}
        {description && (
          <InputLabelDescription centered={textCentered} value={description} />
        )}
        <style jsx>{`
          :focus-within :global(.title) {
            color: #ddd !important;
          }
        `}</style>
      </Tag>
    );
  }
);

export default InputLabel;
