import React, { useEffect, useMemo, useState } from 'react'

import { StarFilled, StarOutlined } from '@ant-design/icons'
import {
  Card,
  Group,
  Badge,
  Text,
  Title,
  Box,
  Flex,
  Tooltip,
  TextInput,
  Loader
} from '@mantine/core'
import { useDebouncedValue } from '@mantine/hooks'
import { IconX, IconSearch } from '@tabler/icons-react'
import { useLocalStorageState } from 'ahooks'
import { Button, Pagination } from 'antd'
import clsx from 'clsx'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import useSWR from 'swr'

import { OrgOrganization } from '@clinic/client'
import { listOrgs, starOrg, unStarOrg } from '~/api'
import EmptyResult from '~/components/EmptyResult'
import { OrgIcon } from '~/components/Icons'
import { useMutation } from '~/hooks/use-mutation'
import { useQueryParams } from '~/hooks/use-query-params'
import { orgsTelemetry } from '~/telemetry'
import { formatDateTime } from '~/utils/date-time'

interface OrgCardProps {
  org: OrgOrganization
}

const OrgCard: React.FC<OrgCardProps> = ({ org }) => {
  const lastUpdatedTime = useMemo(
    () => formatDateTime(org.lastUpdated!),
    [org.lastUpdated]
  )

  const [starred, setStarred] = useState(org.isStarred ?? false)
  useEffect(() => {
    setStarred(org.isStarred!)
  }, [org.isStarred])

  const starOrgMut = useMutation(starOrg)
  const unStarOrgMut = useMutation(unStarOrg)

  function handleStar(event: any) {
    event.stopPropagation()
    const isStarred = starred
    setStarred(!isStarred)
    if (isStarred) {
      unStarOrgMut.run(org.id!, undefined, function () {
        // revert if fails
        setStarred(isStarred)
      })
    } else {
      starOrgMut.run(org.id!, undefined, function () {
        // revert if fails
        setStarred(isStarred)
      })
    }
  }

  return (
    <Card shadow='sm' p='lg' radius='md'>
      <Flex
        justify='space-between'
        align='center'
        style={{ whiteSpace: 'nowrap' }}
      >
        <Flex
          align='center'
          gap='sm'
          style={{
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            flexGrow: 1,
            marginRight: '1rem'
          }}
        >
          <Box style={{ flexShrink: 0 }}>
            <OrgIcon />
          </Box>
          <Tooltip label={org.name} withinPortal>
            <Text
              color='#383E40'
              weight={700}
              size='lg'
              style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}
            >
              {org.name}
            </Text>
          </Tooltip>
          <a className='hover:bg-gray-100 rounded p-1' onClick={handleStar}>
            {starred ? (
              <StarFilled className='text-yellow-400 text-base block leading-[0]' />
            ) : (
              <StarOutlined className='text-gray-500 text-base block leading-[0]' />
            )}
          </a>
        </Flex>
        <Badge
          variant='outline'
          color={org.type === 'cloud' ? 'blue' : 'teal'}
          style={{
            flexShrink: 0
          }}
          styles={{
            root: {
              fontWeight: 500
            }
          }}
        >
          {org.type === 'cloud' ? 'Cloud' : 'On-Prem'}
        </Badge>
      </Flex>
      <div className='flex justify-between mt-6'>
        <Group spacing='xs'>
          <Text fz='sm' c='dimmed'>
            Cluster Count:
          </Text>
          <Text fz='sm'>{org.clusterCount}</Text>
        </Group>
        <Group spacing='xs'>
          <Text fz='sm' c='dimmed'>
            Last Updated:
          </Text>
          <Text fz='sm'>{lastUpdatedTime}</Text>
        </Group>
      </div>
    </Card>
  )
}

const FILTERS = ['all', 'mine', 'starred']
const defParams = {
  query: '',
  limit: 10,
  page: 1,
  filter: FILTERS[0]
}

const Page: React.FC = () => {
  const [filter, setFilter] = useLocalStorageState<string>(
    'clinic.orgs.filter',
    {
      defaultValue: FILTERS[0]
    }
  )

  const { queryParams, setQueryParams } = useQueryParams(defParams, { filter })
  const [search, setSearch] = useState('')
  const [debouncedSearch] = useDebouncedValue(search, 500)

  const { data: orgs, error } = useSWR(
    ['/orgs', queryParams, debouncedSearch],
    () =>
      listOrgs(
        debouncedSearch,
        queryParams.filter,
        queryParams.limit,
        queryParams.page
      )
  )
  const loading = !orgs && !error

  const navigate = useNavigate()
  const location = useLocation()

  async function handleSwitchOrg(orgId: string, name: string) {
    orgsTelemetry.clickOrgItem({ id: orgId, name })
    navigate(`/orgs/${orgId}/clusters`, { state: { from: location } })
  }

  function handlePaginationChange(page: number, pageSize: number) {
    orgsTelemetry.clickPagination({ page, pageSize })
    setQueryParams({
      ...queryParams,
      page,
      limit: pageSize
    })
  }

  function handleFilterChange(filter: string) {
    orgsTelemetry.clickFiler({ filter })
    setFilter(filter)
    setQueryParams({
      ...queryParams,
      page: 1,
      filter
    })
  }

  return (
    <div className='flex flex-col min-h-full mb-4 max-w-5xl mx-auto'>
      <section className='flex justify-between pt-4'>
        <div>
          <Title order={1} weight={300}>
            Welcome!
          </Title>
          <Text fz='md'>
            Choose an Organization below to explore your cluster data.
          </Text>
        </div>
        <div className='text-right'>
          <Link to='/orgs/new' onClick={() => orgsTelemetry.clickCreateOrg()}>
            <Button>New Organization</Button>
          </Link>
        </div>
      </section>

      <section className='flex justify-between items-center py-4'>
        <div className='flex items-center gap-2'>
          <Text fz='md'>Organization Name: </Text>
          <TextInput
            name='orgName'
            placeholder='Search with org name...'
            value={search}
            w={300}
            rightSection={
              loading ? (
                <Loader size='xs' />
              ) : !!search ? (
                <Box
                  component={IconX}
                  size={14}
                  sx={{ cursor: 'pointer' }}
                  onClick={() => {
                    setSearch('')
                  }}
                ></Box>
              ) : (
                <Box
                  component={IconSearch}
                  size={14}
                  sx={{ cursor: 'pointer' }}
                ></Box>
              )
            }
            onChange={(event) => {
              setSearch(event.currentTarget.value)
            }}
          />
        </div>

        <div className='flex gap-4'>
          {FILTERS.map((f) => (
            <a
              key={f}
              className={clsx(
                'text-gray-500 capitalize hover:text-inherit',
                f === queryParams.filter && 'text-inherit font-medium'
              )}
              onClick={() => handleFilterChange(f)}
            >
              {f}
            </a>
          ))}
        </div>
      </section>

      <section className='grid grid-cols-1 md:grid-cols-2 gap-4 pb-4'>
        {orgs?.data?.items?.map((org, idx) => (
          <div
            className='cursor-pointer'
            key={org.id}
            onClick={() => handleSwitchOrg(org.id!, org.name!)}
          >
            <OrgCard org={org} />
          </div>
        ))}
      </section>

      {(orgs?.data.total ?? 0) > 0 && (
        <section className='flex justify-end'>
          <Pagination
            total={orgs?.data.total}
            current={queryParams.page}
            pageSize={queryParams.limit}
            onChange={handlePaginationChange}
          />
        </section>
      )}

      {orgs?.data.total === 0 && queryParams.query && <EmptyResult />}
    </div>
  )
}

export default Page
