import { Autocomplete, ListItem, ListItemText, type SxProps, TextField, type Theme } from "@mui/material";
import { getLocalizedString } from "@olenbetong/appframe-core";
import { useDataWithFilter, useDebounce } from "@olenbetong/appframe-react";
import { useMemo, useRef, useState } from "react";
import { dsProjects, type ProjectsRecord } from "./data/dsProjects";
import { dsReportProjects } from "./data/dsReportProjects";

type ProjectSelectProps = {
	className?: string;
	disabled?: boolean;
	id?: string;
	names?: {
		domain?: string;
		projectId?: string;
		name?: string;
	};
	nullable?: boolean;
	readOnly?: boolean;
	required?: boolean;
	onChange?: (project: Partial<ProjectsRecord> | null) => void;
	defaultValue?: Partial<ProjectsRecord> | null;
	value?: Partial<ProjectsRecord> | null;
	label?: string;
	sx?: SxProps<Theme> | undefined;
	report?: boolean;
};

export function ProjectSelect({
	className,
	disabled,
	id,
	names,
	onChange,
	readOnly,
	required,
	defaultValue,
	value,
	label,
	sx,
	report,
}: ProjectSelectProps) {
	let [selected, setSelected] = useState<Partial<ProjectsRecord | null>>(defaultValue ?? null);
	let [query, setQuery] = useState("");
	let search = useDebounce(query);
	let projects = useDataWithFilter(
		report ? dsReportProjects : dsProjects,
		search ? `[SearchColumn] LIKE '%${search}%'` : "",
	);

	let highlightRef = useRef<Partial<ProjectsRecord | null>>(null);

	function handleSelect(value: Partial<ProjectsRecord> | null) {
		highlightRef.current = null;

		if (!disabled && !readOnly) {
			if (onChange) {
				onChange(value);
			} else {
				setSelected(value);
			}
		}
	}

	let current = value === undefined ? selected : value;

	const duplicatedNames = useMemo(() => {
		const nameCount = new Map<string, number>();
		projects.forEach((opt) => {
			nameCount.set(opt.ProjectName, (nameCount.get(opt.ProjectName) || 0) + 1);
		});

		return new Set([...nameCount.entries()].filter(([, count]) => count > 1).map(([name]) => name));
	}, [projects]);

	return (
		<>
			<Autocomplete<Partial<ProjectsRecord>>
				sx={sx}
				autoHighlight
				autoSelect
				clearOnEscape
				className={className}
				options={projects}
				disabled={disabled}
				getOptionLabel={(option) =>
					option?.ProjectID !== undefined ? `${option.ProjectID}: ${option.ProjectName}` : ""
				}
				isOptionEqualToValue={(option, value) => option.Domain === value.Domain && option.ProjectID === value.ProjectID}
				onChange={(_, value) => handleSelect(value)}
				onClose={() => setQuery("")}
				value={value !== undefined ? value : selected}
				renderInput={(params) => (
					<TextField
						{...(params as any)}
						label={label ? label : getLocalizedString("Project ID")}
						id={id ?? "ProjectLookup"}
						fullWidth
						slotProps={{
							input: params.slotProps?.input,
							inputLabel: params.slotProps?.inputLabel,
							htmlInput: {
								readOnly,
								...params.slotProps?.htmlInput,
							},
						}}
						autoComplete="off"
						variant="filled"
						required={required}
						onChange={(evt) => setQuery(evt.target.value)}
						value={query}
					/>
				)}
				renderOption={(props, option) => {
					let isDuplicated = option.ProjectName && duplicatedNames.has(option.ProjectName);
					return (
						<ListItem {...props}>
							<ListItemText
								primary={isDuplicated ? `${option.ProjectName} (${option.Domain})` : option.ProjectName}
								secondary={option.ProjectID}
							/>
						</ListItem>
					);
				}}
			/>
			<input name={names?.domain ?? "Domain"} type="hidden" value={current?.Domain ?? ""} />
			<input name={names?.name ?? "ProjectName"} type="hidden" value={current?.ProjectName ?? ""} />
			<input name={names?.projectId ?? "ProjectID"} type="hidden" value={current?.ProjectID ?? ""} />
		</>
	);
}
