import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import DragAndDrop from "@Front/Components/DesignSystem/DragAndDrop";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import Module from "@Front/Config/Module";
import PdfService from "@Front/Services/PdfService";
import { FileBlob } from "@Front/Api/Entities/types";
import { ShieldCheckIcon } from "@heroicons/react/24/outline";
import { useRouter } from "next/router";
import React, { useState } from "react";
import MessageBus from "src/sdk/MessageBus";

import classes from "./classes.module.scss";
import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService";
import FileService from "src/common/Api/LeCoffreApi/sdk/FileService";

type IProps = {
	folderUid: string;
};

/**
 * Convert a File object to FileBlob
 * @param file - The File object to convert
 * @returns Promise<FileBlob> - The converted FileBlob
 */
const convertFileToFileBlob = async (file: File): Promise<FileBlob> => {
	return new Promise((resolve, reject) => {
		const reader = new FileReader();
		reader.onload = () => {
			const arrayBuffer = reader.result as ArrayBuffer;
			const uint8Array = new Uint8Array(arrayBuffer);
			resolve({
				type: file.type,
				data: uint8Array
			});
		};
		reader.onerror = () => reject(new Error('Failed to read file'));
		reader.readAsArrayBuffer(file);
	});
};



export default function DocumentVerification(props: IProps) {
	const { folderUid } = props;
	const router = useRouter();
	
	const [documentToVerify, setDocumentToVerify] = useState<File | null>(null);
	const [validationCertificate, setValidationCertificate] = useState<File | null>(null);
	const [isVerifying, setIsVerifying] = useState(false);
	const [verificationResult, setVerificationResult] = useState<{
		success: boolean;
		message: string;
		details?: string;
		merkleProof?: string;
	} | null>(null);

	const handleDocumentToVerifyChange = (files: File[]) => {
		if (files.length > 0 && files[0]) {
			setDocumentToVerify(files[0]);
		} else {
			setDocumentToVerify(null);
		}
	};

	const handleValidationCertificateChange = (files: File[]) => {
		if (files.length > 0 && files[0]) {
			setValidationCertificate(files[0]);
		} else {
			setValidationCertificate(null);
		}
	};

	const handleVerifyDocuments = async () => {
		if (!documentToVerify || !validationCertificate) {
			console.error("Both documents are required for verification");
			return;
		}

		setIsVerifying(true);
		setVerificationResult(null);

		const messageBus = MessageBus.getInstance();
		
		try {
			// Here the things we need to verify:
			// - we can produce the same hash from the document provided than what is in the validation certificate
			// - the merkle proof is valid with that hash
			// - the root of the merkle tree is a state id from a commited state in the process
			// - that process is a file process linked to the right folder
			// Step 1: Parse the validation certificate
			const validationData = await PdfService.getInstance().parseCertificate(validationCertificate);

			// Step 2: Convert File to FileBlob and hash the document using MessageBus
			const fileBlob = await convertFileToFileBlob(documentToVerify);

			await messageBus.isReady();
			const documentHash = await messageBus.hashDocument(fileBlob, validationData.commitmentId);	
			
			// Step 3: Compare hashes
			const hashesMatch = documentHash.toLowerCase() === validationData.documentHash.toLowerCase();

			if (!hashesMatch) {
				throw new Error('Hash du document invalide, le document fourni n\'est pas celui qui a été certifié');
			}

			// Step 4: Verify the merkle proof
			const merkleProof = validationData.merkleProof;
			const merkleProofValid = await messageBus.verifyMerkleProof(merkleProof, documentHash);

			if (!merkleProofValid) {
				throw new Error('Preuve de Merkle invalide, le document n\'a pas été certifié là où le certificat le prétend');
			}

			// Step 5: Verify that this file process depends on the right folder process
			// First pin all the validated documents related to the folder
			const documentProcesses = await DocumentService.getDocuments();

			const documents = documentProcesses.filter((process: any) => 
				process.processData.document_status === "VALIDATED" && 
				process.processData.folder.uid === folderUid
			);

			if (!documents || documents.length === 0) {
				throw new Error(`Aucune demande de document trouvé pour le dossier ${folderUid}`);
			}

			// Step 6: verify that the merkle proof match the last commited state for the file process
			const stateId = JSON.parse(validationData.merkleProof)['root'];

			let stateIdExists = false;
			for (const doc of documents) {
				const processData = doc.processData;

				for (const file of processData.files) {
					const fileUid = file.uid;
					const fileProcess = await FileService.getFileByUid(fileUid);	
					const lastUpdatedStateId = fileProcess.lastUpdatedFileState.state_id;

					stateIdExists = lastUpdatedStateId === stateId; // we assume that last state is the validated document, that seems reasonable
					if (stateIdExists) break;
				}

				if (stateIdExists) break;
			}

			if (!stateIdExists) {
				throw new Error('La preuve fournie ne correspond à aucun document demandé pour ce dossier.');
			}	

			setVerificationResult({
				success: true,
				message: "✅ Vérification réussie ! Le document est authentique et intègre.",
			});	
		} catch (error) {
			console.error("Verification failed:", error);
			setVerificationResult({
				success: false,
				message: `❌ Erreur lors de la vérification: ${error}`,
			});
		} finally {
			setIsVerifying(false);
		}
	};

	const handleBackToFolder = () => {
		const folderPath = Module.getInstance()
			.get()
			.modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folderUid);
		router.push(folderPath);
	};

	const bothDocumentsPresent = documentToVerify && validationCertificate;

	return (
		<div className={classes["root"]}>
			<div className={classes["header"]}>
				<Typography typo={ETypo.TITLE_H2} color={ETypoColor.TEXT_PRIMARY}>
					Vérification de Documents
				</Typography>
				<Typography typo={ETypo.TEXT_LG_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
					Vérifiez l'intégrité et l'authenticité de vos documents
				</Typography>
			</div>

			<div className={classes["content"]}>
				<div className={classes["drag-drop-container"]}>
					<div className={classes["drag-drop-box"]}>
						<DragAndDrop
							title="Document à valider"
							description="Glissez-déposez ou cliquez pour sélectionner le document que vous souhaitez vérifier"
							onChange={handleDocumentToVerifyChange}
						/>
						{documentToVerify && (
							<div className={classes["file-info"]}>
								<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.COLOR_SUCCESS_500}>
									✓ {documentToVerify.name}
								</Typography>
							</div>
						)}
					</div>

					<div className={classes["drag-drop-box"]}>
						<DragAndDrop
							title="Certificat de validation"
							description="Glissez-déposez ou cliquez pour sélectionner le certificat de validation correspondant"
							onChange={handleValidationCertificateChange}
						/>
						{validationCertificate && (
							<div className={classes["file-info"]}>
								<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.COLOR_SUCCESS_500}>
									✓ {validationCertificate.name}
								</Typography>
							</div>
						)}
					</div>
				</div>

				{!bothDocumentsPresent && (
					<div className={classes["warning"]}>
						<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_WARNING_500}>
							⚠️ Veuillez sélectionner les deux documents pour procéder à la vérification
						</Typography>
					</div>
				)}

				{verificationResult && (
					<div className={`${classes["verification-result"]} ${classes[verificationResult.success ? "success" : "error"]}`}>
						<Typography typo={ETypo.TEXT_LG_REGULAR} color={verificationResult.success ? ETypoColor.COLOR_SUCCESS_500 : ETypoColor.COLOR_ERROR_500}>
							{verificationResult.message}
						</Typography>
					</div>
				)}

				<div className={classes["actions"]}>
					<Button
						variant={EButtonVariant.SECONDARY}
						styletype={EButtonstyletype.TEXT}
						size={EButtonSize.LG}
						onClick={handleBackToFolder}
						disabled={isVerifying}
					>
						Retour au dossier
					</Button>
					
					<Button
						variant={EButtonVariant.PRIMARY}
						styletype={EButtonstyletype.CONTAINED}
						size={EButtonSize.LG}
						onClick={handleVerifyDocuments}
						rightIcon={<ShieldCheckIcon />}
						disabled={!bothDocumentsPresent || isVerifying}
						isLoading={isVerifying}
					>
						{isVerifying ? "Vérification en cours..." : "Vérifier les documents"}
					</Button>
				</div>
			</div>
		</div>
	);
} 