import MuiDialog, { DialogProps as MuiDialogProps, dialogClasses } from '@mui/material/Dialog'
import useMediaQuery from '@mui/material/useMediaQuery'
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'

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)}`};
  }
`

const StyledIconContainer = 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;
  row-gap: 8px;
  column-gap: 16px;
  padding: ${`${paddingY} ${getPaddingX(false)}`};

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

type InternalDialogProps = {
  'data-testid'?: string
  /** If `true` remove padding from Dialog container. */
  noPadding?: boolean
}

export type DialogProps = Pick<
  MuiDialogProps,
  'aria-labelledby' | 'aria-describedby' | 'children' | 'className' | 'open' | 'onClose'
> &
  InternalDialogProps

export const BaseDialog = ({ noPadding, 'data-testid': dataTestId = 'dialog', ...props }: DialogProps) => {
  const theme = useTheme()
  const isDesktop = useMediaQuery(`(${theme.forLargerThanPhone})`)

  return (
    <MuiDialog
      sx={{
        [`.${dialogClasses.paper}`]: {
          background: () => theme.navSecondary100,
          borderRadius: '12px',
          boxShadow: 'none',
          margin: '16px',
          padding: () => {
            if (noPadding) return '0px'
            return `${paddingY} ${getPaddingX(isDesktop)}`
          },
          maxWidth: '640px',
          width: '640px',
        },
        [`.${backdropClasses.root}`]: {
          background: 'rgba(0,0,0,0.2)',
        },
      }}
      data-testid={dataTestId}
      {...props}
    />
  )
}

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
} & DialogProps

export const ConfirmationDialog = ({
  header,
  content,
  iconName,
  status = 'fair',
  primaryButtonProps,
  secondaryButtonProps,
  buttonsDirection = 'row-reverse',
  textAlign = 'left',
  ...props
}: ConfirmationDialogProps) => {
  const theme = useTheme()
  const isDesktop = useMediaQuery(`(${theme.forLargerThanPhone})`)

  return (
    <BaseDialog {...props} noPadding>
      <StyledHeaderContainer textAlign={textAlign}>
        {iconName && (
          <StyledIconContainer status={status} data-testid="dialog:icon">
            <Icon name={iconName} />
          </StyledIconContainer>
        )}
        <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 default styled(ConfirmationDialog)``
