import { Link } from '@chakra-ui/next-js'
import {
  Alert,
  AlertDescription,
  AlertIcon,
  AlertTitle,
  Box,
  Button,
  ButtonGroup,
  Card,
  CardBody,
  Flex,
  HStack,
  Heading,
  IconButton,
  Image,
  Input,
  InputGroup,
  InputLeftElement,
  InputRightElement,
  LinkBox,
  LinkOverlay,
  Menu,
  MenuButton,
  MenuDivider,
  MenuItem,
  MenuList,
  SimpleGrid,
  Skeleton,
  Spinner,
  Table,
  Tbody,
  Td,
  Text,
  Tr,
} from '@chakra-ui/react'
import { useDebouncedCallback, useLocalStorageValue } from '@react-hookz/web'
import Head from 'next/head'
import { useRouter } from 'next/router'
import { TbCheck, TbFilter, TbFilterEdit, TbLayoutGrid, TbLayoutList, TbMoodSad, TbSearch, TbX } from 'react-icons/tb'
import useSWR from 'swr'
import Pagination from '~/components/pagination'

const PER_PAGE = 12

export const getStaticProps = async () => {
  const url = new URL(`${process.env.NEXT_PUBLIC_DIRECTUS_API_URL}/items/categories`)
  url.searchParams.append('fields[]', 'slug')
  url.searchParams.append('fields[]', 'name')
  url.searchParams.append('fields[]', 'subcategories.slug')
  url.searchParams.append('fields[]', 'subcategories.name')
  url.searchParams.append('sort', 'name')
  url.searchParams.append('limit', -1)
  url.searchParams.append(
    'filter',
    JSON.stringify({
      parent_id: {
        _null: true,
      },
    })
  )

  const res = await fetch(url.toString())

  const { data: categories } = await res.json()

  return { props: { categories } }
}

export default function VendorsPage({ globals, categories }) {
  const router = useRouter()
  const {
    query: { page = 1, category = '', q: search = '' },
  } = router

  const { value: perPage, set: setPerPage } = useLocalStorageValue('perPage', {
    defaultValue: PER_PAGE,
    initializeWithValue: false,
  })

  const { value: layout, set: setLayout } = useLocalStorageValue('layout', {
    defaultValue: 'GRID',
    initializeWithValue: false,
  })

  const setSearch = useDebouncedCallback(
    (q) => {
      router.replace({ query: { ...router.query, q } })
    },
    [router],
    500
  )

  const { data, error, isLoading, isValidating } = useSWR(['vendors', page, perPage, search, category], async () => {
    if (!perPage) return

    const url = new URL(`${process.env.NEXT_PUBLIC_DIRECTUS_API_URL}/items/vendors`)
    url.searchParams.append('fields[]', '*')
    url.searchParams.append('limit', perPage)
    url.searchParams.append('page', page)
    url.searchParams.append('sort', 'name')
    url.searchParams.append('meta[]', 'filter_count')

    if (search !== '' || category !== '') {
      url.searchParams.append(
        'filter',
        JSON.stringify({
          _and: [
            category !== '' ? { categories: { categories_id: { slug: { _eq: category } } } } : {},
            search !== ''
              ? {
                  _or: ['name', 'description', 'long_description', 'city'].map((s) => ({
                    [s]: { _contains: search },
                  })),
                }
              : {},
          ],
        })
      )
    }

    const res = await fetch(url.toString())
    if (!res.ok) {
      throw new Error('Oops')
    }
    return res.json()
  })

  const { meta, data: vendors } = data || { meta: {}, data: [] }

  const lastPage = Math.max(1, Math.ceil(meta.filter_count / perPage))
  if (!isNaN(lastPage) && page > lastPage) {
    router.replace({ query: { ...router.query, page: lastPage } })
  }

  return (
    <Box className="vendors">
      <Head>
        <title>{['Vendors', globals.meta_title].join(' — ')}</title>
      </Head>
      <Flex alignItems="center" justifyContent="space-between" direction={['column', 'row']} mb="5" gap="5">
        <Heading size="lg">Vendors</Heading>
        <Box>{isValidating && <Spinner />}</Box>
        <HStack gap="5">
          <InputGroup>
            <InputLeftElement>
              <TbSearch />
            </InputLeftElement>
            <Input onChange={(ev) => setSearch(ev.target.value.toLowerCase())} />
            <InputRightElement
              onClick={(ev) => {
                ev.currentTarget.parentNode.childNodes[1].value = ''
                setSearch('')
              }}
            >
              {search !== '' && <TbX />}
            </InputRightElement>
          </InputGroup>
          <Menu>
            <MenuButton as={IconButton} icon={category === '' ? <TbFilter /> : <TbFilterEdit />} />
            <MenuList>
              {categories.map((cat) => (
                <Link key={cat.slug} prefetch={false} href={{ query: { ...router.query, category: cat.slug } }}>
                  <MenuItem icon={category === cat.slug && <TbCheck />} isDisabled={category === cat.slug}>
                    {cat.name}
                  </MenuItem>
                </Link>
              ))}
              <MenuDivider />
              <Link href={{ query: { ...router.query, category: '' } }}>
                <MenuItem>Clear</MenuItem>
              </Link>
            </MenuList>
          </Menu>
          <ButtonGroup isAttached>
            <IconButton icon={<TbLayoutGrid />} onClick={() => setLayout('GRID')} isDisabled={layout === 'GRID'} />
            <IconButton icon={<TbLayoutList />} onClick={() => setLayout('LIST')} isDisabled={layout === 'LIST'} />
          </ButtonGroup>
        </HStack>
      </Flex>

      {error && (
        <Alert status="error" marginY={3}>
          <AlertIcon />
          There was an error processing your request
        </Alert>
      )}

      {layout === 'GRID' && (
        <SimpleGrid columns={[1, 2, 3, 4]} spacing={3}>
          {isLoading &&
            new Array(perPage).fill(true).map((v, k) => (
              <Card key={k}>
                <Skeleton h="40" />
                <CardBody>
                  <Skeleton h="6" mb="2" />
                  <Skeleton h="4" mb="1" />
                  <Skeleton h="4" />
                </CardBody>
              </Card>
            ))}
          {!isLoading &&
            vendors.map((v) => (
              <LinkBox as={Card} rounded={4} key={v.id}>
                <Image
                  roundedTop={4}
                  objectFit="contain"
                  src={`${process.env.NEXT_PUBLIC_DIRECTUS_API_URL}/assets/${v.logo}?key=logo-card`}
                  alt={v.name}
                  width="250"
                  height="150"
                  style={{ objectFit: 'contain', background: '#fff' }}
                />
                <CardBody>
                  <LinkOverlay as={Link} href={`/vendors/${v.slug}`} prefetch={false}>
                    <Text mb="2" fontWeight="900">
                      {v.name}
                    </Text>
                    <Text fontSize="sm">
                      {v?.description?.substring(0, v?.description?.substring(0, 80).lastIndexOf(' '))} &hellip;
                    </Text>
                  </LinkOverlay>
                </CardBody>
              </LinkBox>
            ))}
        </SimpleGrid>
      )}

      {layout === 'LIST' && (
        <>
          {isLoading && (
            <Table>
              <Tbody>
                {new Array(perPage).fill(true).map((v, k) => (
                  <Tr key={k}>
                    <Td w="10%">
                      <Skeleton h="12" w="12" />
                    </Td>
                    <Td w="30%">
                      <Skeleton h="6" />
                    </Td>
                    <Td w="60%">
                      <Skeleton h="6" />
                    </Td>
                  </Tr>
                ))}
              </Tbody>
            </Table>
          )}
          {!isLoading && (
            <Table>
              <Tbody>
                {vendors.map((v) => (
                  <Link key={v.id} href={`/vendors/${v.slug}`} prefetch={false} display="contents">
                    <Tr verticalAlign="middle">
                      <Td>
                        <Image
                          rounded="md"
                          src={`${process.env.NEXT_PUBLIC_DIRECTUS_API_URL}/assets/${v.logo}?key=logo-card`}
                          alt={v.name}
                          width="12"
                          height="12"
                          style={{ objectFit: 'contain', background: '#fff' }}
                        />
                      </Td>
                      <Td>{v.name}</Td>
                      <Td>
                        <Text fontSize="sm">
                          {v?.description?.substring(0, v?.description?.substring(0, 80).lastIndexOf(' '))} &hellip;
                        </Text>
                      </Td>
                    </Tr>
                  </Link>
                ))}
              </Tbody>
            </Table>
          )}
        </>
      )}

      {meta.filter_count === 0 && (
        <Box>
          <Alert status="info" flexDirection="column" justifyContent="center" rounded="md" paddingY="10">
            <TbMoodSad style={{ width: '2rem', height: '2rem' }} />
            <AlertTitle mt={4} mb={1} fontSize="lg">
              No results found.
            </AlertTitle>
            <AlertDescription maxWidth="sm">Try refining your search term and filters &hellip;</AlertDescription>
          </Alert>
        </Box>
      )}

      {meta.filter_count > perPage && (
        <>
          <Pagination page={Number(page)} itemsPerPage={perPage} totalItems={meta.filter_count} />
          <HStack mt="5" justifyContent="center">
            <Text>Results per page:</Text>
            <ButtonGroup isAttached>
              {[12, 24, 48].map((n) => (
                <Button key={n} onClick={() => setPerPage(n)} isDisabled={perPage === n}>
                  {n}
                </Button>
              ))}
            </ButtonGroup>
          </HStack>
        </>
      )}
    </Box>
  )
}
