import type { ButtonProps } from '@blueprintjs/core'
import {
  Button,
  Classes,
  Dialog,
  DialogBody,
  DialogFooter,
  FileInput,
  InputGroup,
} from '@blueprintjs/core'
import { notify } from '@inject/shared/notification/engine'
import type { ChangeEvent, FC } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'
import TooltipLabel from '../Tooltips/TooltipLabel'
import { GENERIC_CONTENT } from '../assets/generalContent'
import { FILE_UPLOAD_FORM } from '../assets/pageContent/files'
import { addFile, updateFile } from '../indexeddb/operations'
import type { ContentFile } from '../indexeddb/types'

interface FileUploaderProps {
  contentFile?: ContentFile
  buttonProps: ButtonProps
  onAdd?: (id: number) => void
}

const FileUploader: FC<FileUploaderProps> = ({
  contentFile,
  buttonProps,
  onAdd,
}) => {
  const [isOpen, setIsOpen] = useState<boolean>(false)
  const [name, setName] = useState<string>('')
  const [file, setFile] = useState<File | undefined>()

  const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    if (e.target.files) {
      setFile(e.target.files[0])
    }
  }

  const placeholder = useMemo(() => file?.name || 'Input text', [file?.name])

  const clearInput = useCallback(() => {
    setName('')
    setFile(undefined)
  }, [])

  const handleAddButton = useCallback(async (file: Omit<ContentFile, 'id'>) => {
    try {
      const id = await addFile(file)
      if (onAdd) onAdd(Number(id))
      clearInput()
      setIsOpen(false)
    } catch (error) {
      notify(
        `Failed to add file '${file.name}': ${error}`,
        JSON.stringify(error),
        {
          intent: 'danger',
        }
      )
    }
  }, [])

  const handleUpdateButton = useCallback(async (file: ContentFile) => {
    try {
      await updateFile(file)
      setIsOpen(false)
    } catch (error) {
      notify(
        `Failed to update file '${file.name}': ${error}`,
        JSON.stringify(error),
        {
          intent: 'danger',
        }
      )
    }
  }, [])

  useEffect(() => {
    setName(contentFile?.name || '')
    setFile(
      contentFile?.blob
        ? new File([contentFile?.blob], contentFile?.name)
        : undefined
    )
  }, [contentFile])

  return (
    <>
      <Button {...buttonProps} onClick={() => setIsOpen(true)} />
      <Dialog
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        icon={contentFile ? 'edit' : 'plus'}
        title={contentFile ? 'Edit file' : 'New file'}
      >
        <DialogBody>
          <TooltipLabel label={FILE_UPLOAD_FORM.name}>
            <InputGroup
              placeholder={placeholder}
              value={name}
              onChange={e => setName(e.target.value)}
            />
          </TooltipLabel>
          <TooltipLabel label={FILE_UPLOAD_FORM.file}>
            <div
              style={{ display: 'flex', gap: '0.5rem', alignItems: 'flex-end' }}
            >
              <FileInput
                className={Classes.INPUT}
                fill
                hasSelection={file !== undefined}
                text={file ? file.name : 'Choose file...'}
                onInputChange={handleFileChange}
              />
            </div>
          </TooltipLabel>
        </DialogBody>
        <DialogFooter
          actions={
            contentFile ? (
              <Button
                disabled={!file}
                onClick={() =>
                  handleUpdateButton({
                    id: contentFile.id,
                    name: file && name === '' ? file?.name : name,
                    blob: file
                      ? new Blob([file], { type: file.type })
                      : new Blob(),
                  })
                }
                intent='primary'
                icon='edit'
                text={GENERIC_CONTENT.buttons.save}
              />
            ) : (
              <Button
                disabled={!file}
                onClick={() =>
                  handleAddButton({
                    name: file && name === '' ? file?.name : name,
                    blob: file
                      ? new Blob([file], { type: file.type })
                      : new Blob(),
                  })
                }
                intent='primary'
                icon='plus'
                text={GENERIC_CONTENT.buttons.add}
              />
            )
          }
        />
      </Dialog>
    </>
  )
}

export default FileUploader
