"use client"

import type { IUploadStepProps } from "./UploadStep.d"
import type { JSX } from "react"

import { Upload } from "lucide-react"
import { FunctionComponent, useCallback, useRef, useState } from "react"

import cs from "classnames"

import { uploadFileWithProgress } from "@shared/api/uploadFile"
import { useWizard } from "@shared/context/WizardContext"
import { Button } from "@shared/ui"

import styles from "./UploadStep.module.scss"

const ACCEPTED_VIDEO_TYPES = "video/*"
const ERROR_UPLOAD_FAILED = "Не удалось загрузить файл"

export const UploadStep: FunctionComponent<IUploadStepProps> = ({
	className,
}): JSX.Element => {
	const { projectId, setFileKey } = useWizard()
	const [isDragging, setIsDragging] = useState(false)
	const [isUploading, setIsUploading] = useState(false)
	const [progress, setProgress] = useState(0)
	const [error, setError] = useState<string | null>(null)
	const inputRef = useRef<HTMLInputElement>(null)

	const handleUpload = useCallback(
		async (file: File) => {
			setIsUploading(true)
			setProgress(0)
			setError(null)

			try {
				const result = await uploadFileWithProgress(
					file,
					`projects/${projectId}`,
					setProgress,
				)
				await setFileKey(
					result.file_path,
					result.file_id,
					result.filename ?? null,
				)
			} catch {
				setError(ERROR_UPLOAD_FAILED)
			} finally {
				setIsUploading(false)
			}
		},
		[projectId, setFileKey],
	)

	const handleFileChange = useCallback(
		(e: React.ChangeEvent<HTMLInputElement>) => {
			const file = e.target.files?.[0]
			if (file) handleUpload(file)
			/* Reset input so re-selecting the same file triggers change */
			e.target.value = ""
		},
		[handleUpload],
	)

	const handleDrop = useCallback(
		(e: React.DragEvent) => {
			e.preventDefault()
			setIsDragging(false)
			const file = e.dataTransfer.files[0]
			if (file) handleUpload(file)
		},
		[handleUpload],
	)

	const handleDragOver = useCallback((e: React.DragEvent) => {
		e.preventDefault()
		setIsDragging(true)
	}, [])

	const handleDragLeave = useCallback((e: React.DragEvent) => {
		e.preventDefault()
		setIsDragging(false)
	}, [])

	return (
		<div className={cs(styles.root, className)} data-testid="UploadStep">
			<div className={styles.content}>
				<div
					className={cs(styles.dropZone, {
						[styles.dropZoneActive]: isDragging,
						[styles.dropZoneUploading]: isUploading,
					})}
					onDrop={handleDrop}
					onDragOver={handleDragOver}
					onDragLeave={handleDragLeave}
					onClick={() => inputRef.current?.click()}
				>
					<input
						ref={inputRef}
						type="file"
						accept={ACCEPTED_VIDEO_TYPES}
						className={styles.fileInput}
						onChange={handleFileChange}
						disabled={isUploading}
					/>
					<Upload size={48} className={styles.icon} />

					{isUploading ? (
						<>
							<p className={styles.title}>Загрузка файла...</p>
							<div className={styles.progressTrack}>
								<div
									className={styles.progressBar}
									style={{ width: `${progress}%` }}
								/>
							</div>
							<p className={styles.progressLabel}>{Math.round(progress)}%</p>
						</>
					) : (
						<>
							<p className={styles.title}>Перетащите видеофайл сюда</p>
							<p className={styles.subtitle}>или нажмите для выбора файла</p>
							<Button
								variant="outline"
								size="sm"
								type="button"
								onClick={(e) => {
									e.stopPropagation()
									inputRef.current?.click()
								}}
							>
								Выбрать файл
							</Button>
						</>
					)}

					{error && <p className={styles.error}>{error}</p>}
				</div>
			</div>
		</div>
	)
}
