import "./index.scss";

import clsx from "clsx";
import { forwardRef, type HTMLAttributes, useEffect, useId, useRef } from "react";

function Mark(props: HTMLAttributes<SVGElement>) {
	return (
		<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" {...props}>
			<path d="M20.285 2L9 13.567 3.714 8.556 0 12.272 9 21 24 5.715z" fill="currentColor" />
		</svg>
	);
}

export type CheckboxProps = React.RefAttributes<HTMLInputElement> &
	Omit<React.HTMLProps<HTMLInputElement>, "value"> & {
		className?: string;
		id?: string;
		/**
		 * Label for the checkbox.
		 */
		label?: React.ReactNode;
		/**
		 * Tooltip text for the checkbox.
		 */
		title?: string;
		value?: boolean;
		/**
		 * Reverses the checkbox layout, placing the label before the checkbox.
		 */
		reverse?: boolean;
	};

export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(
	{ className, disabled = false, id, onChange = () => null, label, title, reverse, value, ...other }: CheckboxProps,
	ref: React.ForwardedRef<HTMLInputElement>,
) {
	let inputId = useId();
	inputId = id ?? inputId;
	let inputIdRef = `#${inputId}`;
	let input = useRef<HTMLInputElement>(null);

	// oxlint-disable-next-line react-hooks/exhaustive-deps -- Ref object
	useEffect(() => {
		if (typeof ref === "function") {
			ref(input.current);
		} else if (ref) {
			ref.current = input.current;
		}
	}, []);

	function handleClick() {
		let elem = input.current;
		if (elem) {
			elem.focus();
			elem.click();
		}
	}

	function handleInputChanged(evt: any) {
		if (!disabled) {
			onChange(evt);
		}
	}

	function handleKeyDown(evt: any) {
		if (evt.nativeEvent) {
			let { nativeEvent } = evt;

			if (nativeEvent.key === " ") {
				nativeEvent.preventDefault();
				input.current?.click();
			}
		}
	}

	return (
		<div
			className={clsx("ObCheckbox-root", disabled && "Ob-disabled", reverse && "Ob-reverse", className)}
			title={title}
		>
			<input
				className="ObCheckbox-input"
				id={inputId}
				type="checkbox"
				onChange={handleInputChanged}
				checked={value}
				disabled={disabled}
				ref={input}
				{...other}
			/>
			<label htmlFor={inputIdRef} className="ObCheckbox-label" onKeyDown={handleKeyDown} onClick={handleClick}>
				<div className="ObCheckbox-box">
					<Mark className="ObCheckbox-mark" />
				</div>
				{label && <div className="ObCheckbox-label-text">{label}</div>}
			</label>
		</div>
	);
});
