import { useRef, useEffect, ReactNode } from 'react'
import styled from 'styled-components'
import Copy from './copy.js'
import { focusWithoutScroll } from '@navinc/utils'
import { InferComponentProps } from './types.js'
import { Theme } from './theme.js'
import { Property } from 'csstype'
import isRebrand from './is-rebrand.js'

const getLabelStyling = ({ isInvalid, theme }: { isInvalid?: boolean; theme: Theme }) => `
  margin: 0;
  padding: 0;
  color: ${isInvalid ? theme.error : 'inherit'};
`

const getFillColor = (theme, disabled, isInvalid) => {
  if (isRebrand(theme)) return isInvalid ? theme.navStatusNegative100 : theme.navSecondary
  return disabled ? theme.neutral100 : theme.bubbleBlue100
}

const getBorderColor = (theme, disabled, isInvalid, checked) => {
  if (isRebrand(theme)) {
    if (isInvalid) return theme.navStatusNegative
    return checked ? theme.navPrimary400 : theme.navNeutral300
  }
  return disabled ? theme.scuttleGray300 : theme.bubbleBlue200
}

const getIndicatorColor = (theme, checked, isInvalid) => {
  if (isRebrand(theme)) {
    if (checked) return isInvalid ? theme.navStatusNegative : theme.navPrimary400
    return 'transparent'
  }
  return checked ? theme.navPrimary : 'transparent'
}

const CopyLabel = styled(Copy).withConfig({
  shouldForwardProp: (prop) => !['isInvalid'].includes(prop),
})`
  ${getLabelStyling}
`

const DivLabel = styled.div<{ isInvalid?: boolean }>`
  ${getLabelStyling}
`

const RadioItem = styled.label<{
  asideContent?: boolean
  hasBorder?: boolean
  checked?: boolean
  checkedBackgroundColor?: Property.BackgroundColor
}>`
  display: flex;
  flex-flow: row nowrap;
  align-items: center;
  flex: 1 1 auto;
  margin-bottom: 0;
  cursor: pointer;
  text-align: left;
  ${({ asideContent, hasBorder, theme }) =>
    (asideContent || hasBorder) &&
    `
    border-radius: ${isRebrand(theme) ? '8px' : '12px'};
    border: 1px solid ${isRebrand(theme) ? theme.navNeutral300 : theme.border};
    padding: ${isRebrand(theme) ? '14px 16px' : '8px 16px'};
    min-height:${isRebrand(theme) ? '24px' : '62px'};
  `}

  ${({ checked, checkedBackgroundColor }) =>
    checked &&
    checkedBackgroundColor &&
    `
    background-color: ${checkedBackgroundColor};
    border-color: ${checkedBackgroundColor};
  `}

  & > :first-child {
    margin-right: 16px;
  }
`

const AsideContainer = styled.div`
  display: flex;
  flex: 1;
  justify-content: flex-end;
  margin-left: 8px;
`

const RadioIndicator = styled.input.attrs(() => ({ type: 'radio' }))<{
  isInvalid?: boolean
}>`
  box-sizing: border-box;
  border-radius: 50%;
  background-color: ${({ checked, isInvalid, theme }) => getIndicatorColor(theme, checked, isInvalid)};
  height: 12px;
  width: 12px;
  appearance: none;
  margin: 0;
  font-size: inherit;
  transition: background-color 300ms ease;
`

const RadioSpot = styled.div<{ checked?: boolean; disabled?: boolean; isInvalid?: boolean }>`
  display: flex;
  justify-content: center;
  align-items: center;
  box-sizing: border-box;
  border-radius: 50%;
  border-style: solid;
  border-width: ${({ checked, theme }) => (checked && !isRebrand(theme) ? '2px' : '1px')};
  border-color: ${({ disabled, checked, isInvalid, theme }) => getBorderColor(theme, disabled, isInvalid, checked)};
  background: ${({ disabled, isInvalid, theme }) => getFillColor(theme, disabled, isInvalid)};
  opacity: ${({ disabled, theme }) => disabled && isRebrand(theme) && '38%'};
  height: 24px;
  flex: 0 0 auto;
  width: 24px;
  transition: box-shadow 300ms ease;

  &:focus-within {
    box-shadow: ${({ theme }) =>
      isRebrand(theme) ? `0 0 0 4px ${theme.navStatusPositive500}` : `0 0 0 8px ${theme.bubbleBlue300}`};

    & > ${RadioIndicator} {
      outline: none;
    }
  }
`

type RadioProps = {
  asideContent?: boolean
  autoFocus?: boolean
  checkedBackgroundColor?: Property.BackgroundColor
  children?: ReactNode
  label?: ReactNode
  className?: string
  checked?: boolean
  disabled?: boolean
  hasBorder?: boolean
  isInvalid?: boolean
} & InferComponentProps<typeof RadioIndicator>
export const Radio = ({
  asideContent,
  autoFocus,
  checkedBackgroundColor,
  children: _children,
  label,
  className,
  checked,
  disabled,
  hasBorder,
  isInvalid,
  ...props
}: RadioProps) => {
  const inputRef = useRef<HTMLElement>(null)

  useEffect(() => {
    if (autoFocus && inputRef.current) {
      focusWithoutScroll(inputRef.current)
    }
  }, [autoFocus])

  const Label = typeof label === 'string' ? CopyLabel : DivLabel

  return (
    <RadioItem
      asideContent={asideContent}
      checked={checked}
      className={className}
      hasBorder={hasBorder}
      checkedBackgroundColor={checkedBackgroundColor}
    >
      <RadioSpot {...{ checked, disabled, isInvalid }}>
        <RadioIndicator ref={inputRef} {...{ checked, disabled, isInvalid }} {...props} />
      </RadioSpot>
      <Label isInvalid={isInvalid}>{label}</Label>
      {asideContent && <AsideContainer>{asideContent}</AsideContainer>}
    </RadioItem>
  )
}

const StyledRadio = styled(Radio)``
export default StyledRadio
