import React, { memo, useCallback, useMemo, useState } from 'react'

import { LazyIllustration } from '../../components/lazy-illustration/LazyIllustration'
import { illustrationNames } from '../../generated/illustrationAssets'

const debounce = <P = unknown,>(
  callback: (...args: P[]) => unknown,
  wait: number,
) => {
  let timeoutId: number
  return (...args: P[]) => {
    if (timeoutId) {
      window.clearTimeout(timeoutId)
    }
    timeoutId = window.setTimeout(() => {
      callback(...args)
    }, wait)
  }
}

const IllustrationItem = memo(
  ({
    children,
    name,
    copyText,
    onClick,
  }: React.PropsWithChildren<{
    name: string
    copyText: string
    onClick: () => void
  }>) => {
    return (
      <li>
        <button
          onClick={onClick}
          className="uy:group uy:flex uy:flex-col uy:w-full uy:items-center uy:gap-125 uy:p-200 uy:transition-all uy:rounded-100 uy:bg-surface-neutral uy:hover:bg-surface-neutral-low-hover uy:shadow-raising uy:hover:shadow-floating uy:focus-visible:shadow-floating uy:focus-visible:outline-none uy:focus-visible:ring-2 uy:focus-visible:ring-ring uy:focus-visible:ring-offset-2 uy:focus-visible:ring-utility-focus-ring uy:focus-visible:border-border-form-hover uy:focus-visible:bg-surface-neutral-low-hover uy:border uy:border-solid uy:border-border-neutral"
        >
          <figure className="uy:flex uy:flex-col uy:items-center uy:w-full">
            <div className="uy:flex uy:justify-center uy:items-center uy:w-[90%] uy:transition-all uy:group-hover:scale-120">
              {children}
            </div>
            <figcaption className="uy:flex uy:flex-col uy:items-center">
              <span className="uy:typography-body-strong uy:text-content-neutral uy:cursor-pointer uy:truncate uy:w-full uy:block">
                {name}
              </span>
              <span className="uy:typography-action-small uy:bg-transparent uy:text-content-primary">
                {copyText}
              </span>
            </figcaption>
          </figure>
        </button>
      </li>
    )
  },
)

const IllustrationLibrary = ({
  filter,
}: {
  filter?: 'filled' | 'outlined'
}) => {
  const [query, setQuery] = useState<string>('')
  const [copiedIllustration, setCopiedIllustration] = useState<string | null>(
    null,
  )

  const illustrationList = useMemo(() => {
    const predicate =
      filter !== undefined
        ? (name: string) => name.toLowerCase().includes(filter)
        : () => true
    return illustrationNames
      .filter(name => !name.endsWith('Animation'))
      .filter(name => predicate(name))
  }, [filter])

  const copyToClipboard = useCallback((illustrationName: string) => {
    const importStatement = `import ${illustrationName} from '@payfit/unity-illustrations/assets/${illustrationName}'`

    navigator.clipboard
      .writeText(importStatement)
      .then(() => {
        setCopiedIllustration(illustrationName)
        setTimeout(() => {
          setCopiedIllustration(null)
        }, 5000)
      })
      .catch((error: unknown) => {
        console.error('Failed to copy: ', error)
      })
  }, [])

  const updateSearchQuery = debounce((illustrationName: string) => {
    setQuery(illustrationName)
  }, 150)

  const illustrationListMatchingSearch = illustrationList.filter(
    illustrationName =>
      illustrationName.toLowerCase().includes(query.toLowerCase()),
  )

  return (
    <section className="uy:flex uy:flex-col uy:gap-300 uy:max-w-[80vmax] uy:mx-auto">
      <header>
        <h3>Illustration Gallery</h3>
        <p className="uy:m-0!">
          Click on any illustration to copy its import path to the clipboard.
        </p>
      </header>
      <input
        type="search"
        placeholder="Search for an illustration..."
        className="uy:flex uy:h-500 uy:w-full uy:text-content-form-enabled uy:rounded-100 uy:border uy:border-solid uy:border-border-form-enabled uy:bg-background uy:px-150 uy:py-100 uy:typography-body uy:placeholder:text-content-neutral-lowest uy:hover:border-border-form-hover uy:focus-visible:outline-none uy:focus-visible:ring-2 uy:focus-visible:ring-ring uy:focus-visible:ring-offset-2 uy:focus-visible:ring-utility-focus-ring"
        onChange={e => {
          updateSearchQuery(e.target.value)
        }}
      />
      <ul className="sb-unstyled uy:list-none uy:grid uy:grid-cols-[repeat(auto-fill,minmax(200px,_1fr))] uy:gap-x-100 uy:gap-y-200">
        {illustrationListMatchingSearch.map(name => {
          return (
            <IllustrationItem
              name={name}
              copyText={
                copiedIllustration === name ? 'Copied!' : 'Click to Copy'
              }
              key={name}
              onClick={() => {
                copyToClipboard(name)
              }}
            >
              <LazyIllustration
                variant="picture"
                alt={`${name} illustration`}
                name={name}
              />
            </IllustrationItem>
          )
        })}
      </ul>
    </section>
  )
}

export default IllustrationLibrary
