import { useRef, useState } from "react";

import { Button, DragAndDrop, Icon } from "@ax/components";

import * as S from "./style";

const VALID_FORMATS = ["jpg", "jpeg", "png", "webp"];
const VALID_EXTENSIONS = VALID_FORMATS.map((f) => `.${f}`).join(",");

const UploadView = (props: IProps) => {
	const { onImageLoaded, onSkip } = props;

	const inputRef = useRef<HTMLInputElement | null>(null);
	const [inDropZone, setInDropZone] = useState(false);
	const [dropDepth, setDropDepth] = useState(0);
	const [error, setError] = useState<string | null>(null);

	const isValidFormat = (fileName: string) => {
		const ext = fileName.split(".").pop()?.toLowerCase() ?? "";
		return VALID_FORMATS.includes(ext);
	};

	const readFile = (file: File) => {
		if (!isValidFormat(file.name)) {
			setError(`Invalid format. Allowed: ${VALID_FORMATS.join(", ")}`);
			return;
		}
		setError(null);
		const reader = new FileReader();
		reader.onload = (e) => {
			const result = e.target?.result;
			if (typeof result === "string") onImageLoaded(result);
		};
		reader.readAsDataURL(file);
	};

	const handleDragEnter = () => setDropDepth((d) => d + 1);

	const handleDragLeave = () => {
		setDropDepth((d) => d - 1);
		if (dropDepth > 1) return;
		setInDropZone(false);
	};

	const handleDragOver = () => setInDropZone(true);

	const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
		const file = e.dataTransfer.files[0];
		if (file) readFile(file);
		setInDropZone(false);
		setDropDepth(0);
	};

	const handleFileInput = (e: React.ChangeEvent<HTMLInputElement>) => {
		const file = e.currentTarget.files?.[0];
		if (file) readFile(file);
	};

	const handleClick = () => inputRef.current?.click();

	return (
		<S.Wrapper>
			<S.DragAndDropWrapper>
				<DragAndDrop
					onDrop={handleDrop}
					onDragOver={handleDragOver}
					onDragEnter={handleDragEnter}
					onDragLeave={handleDragLeave}
				>
					<S.DropZone inDropZone={inDropZone}>
						<S.IconWrapper>
							<Icon name="image" size="48" />
						</S.IconWrapper>
						<S.DragTitle>{inDropZone ? "Drop your image" : "Drag your image here"}</S.DragTitle>
						{!inDropZone && <S.DragSubtitle>or</S.DragSubtitle>}
						<S.FilesInput ref={inputRef} type="file" accept={VALID_EXTENSIONS} onChange={handleFileInput} />
						{!inDropZone && (
							<S.SelectButton type="button" buttonStyle="solid" onClick={handleClick}>
								Select image
							</S.SelectButton>
						)}
					</S.DropZone>
				</DragAndDrop>
				{error && <S.DragError data-testid="upload-view-error">{error}</S.DragError>}
			</S.DragAndDropWrapper>
			<S.Actions>
				<Button type="button" buttonStyle="text" onClick={onSkip}>
					Skip profile picture
				</Button>
			</S.Actions>
		</S.Wrapper>
	);
};

interface IProps {
	onImageLoaded: (imageSrc: string) => void;
	onSkip: () => void;
}

export default UploadView;
