import Customers from "@Front/Api/LeCoffreApi/Notary/Customers/Customers";
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
import AutocompleteMultiSelect from "@Front/Components/DesignSystem/AutocompleteMultiSelect";
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption";
import Form from "@Front/Components/DesignSystem/Form";
import TextField from "@Front/Components/DesignSystem/Form/TextField";
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
import BackArrow from "@Front/Components/Elements/BackArrow";
import Module from "@Front/Config/Module";
import { ValidationError } from "class-validator";
import { ECivility } from "le-coffre-resources/dist/Customer/Contact";
import { Contact, Customer, OfficeFolder } from "le-coffre-resources/dist/Notary";
import Link from "next/link";
import { useRouter } from "next/router";
import backgroundImage from "@Assets/images/background_refonte.svg";
import classes from "./classes.module.scss";
import { useCallback, useEffect, useState } from "react";
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";

enum ESelectedOption {
	EXISTING_CUSTOMER = "existing_customer",
	NEW_CUSTOMER = "new_customer",
}
type IProps = {};

export default function AddClientToFolder(props: IProps) {
	const router = useRouter();
	let { folderUid } = router.query;

	const [selectedOption, setSelectedOption] = useState<ESelectedOption>(ESelectedOption.EXISTING_CUSTOMER);
	const [availableCustomers, setAvailableCustomers] = useState<Customer[]>([]);
	const [selectedCustomers, setSelectedCustomers] = useState<IOption[]>([]);
	const [existingCustomers, setExistingCustomers] = useState<IOption[]>([]);
	const [isLoaded, setIsLoaded] = useState<boolean>(false);
	const [validationError, setValidationError] = useState<ValidationError[]>([]);

	const onFormSubmit = useCallback(
		async (
			e: React.FormEvent<HTMLFormElement> | null,
			values: {
				[key: string]: any;
			},
		) => {
			values["civility"] = ECivility.MALE; // TODO: should maybe be deleted later or added to the form

			const allCustomersToLink = selectedCustomers.concat(existingCustomers);
			let customersToLink: Partial<Customer>[] = allCustomersToLink.map((customer) => {
				return Customer.hydrate<Customer>({ uid: customer.id as string });
			}) as Partial<Customer>[];

			if (selectedOption === "new_customer") {
				try {
					// remove every space from the phone number
					values["cell_phone_number"] = values["cell_phone_number"].replace(/\s/g, "");
					values["cell_phone_number"] = values["cell_phone_number"].replace(/\./g, "");
					if (values["cell_phone_number"] && values["cell_phone_number"].length === 10) {
						// get the first digit of the phone number
						const firstDigit = values["cell_phone_number"].charAt(0);
						// if the first digit is a 0 replace it by +33
						if (firstDigit === "0") {
							values["cell_phone_number"] = "+33" + values["cell_phone_number"].substring(1);
						}
					}
					const contactToCreate = Contact.hydrate<Customer>(values);
					await contactToCreate.validateOrReject?.({ groups: ["createCustomer"], forbidUnknownValues: false });
				} catch (validationErrors) {
					setValidationError(validationErrors as ValidationError[]);
					return;
				}

				try {
					const customer: Customer = await Customers.getInstance().post({
						contact: values,
					});
					if (!customer.uid) return;
					customersToLink?.push({ uid: customer.uid } as Partial<Customer>);
				} catch (backError) {
					if (!Array.isArray(backError)) return;
					setValidationError(backError as ValidationError[]);
					return;
				}
			}

			if (customersToLink) {
				const body = OfficeFolder.hydrate<OfficeFolder>({
					customers: customersToLink.map((customer) => {
						return Customer.hydrate<Customer>(customer);
					}),
				});
				await Folders.getInstance().put(folderUid as string, body);
				router.push(`/folders/${folderUid}`);
			}
		},
		[existingCustomers, folderUid, router, selectedCustomers, selectedOption],
	);

	const getFolderPreSelectedCustomers = useCallback(
		async (folderUid: string): Promise<IOption[] | undefined> => {
			const query = {
				q: {
					customers: {
						include: {
							contact: true,
						},
					},
				},
			};
			let preExistingCustomers: IOption[] = [];
			try {
				const folder = await Folders.getInstance().getByUid(folderUid, query);
				preExistingCustomers = folder.customers!.map((customer) => {
					return {
						label: customer.contact?.first_name + " " + customer.contact?.last_name,
						id: customer.uid ?? "",
					};
				});
			} catch (error) {
				router.push(Module.getInstance().get().modules.pages["404"].props.path);
				return;
			}
			return preExistingCustomers;
		},
		[router],
	);

	const loadCustomers = useCallback(async () => {
		const query = {};
		const availableCustomers = await Customers.getInstance().get(query);
		let preExistingCustomers: IOption[] | undefined = await getFolderPreSelectedCustomers(folderUid as string);
		const existingCustomers = preExistingCustomers ?? [];

		existingCustomers.forEach((customer) => {
			const index = availableCustomers.findIndex((availableCustomer) => availableCustomer.uid === customer.id);
			if (index !== -1) availableCustomers.splice(index, 1);
		});

		let selectedOption = ESelectedOption.EXISTING_CUSTOMER;
		if (availableCustomers.length === 0) {
			selectedOption = ESelectedOption.NEW_CUSTOMER;
		}

		setAvailableCustomers(availableCustomers);
		setExistingCustomers(existingCustomers);
		setIsLoaded(true);
		setSelectedOption(selectedOption);
	}, [folderUid, getFolderPreSelectedCustomers]);

	const getSelectedOptions = useCallback((): IOption[] => {
		let options = availableCustomers?.map((customer) => {
			return {
				label: customer.contact?.first_name + " " + customer.contact?.last_name,
				id: customer.uid ?? "",
			};
		});
		if (!options) options = [];
		return options;
	}, [availableCustomers]);

	const onMutiSelectChange = (selectedCustomers: IOption[] | null): void => {
		if (!selectedCustomers) return;
		setSelectedCustomers(selectedCustomers);
	};

	const onExistingClientSelected = (): void => setSelectedOption(ESelectedOption.EXISTING_CUSTOMER);
	const onNewClientSelected = (): void => setSelectedOption(ESelectedOption.NEW_CUSTOMER);

	useEffect(() => {
		loadCustomers();
	}, [loadCustomers]);

	const selectOptions: IOption[] = getSelectedOptions();

	const backwardPath = Module.getInstance()
		.get()
		.modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folderUid as string);
	return (
		<DefaultDoubleSidePage title={"Ajouter client(s)"} image={backgroundImage} showHeader>
			<div className={classes["root"]}>
				<div className={classes["back-arrow"]}>
					<BackArrow url={backwardPath} />
				</div>
				<Typography typo={ETypo.TITLE_H1}>Associer un ou plusieurs client(s)</Typography>
				{isLoaded && (
					<>
						<div className={classes["radiobox-container"]}>
							{availableCustomers.length !== 0 && (
								<RadioBox
									name="client"
									onChange={onExistingClientSelected}
									checked={selectedOption === "existing_customer"}
									value={"existing client"}
									label="Client existant"
								/>
							)}

							<RadioBox
								name="client"
								onChange={onNewClientSelected}
								checked={selectedOption === "new_customer"}
								value={"new client"}
								label="Nouveau client"
							/>
						</div>

						<Form className={classes["form"]} onSubmit={onFormSubmit}>
							{selectedOption === "existing_customer" && (
								<div className={classes["existing-client"]}>
									<AutocompleteMultiSelect
										label="Clients"
										options={selectOptions}
										selectedOptions={selectedCustomers}
										onSelectionChange={onMutiSelectChange}
									/>

									<div className={classes["button-container"]}>
										<Link href={backwardPath} className={classes["cancel-button"]}>
											<Button variant={EButtonVariant.PRIMARY} styletype={EButtonstyletype.OUTLINED}>
												Annuler
											</Button>
										</Link>
										<Button type="submit">Associer au dossier</Button>
									</div>
								</div>
							)}

							{selectedOption === "new_customer" && (
								<div className={classes["new-client"]}>
									<TextField
										name="last_name"
										placeholder="Nom"
										validationError={validationError.find((error) => error.property === "last_name")}
									/>
									<TextField
										name="first_name"
										placeholder="Prénom"
										validationError={validationError.find((error) => error.property === "first_name")}
									/>
									<TextField
										name="email"
										placeholder="E-mail"
										validationError={validationError.find((error) => error.property === "email")}
									/>
									<TextField
										name="cell_phone_number"
										placeholder="Numéro de téléphone"
										validationError={validationError.find((error) => error.property === "cell_phone_number")}
									/>
									<div className={classes["button-container"]}>
										<Link href={backwardPath} className={classes["cancel-button"]}>
											<Button variant={EButtonVariant.PRIMARY} styletype={EButtonstyletype.OUTLINED}>
												Annuler
											</Button>
										</Link>
										<Button type="submit">Associer au dossier</Button>
									</div>
								</div>
							)}
						</Form>
					</>
				)}
			</div>
		</DefaultDoubleSidePage>
	);
}
