import ChevronIcon from "@Assets/Icons/chevron.svg";
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
import OfficeFolderAnchors from "@Front/Api/LeCoffreApi/Notary/OfficeFolderAnchors/OfficeFolderAnchors";
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import FolderBoxInformation, { EFolderBoxInformationType } from "@Front/Components/DesignSystem/FolderBoxInformation";
import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField";
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
import QuantityProgressBar from "@Front/Components/DesignSystem/QuantityProgressBar";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard";
import Module from "@Front/Config/Module";
import { OfficeFolder } from "le-coffre-resources/dist/Notary";
import { EDocumentStatus } from "le-coffre-resources/dist/Notary/Document";
import Link from "next/link";
import { NextRouter, useRouter } from "next/router";
import { ChangeEvent, useCallback, useEffect, useState } from "react";
import Image from "next/image";
import ValidateAnchoringGif from "@Front/Assets/images/validate_anchoring.gif";

import BasePage from "../../Base";
import classes from "./classes.module.scss";
import ClientSection from "./ClientSection";
import Loader from "@Front/Components/DesignSystem/Loader";
import Newsletter from "@Front/Components/DesignSystem/Newsletter";

export enum AnchorStatus {
	"VERIFIED_ON_CHAIN" = "VERIFIED_ON_CHAIN",
	"ANCHORING" = "ANCHORING",
	"NOT_ANCHORED" = "NOT_ANCHORED",
}

type IProps = {};

type IPropsClass = IProps & {
	router: NextRouter;
	selectedFolderUid: string;
	isAnchored: AnchorStatus;
	isLoading: boolean;
	selectedFolder: OfficeFolder | null;
	getAnchoringStatus: () => Promise<void>;
	getFolderCallback: () => Promise<void>;
	openedCustomer?: string;
};

type IState = {
	isArchivedModalOpen: boolean;
	inputArchivedDescripton: string;
	isValidateModalVisible: boolean;
	hasValidateAnchoring: boolean;
	isVerifDeleteModalVisible: boolean;
	isPreventArchiveModalOpen: boolean;
	loadingAnchoring: boolean;
};
class FolderInformationClass extends BasePage<IPropsClass, IState> {
	public constructor(props: IPropsClass) {
		super(props);
		this.state = {
			isArchivedModalOpen: false,
			inputArchivedDescripton: "",
			isValidateModalVisible: false,
			hasValidateAnchoring: false,
			isVerifDeleteModalVisible: false,
			isPreventArchiveModalOpen: false,
			loadingAnchoring: false,
		};
		this.openArchivedModal = this.openArchivedModal.bind(this);
		this.closeArchivedModal = this.closeArchivedModal.bind(this);
		this.onArchivedModalAccepted = this.onArchivedModalAccepted.bind(this);
		this.onPreventArchiveModalAccepted = this.onPreventArchiveModalAccepted.bind(this);
		this.getCompletionNumber = this.getCompletionNumber.bind(this);
		this.onArchivedDescriptionInputChange = this.onArchivedDescriptionInputChange.bind(this);
		this.deleteFolder = this.deleteFolder.bind(this);
		this.closeModal = this.closeModal.bind(this);
		this.validateAnchoring = this.validateAnchoring.bind(this);
		this.openValidateModal = this.openValidateModal.bind(this);
		this.openVerifDeleteFolder = this.openVerifDeleteFolder.bind(this);
		this.closeVerifDeleteFolder = this.closeVerifDeleteFolder.bind(this);
		this.closePreventArchiveModal = this.closePreventArchiveModal.bind(this);
	}

	// TODO: Message if the user has not created any folder yet
	// TODO: get the selected folder from the api in componentDidMount
	public override render(): JSX.Element {
		const redirectPathEditCollaborators = Module.getInstance()
			.get()
			.modules.pages.Folder.pages.EditCollaborators.props.path.replace("[folderUid]", this.props.selectedFolderUid);
		return (
			<DefaultNotaryDashboard title={"Dossier"} isArchived={false} mobileBackText="Retour aux dossiers">
				{!this.props.isLoading && (
					<div className={classes["root"]}>
						{this.props.selectedFolder ? (
							<div className={classes["folder-informations"]}>
								<div className={classes["folder-header"]}>
									<div className={classes["header"]}>
										<div className={classes["title"]}>
											<Typography typo={ETypo.TITLE_H1}>Informations du dossier</Typography>
										</div>
										<Link href={redirectPathEditCollaborators}>
											<Button
												variant={EButtonVariant.PRIMARY}
												styletype={EButtonstyletype.TEXT}
												rightIcon={<ChevronIcon />}>
												Modifier les collaborateurs
											</Button>
										</Link>
									</div>
									<FolderBoxInformation
										anchorStatus={this.props.isAnchored}
										folder={this.props.selectedFolder}
										type={EFolderBoxInformationType.INFORMATIONS}
									/>
									<div className={classes["second-box"]}>
										<FolderBoxInformation
											anchorStatus={this.props.isAnchored}
											folder={this.props.selectedFolder}
											type={EFolderBoxInformationType.DESCRIPTION}
										/>
									</div>
									<div className={classes["progress-bar"]}>
										<QuantityProgressBar
											title="Complétion du dossier"
											total={100}
											currentNumber={this.getCompletionNumber()}
										/>
									</div>
									{this.doesFolderHaveCustomer() && (
										<ClientSection
											folder={this.props.selectedFolder}
											anchorStatus={this.props.isAnchored}
											getFolderCallback={this.props.getFolderCallback}
											openedCustomer={this.props.openedCustomer}
										/>
									)}
								</div>

								{!this.doesFolderHaveCustomer() && (
									<ClientSection
										folder={this.props.selectedFolder}
										anchorStatus={this.props.isAnchored}
										getFolderCallback={this.props.getFolderCallback}
										openedCustomer={this.props.openedCustomer}
									/>
								)}

								<div className={classes["button-container"]}>
									<Button
										variant={EButtonVariant.PRIMARY}
										styletype={EButtonstyletype.OUTLINED}
										onClick={this.openArchivedModal}>
										Archiver le dossier
									</Button>
									{this.everyDocumentValidated() && !this.props.isLoading && (
										<>
											{this.props.isAnchored === AnchorStatus.NOT_ANCHORED && (
												<Button variant={EButtonVariant.PRIMARY} onClick={this.openValidateModal}>
													Valider et ancrer
												</Button>
											)}
											{this.props.isAnchored === AnchorStatus.ANCHORING && (
												<Button variant={EButtonVariant.PRIMARY} disabled>
													Demande d'ancrage envoyée...&nbsp;&nbsp;
													<div className={classes["loader-container"]}>
														<div className={classes["loader"]}>
															<Loader />
														</div>
													</div>
												</Button>
											)}
											{this.props.isAnchored === AnchorStatus.VERIFIED_ON_CHAIN && (
												<Button
													variant={EButtonVariant.PRIMARY}
													onClick={() => this.downloadAnchoringProof(this.props.selectedFolder?.uid)}
													disabled={this.state.loadingAnchoring}>
													Télécharger la preuve d'ancrage
													{this.state.loadingAnchoring && (
														<div className={classes["loader-container"]}>
															<div className={classes["loader"]}>
																<Loader />
															</div>
														</div>
													)}
												</Button>
											)}
										</>
									)}
									{this.canDeleteFolder() && (
										<span className={classes["delete-folder"]} onClick={this.openVerifDeleteFolder}>
											<Button variant={EButtonVariant.SECONDARY}>Supprimer le dossier</Button>
										</span>
									)}
								</div>
								<Confirm
									isOpen={this.state.isArchivedModalOpen}
									onAccept={this.onArchivedModalAccepted}
									onClose={this.closeArchivedModal}
									closeBtn
									header={"Archiver le dossier ?"}
									cancelText={"Annuler"}
									confirmText={"Archiver"}>
									<div className={classes["modal-title"]}>
										<Typography typo={ETypo.TEXT_MD_REGULAR}>Souhaitez-vous vraiment archiver le dossier ?</Typography>
									</div>
									<TextAreaField
										name="archived_description"
										placeholder="Description"
										onChange={this.onArchivedDescriptionInputChange}
									/>
								</Confirm>
								<Confirm
									isOpen={this.state.isPreventArchiveModalOpen}
									onAccept={this.onPreventArchiveModalAccepted}
									onClose={this.closePreventArchiveModal}
									closeBtn
									header={"Archiver le dossier"}
									cancelText={"Annuler"}
									confirmText={"Archiver"}>
									<div className={classes["modal-title"]}>
										<Typography typo={ETypo.TEXT_MD_REGULAR}>
											Vous êtes en train d’archiver le dossier sans avoir l’ancré, êtes-vous sûr de vouloir le faire ?
										</Typography>
									</div>
									<TextAreaField
										name="archived_description"
										placeholder="Description"
										onChange={this.onArchivedDescriptionInputChange}
									/>
								</Confirm>
								<Confirm
									isOpen={this.state.isVerifDeleteModalVisible}
									onAccept={this.deleteFolder}
									onClose={this.closeVerifDeleteFolder}
									closeBtn
									header={"Êtes-vous sûr de vouloir supprimer ce dossier ?"}
									cancelText={"Annuler"}
									confirmText={"Confirmer"}>
									<div className={classes["modal-title"]}>
										<Typography typo={ETypo.TEXT_MD_REGULAR}>Cette action sera irréversible.</Typography>
									</div>
								</Confirm>
								<Newsletter isOpen={false} />
							</div>
						) : (
							<div className={classes["no-folder-selected"]}>
								<Typography typo={ETypo.TITLE_H1}>Informations du dossier</Typography>
								<div className={classes["choose-a-folder"]}>
									<Typography typo={ETypo.TEXT_LG_REGULAR} color={ETypoColor.COLOR_NEUTRAL_500}>
										Sélectionnez un dossier
									</Typography>
								</div>
							</div>
						)}
					</div>
				)}
				{this.props.isLoading && (
					<div className={classes["loader-container"]}>
						<div className={classes["loader"]}>
							<Loader />
						</div>
					</div>
				)}
				<Confirm
					isOpen={this.state.isValidateModalVisible}
					onClose={this.closeModal}
					onAccept={this.validateAnchoring}
					closeBtn={true}
					hasContainerClosable={true}
					header={
						this.state.hasValidateAnchoring
							? "Dossier en cours de certification"
							: "Êtes-vous sûr de vouloir ancrer et certifier ce dossier ?"
					}
					cancelText={"Annuler"}
					confirmText={"Confirmer"}
					showButtons={!this.state.hasValidateAnchoring}>
					<div className={classes["validate-document-container"]}>
						{!this.state.hasValidateAnchoring && (
							<Typography
								typo={ETypo.TEXT_MD_REGULAR}
								color={ETypoColor.COLOR_GENERIC_BLACK}
								className={classes["validate-text"]}>
								Les documents du dossier seront certifiés sur la blockchain. Pensez à bien télécharger l'ensemble des
								documents du dossier ainsi que le fichier de preuve d'ancrage pour les mettre dans la GED de votre logiciel
								de rédaction d'actes.
							</Typography>
						)}
						{this.state.hasValidateAnchoring && (
							<div className={classes["document-validating-container"]}>
								<Typography
									typo={ETypo.TEXT_MD_REGULAR}
									color={ETypoColor.COLOR_GENERIC_BLACK}
									className={classes["validate-text"]}>
									Veuillez revenir sur le dossier dans 5 minutes et rafraîchir la page pour télécharger le dossier de
									preuve d'ancrage et le glisser dans la GED de votre logiciel de rédaction d'acte.
								</Typography>
								<Image src={ValidateAnchoringGif} alt="Anchoring animation" className={classes["validate-gif"]} />
							</div>
						)}
					</div>
				</Confirm>
			</DefaultNotaryDashboard>
		);
	}

	private closePreventArchiveModal() {
		this.setState({
			isPreventArchiveModalOpen: false,
		});
	}

	public openVerifDeleteFolder() {
		this.setState({
			isVerifDeleteModalVisible: true,
		});
	}

	public closeVerifDeleteFolder() {
		this.setState({
			isVerifDeleteModalVisible: false,
		});
	}

	private closeModal() {
		this.setState({
			isValidateModalVisible: false,
		});
	}

	private openValidateModal() {
		this.setState({
			isValidateModalVisible: true,
		});
	}

	private async validateAnchoring() {
		this.setState({
			hasValidateAnchoring: true,
		});

		try {
			const timeoutDelay = 9800;
			await this.anchorFolder();
			setTimeout(() => {
				this.setState({
					isValidateModalVisible: false,
				});
			}, timeoutDelay);

			setTimeout(() => {
				this.setState({
					hasValidateAnchoring: false,
				});
			}, timeoutDelay + 1000);
		} catch (e) {
			this.setState({
				isValidateModalVisible: false,
				hasValidateAnchoring: false,
			});
			console.error(e);
		}
	}

	private async anchorFolder() {
		if (!this.props.selectedFolder?.uid) return;
		await OfficeFolderAnchors.getInstance().post(this.props.selectedFolder.uid);
		this.props.getAnchoringStatus();
	}

	private async downloadAnchoringProof(uid?: string) {
		if (!uid) return;
		this.setState({ loadingAnchoring: true });
		try {
			const file: Blob = await OfficeFolderAnchors.getInstance().download(uid);
			const url = window.URL.createObjectURL(file);
			const a = document.createElement("a");
			a.style.display = "none";
			a.href = url;
			// the filename you want
			a.download = `anchoring_proof_${this.props.selectedFolder?.folder_number}_${this.props.selectedFolder?.name}.zip`;
			document.body.appendChild(a);
			a.click();
			window.URL.revokeObjectURL(url);
			this.setState({ loadingAnchoring: false });
		} catch (e) {
			this.setState({ loadingAnchoring: false });
			console.error(e);
		}
	}

	private everyDocumentValidated(): boolean {
		if (!this.props.selectedFolder?.documents) return false;
		return (
			this.props.selectedFolder?.documents?.length >= 1 &&
			this.props.selectedFolder?.documents.every((document) => document.document_status === EDocumentStatus.VALIDATED)
		);
	}

	private async deleteFolder() {
		if (!this.props.selectedFolder?.uid) return;
		await Folders.getInstance().delete(this.props.selectedFolder.uid);
		this.props.router.push(Module.getInstance().get().modules.pages.Folder.props.path);
	}

	private getCompletionNumber() {
		const documents = this.props.selectedFolder?.documents;
		if (!documents) return 0;
		const totalDocuments = documents.length;
		const refusedDocuments = documents.filter((document) => document.document_status === EDocumentStatus.REFUSED).length ?? 0;
		const askedDocuments =
			documents.filter(
				(document) => document.document_status === EDocumentStatus.ASKED || document.document_status === EDocumentStatus.DEPOSITED,
			).length ?? 0;
		const depositedDocuments = totalDocuments - askedDocuments - refusedDocuments;
		const percentage = (depositedDocuments / totalDocuments) * 100;
		return isNaN(percentage) ? 0 : percentage;
	}

	private doesFolderHaveCustomer(): boolean {
		if (!this.props.selectedFolder?.customers) return false;
		return this.props.selectedFolder?.customers!.length > 0;
	}

	private canDeleteFolder(): boolean {
		return (this.props.selectedFolder?.customers?.length ?? 0) === 0 && (this.props.selectedFolder?.documents?.length ?? 0) === 0;
	}

	private openArchivedModal(): void {
		if (this.everyDocumentValidated() && this.props.isAnchored === AnchorStatus.VERIFIED_ON_CHAIN) {
			this.setState({ isArchivedModalOpen: true });
		} else {
			this.setState({ isPreventArchiveModalOpen: true });
		}
	}

	private closeArchivedModal(): void {
		this.setState({ isArchivedModalOpen: false });
	}

	private onArchivedDescriptionInputChange(e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) {
		this.setState({ inputArchivedDescripton: e.target.value });
	}

	private async onArchivedModalAccepted() {
		if (!this.props.selectedFolder) return;
		await Folders.getInstance().archive(this.props.selectedFolder.uid ?? "", this.state.inputArchivedDescripton);
		this.closeArchivedModal();
		this.props.router.push(Module.getInstance().get().modules.pages.Folder.props.path);
	}

	private async onPreventArchiveModalAccepted() {
		if (!this.props.selectedFolder) return;
		await Folders.getInstance().archive(this.props.selectedFolder.uid ?? "", this.state.inputArchivedDescripton);
		this.closePreventArchiveModal();
		this.props.router.push(Module.getInstance().get().modules.pages.Folder.props.path);
	}
}

export default function FolderInformation(props: IProps) {
	const router = useRouter();
	const [isAnchored, setIsAnchored] = useState<AnchorStatus>(AnchorStatus.NOT_ANCHORED);
	const [isLoading, setIsLoading] = useState<boolean>(true);
	const [selectedFolder, setSelectedFolder] = useState<OfficeFolder | null>(null);

	let { folderUid } = router.query;
	const customerUid = router.query["customerUid"] as string | undefined;
	folderUid = folderUid as string;

	const getAnchoringStatus = useCallback(async () => {
		if (!folderUid) return;
		try {
			const anchorStatus = await OfficeFolderAnchors.getInstance().getByUid(folderUid as string);
			setIsAnchored(anchorStatus.status === "VERIFIED_ON_CHAIN" ? AnchorStatus.VERIFIED_ON_CHAIN : AnchorStatus.ANCHORING);
		} catch (e) {
			setIsAnchored(AnchorStatus.NOT_ANCHORED);
		}
	}, [folderUid]);

	const getFolder = useCallback(async () => {
		if (!folderUid) return;
		setIsLoading(true);
		const query = {
			q: {
				deed: { include: { deed_type: true } },
				office: true,
				customers: {
					include: {
						contact: true,
						documents: {
							include: {
								folder: true,
								document_type: true,
								files: true,
							},
						},
					},
				},
				documents: {
					include: {
						depositor: {
							include: {
								contact: true,
							},
						},
					},
				},
				folder_anchor: true,
				notes: {
					include: {
						customer: true,
					},
				},
			},
		};

		const folder = await Folders.getInstance().getByUid(folderUid as string, query);
		if (folder) {
			setSelectedFolder(folder);
			getAnchoringStatus();
		}

		setIsLoading(false);
	}, [folderUid, getAnchoringStatus]);

	useEffect(() => {
		setIsLoading(true);
		getFolder();
	}, [getFolder]);

	return (
		<FolderInformationClass
			{...props}
			selectedFolderUid={folderUid}
			router={router}
			isAnchored={isAnchored}
			isLoading={isLoading}
			selectedFolder={selectedFolder}
			getAnchoringStatus={getAnchoringStatus}
			getFolderCallback={getFolder}
			openedCustomer={customerUid}
		/>
	);
}
