import backgroundImage from "@Assets/images/404-background-image.jpeg";
import DeedTypes from "@Front/Api/LeCoffreApi/SuperAdmin/DeedTypes/DeedTypes";
import Folders from "@Front/Api/LeCoffreApi/SuperAdmin/Folders/Folders";
import Users from "@Front/Api/LeCoffreApi/SuperAdmin/Users/Users";
import Button from "@Front/Components/DesignSystem/Button";
import Form from "@Front/Components/DesignSystem/Form";
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography";
import BackArrow from "@Front/Components/Elements/BackArrow";
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
import { Deed, DeedType, Office, OfficeFolder, OfficeFolderHasStakeholder } from "le-coffre-resources/dist/Notary";

import User from "le-coffre-resources/dist/Notary";
import { NextRouter, useRouter } from "next/router";
import React from "react";
import { ActionMeta, MultiValue } from "react-select";

import BasePage from "../../Base";
import classes from "./classes.module.scss";
import { ValidationError } from "class-validator";
import SelectField, { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
import TextField from "@Front/Components/DesignSystem/Form/TextField";
import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField";

type IFormValues = {
	folder_number: string;
	entitled: string;
	act_typ: IOption | null;
	personal_note: string;
	collaborators: MultiValue<IOption>;
};

type IProps = {};

type IPropsClass = IProps & {
	router: NextRouter;
};

type IState = {
	folder_access: string;
	formValues: IFormValues;
	deedTypes: DeedType[];
	deedTypesOptions: IOption[];
	collaborators: User[];
	collaboratorsOptions: IOption[];
	validationError: ValidationError[];
};
class CreateFolderClass extends BasePage<IPropsClass, IState> {
	public constructor(props: IPropsClass) {
		super(props);

		this.state = {
			folder_access: "",
			formValues: {
				folder_number: "",
				entitled: "",
				act_typ: null,
				personal_note: "",
				collaborators: [],
			},
			deedTypes: [],
			deedTypesOptions: [],
			collaborators: [],
			collaboratorsOptions: [],
			validationError: [],
		};

		this.radioOnChange = this.radioOnChange.bind(this);
		this.onFolderNumberChange = this.onFolderNumberChange.bind(this);
		this.onEntitleChange = this.onEntitleChange.bind(this);
		this.onActTypeChange = this.onActTypeChange.bind(this);
		this.onPersonalNoteChange = this.onPersonalNoteChange.bind(this);
		this.onCollaboratorsChange = this.onCollaboratorsChange.bind(this);
		this.isFormSubmittable = this.isFormSubmittable.bind(this);
		this.onFormSubmit = this.onFormSubmit.bind(this);
	}

	public override render(): JSX.Element {
		return (
			<DefaultDoubleSidePage title={"Dossier"} image={backgroundImage} type="background" showHeader={true}>
				<div className={classes["root"]}>
					<BackArrow />
					<Typography typo={ITypo.H1} color={ITypoColor.BLACK} className={classes["title"]}>
						Créer un dossier
					</Typography>
					<Typography typo={ITypo.H3} color={ITypoColor.PURPLE_FLASH} className={classes["subtitle"]}>
						Informations dossier
					</Typography>
					<Form onSubmit={this.onFormSubmit}>
						<div className={classes["form-container"]}>
							<TextField
								name="folder_number"
								placeholder="Numéro de dossier"
								onChange={this.onFolderNumberChange}
								validationError={this.state.validationError.find((error) => error.property === "folder_number")}
							/>
							<TextField
								name="name"
								placeholder="Intitulé"
								onChange={this.onEntitleChange}
								validationError={this.state.validationError.find((error) => error.property === "name")}
							/>
							<SelectField
								options={this.state.deedTypesOptions}
								placeholder={"Type d'acte"}
								onChange={this.onActTypeChange}
								errors={this.state.validationError.find((error) => error.property === "deed")}
							/>
							<TextAreaField
								name="description"
								placeholder="Note du dossier"
								onChange={this.onPersonalNoteChange}
								validationError={this.state.validationError.find((error) => error.property === "description")}
							/>
						</div>
						<div className={classes["access-container"]}>
							<Typography typo={ITypo.H3} color={ITypoColor.PURPLE_FLASH}>
								Accès au dossier
							</Typography>
							<div className={classes["radio-container"]}>
								<RadioBox name="file_access" defaultChecked onChange={this.radioOnChange} value="whole_office">
									Sélectionner tout l'office
								</RadioBox>
								<RadioBox name="file_access" onChange={this.radioOnChange} value="select_collaborators">
									Sélectionner certains collaborateurs
								</RadioBox>
							</div>
							{this.state.folder_access === "select_collaborators" && (
								<div className={classes["collaborators-container"]}>
									<MultiSelect
										options={this.state.collaboratorsOptions}
										placeholder="Sélectionner les collaborateurs"
										onChange={this.onCollaboratorsChange}
										defaultValue={this.state.formValues.collaborators ?? []}
									/>
								</div>
							)}
							<div className={classes["buttons-container"]}>
								<Button fullwidth type="submit">
									Créer un dossier
								</Button>
							</div>
						</div>
					</Form>
				</div>
			</DefaultDoubleSidePage>
		);
	}

	public override async componentDidMount() {
		const deedTypes = await DeedTypes.getInstance().get({ q: {} });

		// TODO SETUP userStore and get the user's office membership -> Replace IwJ70M471c by the user's office membership uid
		const usersMock = await Users.getInstance().get({ include: { office_membership: true } });
		const userMock = usersMock[0];
		// -------------------
		const collaborators = await Users.getInstance().get({
			where: { office_membership: { uid: userMock?.office_membership?.uid } },
			include: { contact: true },
		});
		this.setState({
			deedTypes,
			deedTypesOptions: this.mapDeedOptions(deedTypes),
			collaborators,
			collaboratorsOptions: this.mapUsersOptions(collaborators),
		});
	}

	private mapDeedOptions(deedTypes: DeedType[]) {
		return deedTypes.map((deedType) => ({
			label: deedType.name,
			value: deedType.uid,
		})) as IOption[];
	}

	private mapUsersOptions(collaborators: User[]) {
		return collaborators.map((collaborator) => ({
			label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name),
			value: collaborator.uid,
		})) as IOption[];
	}

	private onFolderNumberChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) {
		this.setState({
			formValues: {
				...this.state.formValues,
				folder_number: e.target.value,
			},
		});
	}

	private onEntitleChange(e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) {
		this.setState({
			formValues: {
				...this.state.formValues,
				entitled: e.target.value,
			},
		});
	}

	private onActTypeChange(selectedOption: IOption) {
		this.setState({
			formValues: {
				...this.state.formValues,
				act_typ: selectedOption,
			},
		});
	}

	private onPersonalNoteChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) {
		this.setState({
			formValues: {
				...this.state.formValues,
				personal_note: e.target.value,
			},
		});
	}

	private onCollaboratorsChange(newValue: MultiValue<IOption>, actionMeta: ActionMeta<IOption>) {
		this.setState({
			formValues: {
				...this.state.formValues,
				collaborators: newValue,
			},
		});
	}

	private async onFormSubmit(
		e: React.FormEvent<HTMLFormElement> | null,
		values: {
			[key: string]: any;
		},
	) {
		const selectedDeedTypeUid: DeedType | undefined = this.state.deedTypes.find(
			(deedType) => deedType.uid === this.state.formValues.act_typ?.value,
		);

		/**
		 * MOCK DATA
		 */
		const usersMock = await Users.getInstance().get({ include: { office_membership: true } });
		const userMock = usersMock[0];

		let stakeholders = this.getStakeholders();
		let testUsers = stakeholders.map((stakeholder) => ({
			user_stakeholder: {
				uid: stakeholder.user_stakeholder.uid,
			},
		}));

		const officeFolderForm = OfficeFolder.hydrate<OfficeFolder>({
			folder_number: values["folder_number"],
			name: values["name"],
			description: values["description"],
			deed: Deed.hydrate<Deed>({
				deed_type: DeedType.hydrate<DeedType>({
					uid: selectedDeedTypeUid?.uid,
				}),
			}),
			office: Office.hydrate<Office>({
				uid: userMock?.office_membership?.uid,
			}),
			office_folder_has_stakeholder: testUsers.map((user) => {
				return OfficeFolderHasStakeholder.hydrate<OfficeFolderHasStakeholder>({
					user_stakeholder: User.hydrate<User>({
						uid: user.user_stakeholder.uid,
					}),
				});
			}),
		});

		try {
			await officeFolderForm.validateOrReject?.({ groups: ["createFolder"], forbidUnknownValues: false });
		} catch (validationErrors) {
			console.log(validationErrors);
			this.setState({
				validationError: validationErrors as ValidationError[],
			});
			return;
		}

		try {
			const newOfficeFolder = await Folders.getInstance().post(officeFolderForm);
			if (!newOfficeFolder) return;
			this.props.router.push(`/folders/${newOfficeFolder.uid}`);
		} catch (backError: any) {
			if(backError.target && backError.property){
				
				this.setState({
					validationError: backError as ValidationError[],
				});
			}else{
				console.error(backError);
				this.setState({
					validationError: [{
						constraints: {
							unique: "Le numéro de dossier est déjà utilisé"
						},
						property: "folder_number",
					} as ValidationError],
				});
			}
		}
	}

	private isFormSubmittable(): boolean {
		if (
			this.state.formValues.entitled === "" ||
			this.state.formValues.personal_note === "" ||
			this.state.formValues.folder_number === "" ||
			this.state.formValues.act_typ === null
		) {
			return false;
		}

		if (this.state.folder_access === "select_collaborators" && this.state.formValues.collaborators.length === 0) {
			return false;
		}

		return true;
	}

	private radioOnChange(e: React.ChangeEvent<HTMLInputElement>) {
		this.setState({
			folder_access: e.target.value,
		});
	}

	private getStakeholders() {
		let collaborators: User[] = this.state.collaborators;

		let office_folder_has_stakeholders = collaborators.map((collaborator) => {
			return OfficeFolderHasStakeholder.hydrate<OfficeFolderHasStakeholder>({
				user_stakeholder: collaborator,
			});
		});

		if (this.state.folder_access === "select_collaborators") {
			office_folder_has_stakeholders = office_folder_has_stakeholders.filter((collaborator) => {
				return this.state.formValues.collaborators?.some((selectedCollaborator) => {
					return selectedCollaborator.value === collaborator.user_stakeholder.uid;
				});
			});
		}
		return office_folder_has_stakeholders;
	}
}

export default function CreateFolder(props: IProps): JSX.Element {
	const router = useRouter();
	return <CreateFolderClass {...props} router={router} />;
}
