import { forwardRef, useEffect, useId, useImperativeHandle, useRef, useState, type RefObject } from 'react'
import VectorIconTop from '../../vectors/top.svg'
import './styles/File.css'
import type { BackendLimit } from '../../functions/BackendTypes'

export interface PropsForInputFile {
    limits: BackendLimit['upload'] | undefined
}

export interface HandleForInputFile {
    getPreview: () => HTMLVideoElement | HTMLImageElement | undefined
    getValue: () => File | undefined
}

const InputFile = forwardRef<HandleForInputFile, PropsForInputFile>(({ limits }, ref) => {
    const componentID = useId()
    const previewRef = useRef<HTMLVideoElement | HTMLImageElement>(undefined)
    const inputRef = useRef<HTMLInputElement>(null)

    const [fileInstance, setFileInstance] = useState<File>()
    const [fileObjectURL, setFileObjectURL] = useState<string>()

    function updateInput(file?: File) {
        if (fileObjectURL) {
            URL.revokeObjectURL(fileObjectURL)
        }
        const accept = file && !!limits?.mime_types.find((t) => file.type === t)
        if (accept) {
            setFileObjectURL(URL.createObjectURL(file))
            setFileInstance(file)
        } else {
            setFileObjectURL(undefined)
            setFileInstance(undefined)
        }
    }

    useImperativeHandle(ref, () => ({
        getPreview: () => previewRef.current,
        getValue: () => fileInstance,
    }))

    useEffect(() => {
        return () => {
            fileObjectURL && URL.revokeObjectURL(fileObjectURL)
        }
    }, [fileObjectURL])

    return (
        <div
            id="input-file"
            className="input-file"
            tabIndex={0}
            onClick={() => inputRef.current?.click()}
            onDragOver={(e) => e.preventDefault()}
            onDrop={(e) => {
                e.preventDefault()
                updateInput(e.dataTransfer.files.item(0)!)
            }}>
            <input
                id={componentID}
                ref={inputRef}
                type="file"
                accept={limits?.mime_types ? limits.mime_types.join(',') : '*/*'}
                onChange={(e) => {
                    e.preventDefault()
                    updateInput(e.target.files?.item(0) ?? undefined)
                }}
            />

            {!fileInstance && (
                <div className="prompt">
                    <img className="icon animation-fade-in" src={VectorIconTop} />
                    <span className="header animation-scroll-in">DRAG OR CLICK TO UPLOAD A FILE</span>
                    {limits && (
                        <span className="subheader animation-scroll-in">
                            MAX: {limits.video_width_max} &times; {limits.video_height_max}; SIZE:{' '}
                            {Math.floor(limits.filesize / 1024 / 1024)}MB; DURATION:{' '}
                            {Math.floor(limits.duration / 10) * 10} SECS;
                        </span>
                    )}
                </div>
            )}

            {fileInstance && (
                <div className="preview">
                    {fileInstance.type.startsWith('video') && (
                        <video
                            ref={previewRef as RefObject<HTMLVideoElement>}
                            autoPlay
                            loop
                            muted
                            src={fileObjectURL}
                        />
                    )}
                    {fileInstance.type.startsWith('image') && (
                        <img ref={previewRef as RefObject<HTMLImageElement>} src={fileObjectURL} />
                    )}
                </div>
            )}
        </div>
    )
})

export default InputFile
