import { useNavigate } from '@/router'
import { Classes, Icon } from '@blueprintjs/core'
import { css, cx } from '@emotion/css'
import type { FileInfo } from '@inject/graphql/fragment-types'
import { SUPPORTED_FILE_EXTENSIONS } from '@inject/shared/components/DocViewer'
import { breakWord } from '@inject/shared/css/textOverflow'
import type { MouseEventHandler } from 'react'
import { useMemo, type FC } from 'react'
import { generatePath, useHref, useLocation } from 'react-router-dom'
import type { LinkType } from '../LinkButton'

const fileButton = css`
  max-width: 100%;
  display: flex;
  align-items: center;
  gap: 0.5rem;
`

const clickable = css`
  cursor: pointer;
`

interface DocumentViewButtonProps {
  teamId: string
  fileInfo: FileInfo
  exerciseId: string
  onDelete?: () => void
}

/**
 * Renders a button component that redirects to a file view
 * or triggers a file download if the file extension is not supported.
 *
 * The redirect is content-aware and will redirect to the
 * trainee/instructor/analyst page based on the current location.
 * If this component is used outside of these pages, it will throw an error.
 *
 * @param fileInfo - The information about the file.
 * @param teamId - The ID of the team.
 * @param exerciseId - The ID of the exercise.
 * @returns The rendered FileViewRedirectButton component.
 */
const FileViewRedirectButton: FC<DocumentViewButtonProps> = ({
  fileInfo,
  teamId,
  exerciseId,
  onDelete,
}) => {
  const nav = useNavigate()
  const loc = useLocation().pathname

  const link: LinkType = useMemo(() => {
    if (loc.startsWith('/trainee')) {
      return [
        '/trainee/:exerciseId/:teamId/file/:fileId',
        { params: { exerciseId, fileId: fileInfo.id, teamId } },
      ]
    }
    if (loc.startsWith('/instructor')) {
      return [
        '/instructor/:exerciseId/:teamId/file/:fileId',
        { params: { exerciseId, fileId: fileInfo.id, teamId } },
      ]
    }
    if (loc.startsWith('/analyst')) {
      return [
        '/analyst/:exerciseId/:teamId/file/:fileId',
        { params: { exerciseId, fileId: fileInfo.id, teamId } },
      ]
    }
    throw new Error('Unsupported location')
  }, [exerciseId, fileInfo.id, loc, teamId])

  const href = useHref(
    /*
     * this has to be done with apply to ensure type safety between
     * link.to and link.params
     */
    generatePath.apply(null, [link[0].toString(), link[1]?.params])
  )

  const handleClick: MouseEventHandler = e => {
    // prevent default navigation using anchor to avoid page reload
    e.preventDefault()

    const extension = fileInfo.fileName.split('.').pop()
    if (!extension || !SUPPORTED_FILE_EXTENSIONS.includes(extension)) {
      window.open(href, '_blank')
      return
    }

    /*
     * this has to be done with apply to ensure type safety between
     * link.to and link.params
     */
    // eslint-disable-next-line prefer-spread
    nav.apply(null, link)
  }

  return (
    <div className={fileButton}>
      <Icon
        icon={onDelete ? 'cross' : 'paperclip'}
        onClick={onDelete}
        className={cx({ [Classes.TEXT_MUTED]: true, [clickable]: !!onDelete })}
        title={onDelete ? 'Remove attachment' : 'Attachment'}
      />
      <a className={breakWord} href={href} onClick={handleClick}>
        {fileInfo.fileName}
      </a>
    </div>
  )
}

export default FileViewRedirectButton
