import React from 'react'
import PropTypes from 'prop-types'
import {
  Link,
  responsiveProps,
  selectSystemProps,
  useResponsiveProp,
  useThemeTokens,
  withLinkRouter,
  useViewport,
  Typography,
  getTokensPropType
} from '@telus-uds/components-base'
import styled from 'styled-components'
import { OrderedListBase } from '../OrderedList/OrderedListBase'
import { OrderedListItemBase } from '../OrderedList/OrderedListItemBase'
import { Image } from '../Image/Image'
import { htmlAttrs } from '../utils'

const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])

const row = (rowSize, rowBorderWidth) => ({
  flexBasis: `calc(100% / ${rowSize})`,
  [`&:not(:nth-of-type(${rowSize}n + 1))`]: {
    borderLeftWidth: `${rowBorderWidth}px`
  },
  [`&:nth-of-type(n+${rowSize + 1})`]: {
    borderTopWidth: `${rowBorderWidth}px`
  }
})

const Container = styled(OrderedListBase)({
  display: 'flex',
  flexDirection: 'row',
  flexWrap: 'wrap',
  alignContent: 'stretch',
  justifyContent: 'flex-start'
})

const Item = styled(OrderedListItemBase)(
  ({ $rowSize, $itemPadding, $itemBorderColor, $rowBorderWidth }) => ({
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    flexGrow: 1,
    flexShrink: 1,
    padding: `${$itemPadding}px`,
    boxSizing: 'border-box',
    borderStyle: 'solid',
    borderColor: $itemBorderColor,
    borderWidth: 0,
    '& > a': {
      alignSelf: 'center',
      width: '100%'
    },
    ...row($rowSize, $rowBorderWidth)
  })
)

const Center = styled('div')({
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'center',
  textAlign: 'center'
})

/**
 * The WaffleGrid is used to show items in a waffle like manner with borders surrounding the element
 */
export const WaffleGrid = React.forwardRef(
  ({ items, rowSize = null, LinkRouter, tokens, variant, linkRouterProps, ...rest }, ref) => {
    const viewport = useViewport()
    const themeTokens = useThemeTokens('WaffleGrid', tokens, variant, { viewport })
    const currentRowSize = useResponsiveProp(rowSize)

    return (
      <Container ref={ref} {...selectProps(rest)}>
        {items.map((child) => (
          <Item
            key={child.href}
            $rowSize={rowSize ? currentRowSize : themeTokens.rowSize}
            $itemPadding={themeTokens.itemPadding}
            $itemBorderColor={themeTokens.itemBorderColor}
            $rowBorderWidth={themeTokens.rowBorderWidth}
          >
            <Link
              href={child.href}
              LinkRouter={child.LinkRouter || LinkRouter}
              linkRouterProps={{ ...linkRouterProps, ...child.linkRouterProps }}
            >
              <Center>
                {typeof child.image === 'string' ? (
                  // Assuming that string passed is the image URL
                  <Image
                    src={child.image}
                    alt={child.imageAltText}
                    width={96}
                    accessibilityIgnoresInvertColors
                  />
                ) : (
                  // Otherwise it must be an arbitrary content, which we just display by itself
                  child.image
                )}
                <Typography variant={{ weight: 'semibold' }}>{child.text}</Typography>
              </Center>
            </Link>
          </Item>
        ))}
      </Container>
    )
  }
)

WaffleGrid.displayName = 'WaffleGrid'

WaffleGrid.propTypes = {
  ...selectedSystemPropTypes,
  /**
   * The image and the link to display. `items` should be an array of objects with the following keys:
   */
  items: PropTypes.arrayOf(
    PropTypes.shape({
      /**
       * The src attribute for the HTML img element or custom JSX content to render instead
       */
      image: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
      /**
       * The alt attribute for the HTML img element (note that this is ignored if a custom
       * JSX content is used instead of an image URL)
       */
      imageAltText: PropTypes.string,
      /**
       * The text displayed under the image
       */
      text: PropTypes.string,

      /**
       * Target URL
       */
      href: PropTypes.string,
      ...withLinkRouter.propTypes
    })
  ).isRequired,
  /**
   * Sets the tokens for WaffleGrid element.
   */
  tokens: getTokensPropType('WaffleGrid'),
  /**
   * Row size, optionally depending on the viewport
   */
  rowSize: responsiveProps.getTypeOptionallyByViewport(PropTypes.number),
  ...withLinkRouter.propTypes
}
