import {CSSObject, getTheme_v2, ThemeFontKey, ThemeFontSize} from '@sanity/ui/theme'

import {_responsive, rem} from '../helpers'
import {ThemeProps} from '../types'
import {ResponsiveFontStyleProps} from './types'

/**
 * A utility function getting responsive font styles.
 * @internal
 */
export function responsiveFont(
  fontKey: ThemeFontKey,
  props: ResponsiveFontStyleProps & ThemeProps,
): CSSObject[] {
  const {$size, $weight} = props
  const {font, media} = getTheme_v2(props.theme)
  const {family, sizes, weights} = font[fontKey]
  const fontWeight = ($weight && weights[$weight]) || weights.regular

  // @todo: make this configurable
  const defaultSize = sizes[2]

  const base: CSSObject = {
    'position': 'relative',
    'fontFamily': family,
    fontWeight,
    'padding': '1px 0',
    'margin': 0,

    '&:before': {
      content: '""',
      display: 'block',
      height: 0,
    },

    '&:after': {
      content: '""',
      display: 'block',
      height: 0,
    },

    '& > code, & > span': {
      display: 'block',
    },

    '&:not([hidden])': {
      display: 'block',
    },
  }

  // @TODO fix the real condition that is causing $size to be undefined sometimes
  if (!$size) {
    // @ts-expect-error: `warned` isn't typed, the underlying issue should be solved rather than typing it
    if (!responsiveFont.warned) {
      // eslint-disable-next-line no-console
      console.warn('No size specified for responsive font', {fontKey, $size, props, base})
      // @ts-expect-error: `warned` isn't typed, the underlying issue should be solved rather than typing it
      responsiveFont.warned = true
    }

    return [base]
  }

  const resp = _responsive(media, $size, (sizeIndex) => fontSize(sizes[sizeIndex] || defaultSize))

  return [base, ...resp]
}

export function fontSize(size: ThemeFontSize): CSSObject {
  const {ascenderHeight, descenderHeight, fontSize, iconSize, letterSpacing, lineHeight} = size
  const negHeight = ascenderHeight + descenderHeight
  const capHeight = lineHeight - negHeight
  const iconOffset = (capHeight - iconSize) / 2
  const customIconSize = Math.floor((fontSize * 1.125) / 2) * 2 + 1
  const customIconOffset = (capHeight - customIconSize) / 2

  return {
    'fontSize': rem(fontSize),
    'lineHeight': `calc(${lineHeight} / ${fontSize})`,
    'letterSpacing': rem(letterSpacing),
    'transform': `translateY(${rem(descenderHeight)})`,

    '&:before': {
      marginTop: `calc(${rem(0 - negHeight)} - 1px)`,
    },

    '&:after': {
      marginBottom: '-1px',
    },

    '& svg:not([data-sanity-icon])': {
      fontSize: `calc(${customIconSize} / 16 * 1rem)`,
      margin: rem(customIconOffset),
    },

    '& [data-sanity-icon]': {
      fontSize: `calc(${iconSize} / 16 * 1rem)`,
      margin: rem(iconOffset),
    },
  }
}
