import Add from "@mui/icons-material/Add";
import { Alert, Button, TextField } from "@mui/material";
import { getLocalizedString } from "@olenbetong/appframe-core";
import { useId, useRef, useState } from "react";
import type { ProjectsRecord } from "../../data/dsProjects";
import { ProjectSelect } from "../../ProjectSelect";
import { type ElementDetails, getElement } from "../getElement";

const isElementsOnly = /^([a-z]{2,4}[\s]*[0-9]{4,8}[\s,]*)+$/i;
const matchElements = /([a-z]{2,4}[\s]*[0-9]{4,8})/gi;

export type ProjectRecordBase = {
	Domain: string;
	ProjectID: string;
	ProjectName?: string;
};

export type AddElementManualFormProps = {
	onAdd: (element: string | ElementDetails) => Promise<void>;
	mode?: "single" | "multi";
	defaultProject?: ProjectRecordBase;
	allowEmptyElement?: boolean;
};

export function AddElementManualForm({
	onAdd,
	mode,
	defaultProject,
	allowEmptyElement = false,
}: AddElementManualFormProps) {
	let id = useId();
	let buttonRef = useRef<HTMLButtonElement>(null);
	let [working, setWorking] = useState(false);
	let [elementId, setElementId] = useState<string>("");
	let [project, setProject] = useState<Partial<ProjectsRecord> | null>(defaultProject ?? null);

	async function handleSubmit(evt: React.FormEvent<HTMLFormElement>) {
		try {
			evt.preventDefault();
			evt.stopPropagation();
			let formData = new FormData(evt.target as HTMLFormElement);
			let elements = formData.get("ElementID");
			let domain = formData.get("Domain");
			let project: ProjectsRecord = JSON.parse(formData.get("Project") as string);

			if (allowEmptyElement) {
				if (!project.ProjectID) {
					alert(getLocalizedString("Project is required"));
					return;
				}
			} else {
				if (!project.ProjectID || !domain || !elements) {
					let warning = getLocalizedString(
						mode === "multi" ? "Project and elements are required" : "Project and element are required",
					);
					alert(warning);
					return;
				}
			}

			if (elements) {
				setWorking(true);
				let record = (elements as string)
					.match(matchElements)
					?.map((elementId) => elementId.replace(/\s+/g, ""))
					.map((elementId) =>
						getElement({ projectId: project.ProjectID as string, elementId: elementId }, { mode: "manual" }),
					);

				if (!record) {
					alert(getLocalizedString("Invalid elements"));
					return;
				}

				let loaded = (await Promise.all(record)).map((record) => onAdd(record));
				await Promise.all(loaded);
				setWorking(false);
			} else {
				onAdd({
					PrimKey: "",
					Domain: domain?.toString() ?? "",
					Created: project?.Created,
					ProjectID: project.ProjectID,
					ProjectName: project.ProjectName,
					ProjectDomain: project.Domain,
					ElementID: "",
					DisplayName: "",
					GiaiUri: "",
				});
			}
		} catch (error) {
			setWorking(false);
			alert((error as Error).message);
		}
	}

	return (
		<form id={id} onSubmit={handleSubmit} method="post">
			<Alert severity="warning" sx={{ mb: 2 }}>
				{getLocalizedString(
					"Manually entering elements is a major source of errors. Only use this as a last resort. If the camera or scanner is not working, please contact the IT department.",
				)}
			</Alert>

			<input type="hidden" name="Project" value={project ? JSON.stringify(project) : ""} />

			<ProjectSelect
				onChange={(project) => (project ? setProject(project) : setProject(null))}
				value={project}
				id="AddElement_Project"
			/>

			<TextField
				variant="filled"
				fullWidth
				autoComplete="off"
				margin="normal"
				name="ElementID"
				id="AddElement_ElementID"
				label={getLocalizedString("Element ID")}
				value={elementId}
				onChange={(evt) => setElementId(evt.target.value)}
			/>

			<Button
				form={id}
				ref={buttonRef}
				color="primary"
				variant="contained"
				size="large"
				type="submit"
				disabled={(!allowEmptyElement && !isElementsOnly.test(elementId)) || working}
				loading={working}
				loadingPosition="end"
				endIcon={<Add />}
			>
				{getLocalizedString("Add")}
			</Button>
		</form>
	);
}
