import { Author, Book, Checkout, Copy, Repository } from '@/payload-types'
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'
import { EllipsisVerticalIcon } from '@heroicons/react/20/solid'
import clsx from 'clsx'
import { Loader2Icon } from 'lucide-react'
import { PaginatedDocs, User } from 'payload'
import { useCallback, useState } from 'react'

const statuses = {
  'Passed Due': 'text-gray-200 bg-red-500 ring-red-700/10',
  'Due Soon': 'text-amber-800 bg-amber-50 ring-amber-600/20',
  '': '',
}

type Row = {
  id: number
  title: string
  authors: string[]
  owners: string[]
  repositoryAbbreviation: string
  status: 'Passed Due' | 'Due Soon' | ''
  dueDate: Date
  href: string
}

type ListProps = { rows: Row[] }
const CheckedOutBooksList = (props: ListProps) => {
  const { rows } = props

  const [returningBookId, setReturningBookId] = useState(0)

  const isReturningBook = useCallback((id: number) => id === returningBookId, [returningBookId])

  const handleReturnClick = useCallback((id: number) => {
    setReturningBookId(id)
  }, [])

  return (
    <ul role="list" className="divide-y divide-gray-100">
      {rows.map((r) => (
        <li key={r.id} className="flex items-center justify-between gap-x-6 py-5">
          <div className="min-w-0">
            <div className="flex items-start gap-x-3">
              <p className="text-sm/6 text-foreground">
                <span className="font-semibold">{`[${r.repositoryAbbreviation}] `}</span>
                <span>{r.title}</span>
              </p>
              {!!r.status && (
                <p
                  className={clsx(
                    statuses[r.status as keyof typeof statuses],
                    'mt-0.5 rounded-md px-1.5 py-0.5 text-xs font-medium whitespace-nowrap ring-1 ring-inset',
                  )}
                >
                  {r.status}
                </p>
              )}
            </div>
            <div className="mt-1 flex items-center gap-x-2 text-xs/5 text-gray-500">
              <p className="whitespace-nowrap">
                Due on <time dateTime={r.dueDate.toString()}>{r.dueDate.toLocaleDateString()}</time>
              </p>
              <svg viewBox="0 0 2 2" className="size-0.5 fill-current">
                <circle r={1} cx={1} cy={1} />
              </svg>
              <p className="truncate">Borrowed from {r.owners.join(', ')}</p>
            </div>
          </div>
          <div className="flex flex-none items-center gap-x-4">
            <button
              type="button"
              disabled={!!returningBookId}
              className="hidden disabled:opacity-20 cursor-pointer disabled:cursor-auto rounded-md bg-background px-2.5 py-1.5 text-sm font-semibold text-muted-foreground shadow-xs ring-1 ring-gray-300 ring-inset hover:bg-gray-50 sm:flex items-center gap-1"
              onClick={() => handleReturnClick(r.id)}
            >
              {isReturningBook(r.id) && <Loader2Icon className="animate-spin" />}
              <span>Return</span>
            </button>
            <Menu as="div" className="relative flex-none">
              <MenuButton className="-m-2.5 block p-2.5 text-gray-500 hover:text-gray-900">
                <span className="sr-only">Open options</span>
                <EllipsisVerticalIcon aria-hidden="true" className="size-5" />
              </MenuButton>
              <MenuItems
                transition
                className="absolute right-0 z-10 mt-2 w-32 origin-top-right rounded-md bg-white py-2 shadow-lg ring-1 ring-gray-900/5 transition focus:outline-hidden data-closed:scale-95 data-closed:transform data-closed:opacity-0 data-enter:duration-100 data-enter:ease-out data-leave:duration-75 data-leave:ease-in"
              >
                <MenuItem>
                  <button
                    className="block cursor-pointer px-3 py-1 text-sm/6 text-gray-900 data-focus:bg-gray-50 data-focus:outline-hidden"
                    type="button"
                    onClick={() => console.log('return')}
                  >
                    Return<span className="sr-only">, {r.title}</span>
                  </button>
                </MenuItem>
                <MenuItem>
                  <a
                    href={`/repositories/${r.repositoryAbbreviation}`}
                    className="block px-3 py-1 text-sm/6 text-gray-900 data-focus:bg-gray-50 data-focus:outline-hidden"
                  >
                    Repository<span className="sr-only">, {r.repositoryAbbreviation}</span>
                  </a>
                </MenuItem>
                <MenuItem>
                  <a
                    href={r.href}
                    className="block px-3 py-1 text-sm/6 text-gray-900 data-focus:bg-gray-50 data-focus:outline-hidden"
                  >
                    View<span className="sr-only"> {r.title}</span>
                  </a>
                </MenuItem>
              </MenuItems>
            </Menu>
          </div>
        </li>
      ))}
    </ul>
  )
}

type Props = { initialCheckoutPage: PaginatedDocs<Checkout> | null }
const CheckedOutBooks = (props: Props) => {
  const { initialCheckoutPage } = props

  const checkouts = initialCheckoutPage?.docs
  const rows: Row[] =
    checkouts?.map((c) => {
      const copy = c.copy as Copy
      const book = copy.book as Book
      const authors = book.authors as Author[]
      const repository = copy.repository as Repository
      const owners = repository.owner as (number | User)[]

      const parsedDateDue = c.dateDue ? new Date(c.dateDue) : new Date()
      const milisecondsUntilDue = parsedDateDue.getTime() - new Date().getTime()
      const secondsUntilDue = Math.floor(milisecondsUntilDue / 1000)
      const minutesUntilDue = Math.floor(secondsUntilDue / 60)
      const hoursUntilDue = Math.floor(minutesUntilDue / 60)
      const daysUntilDue = Math.floor(hoursUntilDue / 24)

      let status = ''
      if (daysUntilDue <= 0) status = 'Passed Due'
      else if (daysUntilDue <= 5) status = 'Due Soon'

      return {
        id: c.id || 0,
        title: book.title || '',
        authors: authors.map((a) => a.lf) || ([] as string[]),
        owners:
          owners.map((o) => `${(o as User).firstName} ${(o as User).lastName}`) || ([] as string[]),
        repositoryAbbreviation: repository.abbreviation || '',
        status,
        dueDate: parsedDateDue,
        href: `/books/${book.id}`,
      } as Row
    }) || []

  if (!rows.length) return null

  return (
    <section className="py-6">
      <div className="mb-4 flex justify-between items-end">
        <h3 className="px-4 text-lg font-semibold">Outbound Checked Out Books</h3>
      </div>
      <CheckedOutBooksList rows={rows} />
    </section>
  )
}

export default CheckedOutBooks
