import React from 'react'
import PropTypes from 'prop-types'
import { View, StyleSheet, Platform } from 'react-native'
import { StackView } from '../StackView/StackView'
import { Typography } from '../Typography/Typography'
import { useCopy } from '../utils/useCopy'
import { dictionary } from './dictionary'
import { dictionaryContentShape } from './types'
import { variantProp } from '../utils/props/variantProp'

const MIN_SEGMENT_WIDTH = 2
const SEGMENT_WIDTH_TO_FONT_SIZE_RATIO = 0.8

// Width must be static per unit — do not derive from current number or label string length,
// as that causes the segment to resize on every tick (bouncing bug).
// DAYS_LABEL_WIDTH fits "Days" (EN, 4 chars); SECONDS_LABEL_WIDTH fits "Secondes" (FR, 8 chars),
// the longest label across all supported locales.
const DAYS_LABEL_WIDTH = 2.5
const SECONDS_LABEL_WIDTH = 3

const LABEL_SEGMENT_WIDTHS = {
  day: DAYS_LABEL_WIDTH,
  hour: MIN_SEGMENT_WIDTH,
  minute: MIN_SEGMENT_WIDTH,
  second: SECONDS_LABEL_WIDTH
}

const pad = (number, segmentWidth = MIN_SEGMENT_WIDTH) => String(number).padStart(segmentWidth, '0')

const staticStyles = StyleSheet.create({
  container: {
    justifyContent: 'space-evenly',
    alignItems: 'center'
  },
  containerFlexEnd: {
    alignItems: 'flex-end'
  }
})

const getContainerStyle = (feature, segmentWidth, segmentFontSize, labelKey, hasLabel) => [
  staticStyles.container,
  feature &&
    Platform.OS !== 'web' &&
    segmentWidth < MIN_SEGMENT_WIDTH &&
    staticStyles.containerFlexEnd,
  feature && {
    width: segmentFontSize * SEGMENT_WIDTH_TO_FONT_SIZE_RATIO * segmentWidth
  },
  feature &&
    Platform.OS !== 'web' &&
    hasLabel &&
    LABEL_SEGMENT_WIDTHS[labelKey] > MIN_SEGMENT_WIDTH && {
      width:
        segmentFontSize *
        SEGMENT_WIDTH_TO_FONT_SIZE_RATIO *
        Math.max(segmentWidth, LABEL_SEGMENT_WIDTHS[labelKey])
    }
]

export const Segment = React.forwardRef(
  (
    {
      copy = 'en',
      labelKey,
      labelTokens,
      number,
      numberTokens,
      labelMediaIds,
      mainTextMediaIds,
      segmentFontSize,
      segmentWidth = MIN_SEGMENT_WIDTH,
      variant = {}
    },
    ref
  ) => {
    const getCopy = useCopy({ dictionary, copy })
    const { label, large, feature } = variant

    return (
      <View
        ref={ref}
        style={getContainerStyle(feature, segmentWidth, segmentFontSize, labelKey, label)}
      >
        <StackView
          direction={large || feature ? 'column' : 'row'}
          space={large || feature ? 0 : 1}
          tokens={{ alignItems: 'center' }}
        >
          <Typography
            tokens={numberTokens}
            dataSet={{
              ...(mainTextMediaIds && { media: mainTextMediaIds }),
              chromatic: labelKey === 'second' ? 'ignore' : undefined
            }}
          >
            {pad(number, segmentWidth)}
          </Typography>
          {label && (
            <Typography
              tokens={labelTokens}
              dataSet={labelMediaIds ? { media: labelMediaIds } : undefined}
            >
              {getCopy(number === 1 ? labelKey : `${labelKey}s`)}
            </Typography>
          )}
        </StackView>
      </View>
    )
  }
)

Segment.displayName = 'Segment'

Segment.propTypes = {
  copy: PropTypes.oneOfType([PropTypes.oneOf(['en', 'fr']), dictionaryContentShape]),
  labelKey: PropTypes.oneOf(['day', 'hour', 'minute', 'second']),
  labelTokens: PropTypes.object,
  number: PropTypes.number,
  numberTokens: PropTypes.object,
  segmentFontSize: PropTypes.number,
  segmentWidth: PropTypes.number,
  labelMediaIds: PropTypes.string,
  mainTextMediaIds: PropTypes.string,
  variant: variantProp.propType
}
