import MuiDialog, { DialogProps as MuiDialogProps, dialogClasses } from '@mui/material/Dialog'
import { backdropClasses } from '@mui/material/Backdrop'
import styled, { useTheme } from 'styled-components'
import { Button, ButtonBaseProps } from './button'
import { Header } from './header'
import { ReactNode } from 'react'
import { Icon } from './icon'
import { IconName } from './icons'
import { StatusColor } from './theme'
import { IconButton } from './icon-button'
import { InferComponentProps } from './types'
import { useIsLargerThanPhone } from './use-media-query'

const getPaddingX = (isDesktop = false) => (isDesktop ? '48px' : '24px')
const paddingY = '32px'

const StyledHeaderContainer = styled.div<{ textAlign: DialogTextAlign }>`
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  column-gap: 16px;
  padding: ${`${paddingY} ${getPaddingX(false)} 16px`};

  ${Header} {
    ${({ textAlign }) => textAlign === 'left' && 'flex: 1 1 auto;'}
    text-align: ${({ textAlign }) => textAlign};
  }

  @media (${({ theme }) => theme.forLargerThanPhone}) {
    padding: ${`${paddingY} ${getPaddingX(true)} 16px`};
  }
`

const StyledContentContainer = styled.div<{ textAlign: DialogTextAlign }>`
  flex: 1 1 auto;
  overflow-y: auto;
  padding: ${`0 ${getPaddingX(false)}`};
  text-align: ${({ textAlign }) => textAlign};

  @media (${({ theme }) => theme.forLargerThanPhone}) {
    padding: ${`0 ${getPaddingX(true)}`};
  }
`

export const DialogIconContainer = styled.div<{ status: StatusColor }>`
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: ${({ status, theme }) => theme.statusColors[status].backgroundColor};
  color: ${({ status, theme }) => theme.statusColors[status].color};
`

const StyledButtonContainer = styled.div<{ direction: DialogButtonsDirection }>`
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px 16px;
  padding: ${`${paddingY} ${getPaddingX(false)}`};

  @media (${({ theme }) => theme.forLargerThanPhone}) {
    flex-direction: ${({ direction }) => direction};
    justify-content: center;
    padding: ${`40px ${getPaddingX(true)} ${paddingY}`};
  }
`

const CloseX = styled(IconButton)<CloseXProps>`
  position: absolute;
  ${({ $position }) => {
    if ($position === 'left') return 'left: 24px;'
    if ($position === 'right') return 'right: 24px;'
    return ''
  }}
  top: 24px;
`

type CloseXProps = InferComponentProps<typeof IconButton> & {
  $position?: 'left' | 'right'
}

type InternalDialogProps = {
  'data-testid'?: string
  /** If `true` remove padding from Dialog container. */
  noPadding?: boolean
  onCloseX?: false | ((e) => void)
  closeXProps?: CloseXProps
  backgroundImage?: string
  backgroundColor?: string
  backgroundPosition?: string
  backgroundSize?: string
}

export type DialogProps = MuiDialogProps & InternalDialogProps

export const BaseDialog = ({
  noPadding,
  'data-testid': dataTestId = 'dialog',
  fullWidth,
  sx,
  children,
  onCloseX,
  closeXProps,
  backgroundImage,
  backgroundColor,
  backgroundPosition,
  backgroundSize,
  ...props
}: DialogProps) => {
  const theme = useTheme()
  const isDesktop = useIsLargerThanPhone()

  return (
    <MuiDialog
      sx={{
        [`.${dialogClasses.paper}`]: {
          background: backgroundColor || theme.navNeutral,
          ...(backgroundImage && {
            backgroundImage,
            backgroundPosition: backgroundPosition || 'center bottom',
            backgroundRepeat: 'no-repeat',
            backgroundSize: backgroundSize || '100%',
          }),
          borderRadius: '12px',
          boxShadow: 'none',
          margin: backgroundImage ? '0' : '16px',
          padding: () => {
            if (backgroundImage || noPadding) return '0px'
            return `${paddingY} ${getPaddingX(isDesktop)}`
          },
          ...(!fullWidth && {
            maxWidth: '640px',
            width: '640px',
          }),
        },
        [`.${backdropClasses.root}`]: {
          background: 'rgba(0,0,0,0.2)',
        },
        ...sx,
      }}
      data-testid={dataTestId}
      fullWidth={fullWidth}
      {...props}
    >
      {onCloseX ? (
        <CloseX
          aria-label="close"
          name="actions/close"
          variation="outline"
          data-testid="dialog:close-x"
          size="18px"
          color={theme.navNeutralDark}
          onClick={onCloseX}
          $position="left"
          {...closeXProps}
        />
      ) : null}
      {children}
    </MuiDialog>
  )
}

type DialogButtonsDirection = 'column' | 'row-reverse'
type DialogTextAlign = 'left' | 'center'

export type ConfirmationDialogProps = {
  /** Text shown in dialog header. */
  header: string
  /** Slotted dialog content. */
  content: ReactNode
  /** Props passed to primary button. It is recommended to have at least `children` and `onClick`. */
  primaryButtonProps: ButtonBaseProps
  /** Props passed to secondary button. It is recommended to have at least `children` and `onClick`. */
  secondaryButtonProps: ButtonBaseProps
  /** Sets the icon `color` and `background-color` styles. */
  status?: StatusColor
  /** Name of the icon. */
  iconName?: IconName
  /** Controls the header and content text alignment. */
  textAlign?: DialogTextAlign
  /** Defines the `flex-direction` style property of button container. Buttons will always be stacked in a `column` on mobile. */
  buttonsDirection?: DialogButtonsDirection
} & Omit<DialogProps, 'children'>

const _ConfirmationDialog = ({
  header,
  content,
  iconName,
  status = 'fair',
  primaryButtonProps,
  secondaryButtonProps,
  buttonsDirection = 'row-reverse',
  textAlign = 'left',
  ...props
}: ConfirmationDialogProps) => {
  const isDesktop = useIsLargerThanPhone()

  return (
    <BaseDialog {...props} noPadding>
      <StyledHeaderContainer textAlign={textAlign}>
        {iconName && (
          <DialogIconContainer status={status} data-testid="dialog:icon">
            <Icon name={iconName} />
          </DialogIconContainer>
        )}
        <Header data-testid="dialog:header" id={props['aria-labelledby']}>
          {header}
        </Header>
      </StyledHeaderContainer>
      <StyledContentContainer textAlign={textAlign} data-testid="dialog:content" id={props['aria-describedby']}>
        {content}
      </StyledContentContainer>
      <StyledButtonContainer direction={buttonsDirection}>
        <Button
          data-testid="dialog:primary-button"
          {...primaryButtonProps}
          wrap="true"
          size={isDesktop ? 'medium' : 'mediumFull'}
        />
        <Button
          data-testid="dialog:secondary-button"
          {...secondaryButtonProps}
          wrap="true"
          variation="noOutline"
          size={isDesktop ? 'medium' : 'mediumFull'}
        />
      </StyledButtonContainer>
    </BaseDialog>
  )
}

export const ConfirmationDialog = styled(_ConfirmationDialog)``
