import { useNavigate } from '@/router'
import { useHost } from '@inject/graphql/connection/host'
import type { FileInfo } from '@inject/graphql/fragments/FileInfo.generated'
import { downloadFileUrl } from '@inject/shared/config'
import type { MouseEventHandler } from 'react'
import { useMemo, type FC } from 'react'
import { generatePath, useHref, useLocation } from 'react-router-dom'
import type { LinkType } from '../LinkButton'
import FileButtonComponent from './FileButtonComponent'

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

/*
 * supported file extension list for current version 1.14.0
 * https://www.npmjs.com/package/@cyntler/react-doc-viewer/v/1.14.0
 */

const SUPPORTED_FILE_EXTENSIONS = [
  'bmp',
  'gif',
  'jpg',
  'jpeg',
  'pdf',
  'png',
  'tiff',
  'txt',
]

/**
 * 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.
 *
 * @param fileInfo - The information about the file.
 * @param teamId - The ID of the team.
 * @param exerciseId - The ID of the exercise.
 * @param inInstructor - Indicates whether the user is an instructor.
 * @returns The rendered FileViewRedirectButton component.
 */
const FileViewRedirectButton: FC<DocumentViewButtonProps> = ({
  fileInfo,
  teamId,
  exerciseId,
  inInstructor,
  onDelete,
}) => {
  const nav = useNavigate()
  const loc = useLocation().pathname
  const host = useHost()

  const parsedFilename = fileInfo.fileName.split('.')
  const isSupported = SUPPORTED_FILE_EXTENSIONS.includes(
    parsedFilename[parsedFilename.length - 1] || ''
  )

  const link: LinkType | undefined = 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 } },
      ]
    }
  }, [exerciseId, fileInfo.id, loc, teamId])

  const handleClick: MouseEventHandler = e => {
    if (!isSupported || !link) {
      return
    }

    // prevent default navigation using anchor to avoid page reload
    e.preventDefault()

    /*
     * 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)
  }

  const supportedHref = useHref(
    /*
     * this has to be done with apply to ensure type safety between
     * link.to and link.params
     */
    isSupported && link
      ? generatePath.apply(null, [link[0].toString(), link[1]?.params])
      : '.'
  )
  const href = useMemo(
    () =>
      isSupported && link
        ? supportedHref
        : downloadFileUrl(
            host || '',
            teamId,
            fileInfo.id,
            inInstructor ?? false
          ),
    [fileInfo.id, host, inInstructor, isSupported, link, supportedHref, teamId]
  )

  return (
    <FileButtonComponent onClick={handleClick} href={href} onDelete={onDelete}>
      {fileInfo.fileName}
    </FileButtonComponent>
  )
}

export default FileViewRedirectButton
