import React, {useId, useRef, useState} from "react";
import {toast} from "react-toastify";
import * as XLSX from "xlsx";
import {useTranslation} from "react-i18next";

const parseValue = (value, type) => {
    if (value === undefined || value === null)
        return null;

    switch (type) {
        case 'Integer':
            if (value === '')
                return null;
            const parsedInt = parseInt(value, 10);
            return isNaN(parsedInt) ? null : parsedInt;
        case 'Boolean':
            if (typeof value === 'boolean')
                return value;
            if (typeof value === 'string') {
                const lowerValue = value.toLowerCase().trim();
                if (lowerValue === 'oui' || lowerValue === 'true' || lowerValue === '1' || lowerValue === 'x') {
                    return true;
                } else if (lowerValue === 'non' || lowerValue === 'false' || lowerValue === '0' || lowerValue === '') {
                    return false;
                }
            }
            return null;
        case 'Date':
            if (value === '')
                return null;
            if (typeof value === 'string') {
                const date = new Date(value);
                return isNaN(date.getTime()) ? null : date;
            }
            return null;
        case 'String':
        default:
            return String(value);
    }
};

export function FileImport({onDataMapped, expectedFields, textButton}) {
    const id = useId();
    const [headerLineNumber, setHeaderLineNumber] = useState(1);
    const [fileData, setFileData] = useState([]);
    const [fileHeaders, setFileHeaders] = useState([]);
    const [fileName, setFileName] = useState('');
    const [selectedFile, setSelectedFile] = useState(null);
    const [columnMappings, setColumnMappings] = useState({});
    const fileChooser = useRef(null);
    const openMappingModal = useRef(null);
    const closeMappingModal = useRef(null);
    const openHeaderLineModal = useRef(null);
    const {t} = useTranslation();


    // Fonction pour trouver la meilleure correspondance
    const findBestMatch = (fileHeaders, expectedField) => {
        const fieldLabel = expectedField.label.toLowerCase();
        const fieldKey = expectedField.key.toLowerCase();

        // Variantes possibles pour chaque champ (ex: "Nom" peut être "nom", "Nom de famille", etc.)
        const variants = {
            licence: t('fileImport.variants.licence', {returnObjects: true}),
            pays: t('fileImport.variants.pays', {returnObjects: true}),
            nom: t('fileImport.variants.nom', {returnObjects: true}),
            prenom: t('fileImport.variants.prenom', {returnObjects: true}),
            genre: t('fileImport.variants.genre', {returnObjects: true}),
            weight: t('fileImport.variants.weight', {returnObjects: true}),
            categorie: t('fileImport.variants.categorie', {returnObjects: true}),
            overCategory: t('fileImport.variants.overCategory', {returnObjects: true}),
            club: t('fileImport.variants.club', {returnObjects: true}),
        };

        // Recherche de la meilleure correspondance
        for (const header of fileHeaders) {
            const lowerHeader = header.toLowerCase();
            if (lowerHeader === fieldLabel || lowerHeader === fieldKey || (variants[fieldKey] && variants[fieldKey].includes(lowerHeader))) {
                return header;
            }
        }

        // Aucune correspondance trouvée
        return null;
    };

    // Gestion du fichier sélectionné
    const handleFileChange = (e) => {
        const file = e.target.files[0];
        if (!file) return;

        setSelectedFile(file);
        setFileName(file.name);
        openHeaderLineModal.current.click();
    };

    // Valider le numéro de la ligne d'en-tête et lire le fichier
    const handleHeaderLineSubmit = () => {
        if (!selectedFile) return;

        const reader = new FileReader();
        reader.onload = (event) => {
            const data = event.target.result;
            const workbook = XLSX.read(data, {type: 'binary'});
            const sheetName = workbook.SheetNames[0];
            const sheet = workbook.Sheets[sheetName];
            const jsonData = XLSX.utils.sheet_to_json(sheet, {header: 1});

            // Extraire les en-têtes et les données en fonction du numéro de ligne
            const headers = jsonData[headerLineNumber - 1];
            const rows = jsonData.slice(headerLineNumber);
            setFileHeaders(headers);
            setFileData(rows);

            // Initialiser le mapping avec pré-remplissage intelligent
            const initialMappings = {};
            expectedFields.forEach(field => {
                const bestMatch = findBestMatch(headers, field);
                initialMappings[field.key] = bestMatch || '';
            });
            setColumnMappings(initialMappings);

            openMappingModal.current.click();
            fileChooser.current.value = '';
        };
        reader.readAsBinaryString(selectedFile);
    };

    // Mettre à jour le mapping d'une colonne
    const handleMappingChange = (fieldKey, header) => {
        setColumnMappings({
            ...columnMappings,
            [fieldKey]: header,
        });
    };

    // Valider le mapping et envoyer les données
    const handleSubmit = () => {
        // Vérifier que tous les champs requis sont mappés
        const missingMappings = expectedFields
            .filter(field => field.mandatory && !columnMappings[field.key])
            .map(field => field.label);

        if (missingMappings.length > 0) {
            toast.error(`${t('veuillezMapperLesColonnesSuivantes')} : ${missingMappings.join(', ')}`);
            return;
        }

        // Préparer les données mappées et parsées
        const mappedData = fileData.map(row => {
            const mappedRow = {};
            expectedFields.forEach(field => {
                const headerIndex = fileHeaders.indexOf(columnMappings[field.key]);
                const rawValue = headerIndex !== -1 ? row[headerIndex] : '';
                mappedRow[field.key] = parseValue(rawValue, field.type);
            });
            return mappedRow;
        });

        // Envoyer les données au parent ou au backend
        onDataMapped(mappedData);
        closeMappingModal.current.click();
    };

    const handleFileChooser = () => {
        fileChooser.current.click();
    }

    return <div>
        <button type="button" className="btn btn-primary" onClick={handleFileChooser}>{textButton}</button>

        <input ref={fileChooser} type="file" accept=".xlsx, .xls, .csv" onChange={handleFileChange} hidden={true}/>
        <button ref={openMappingModal} type="button" className="btn btn-primary" data-bs-toggle="modal" data-bs-target={"#mappingModal" + id}
                hidden={true}>A
        </button>
        <button ref={openHeaderLineModal} type="button" className="btn btn-primary" data-bs-toggle="modal"
                data-bs-target={"#headerLineModal" + id} hidden={true}>B
        </button>

        <div className="modal fade" id={"mappingModal" + id} tabIndex="-1" aria-labelledby="mappingModalLabel" aria-hidden="true">
            <div className="modal-dialog  modal-dialog-scrollable modal-lg modal-fullscreen-lg-down">
                <div className="modal-content">
                    <div className="modal-header">
                        <h1 className="modal-title fs-5" id="mappingModalLabel">{t('importationDuFichier')} {fileName}</h1>
                        <button ref={closeMappingModal} type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div className="modal-body">
                        <p>{t('veuillezAssocierChaqueChampàUneColonneDuFichier')} :</p>
                        <table className="table">
                            <thead>
                            <tr>
                                <th scope="col">{t('champAttendu')}</th>
                                <th scope="col">{t('colonneDansLeFichier')}</th>
                            </tr>
                            </thead>
                            <tbody>
                            {expectedFields.map(field => <tr key={field.key}>
                                <td>{field.label}</td>
                                <td>
                                    <select className="form-select" value={columnMappings[field.key]}
                                            onChange={(e) => handleMappingChange(field.key, e.target.value)}>
                                        <option value="">{t('sélectionner...')}</option>
                                        {fileHeaders.map(header => (<option key={header} value={header}>{header}</option>))}
                                    </select>
                                </td>
                            </tr>)}
                            </tbody>
                        </table>
                    </div>
                    <div className="modal-footer">
                        <button type="button" className="btn btn-secondary" data-bs-dismiss="modal">{t('button.annuler')}</button>
                        <button type="button" className="btn btn-primary" onClick={handleSubmit}>{t('button.confirmer')}</button>
                    </div>
                </div>
            </div>
        </div>

        <div className="modal fade" id={"headerLineModal" + id} tabIndex="-1" aria-labelledby="headerLineModalLabel" aria-hidden="true">
            <div className="modal-dialog  modal-dialog-scrollable">
                <div className="modal-content">
                    <div className="modal-header">
                        <h1 className="modal-title fs-5" id="headerLineModalLabel">{t('numéroDeLaLigneDentête')}</h1>
                        <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div className="modal-body">
                        <p>{t('veuillezIndiqueràQuelle')} :</p>
                        <div className="input-group mb-3">
                            <span className="input-group-text" id={id + "basic-addon1"}>{t('numéroDeLigne')}</span>
                            <input type="number" className="form-control" aria-describedby={id + "basic-addon1"} min="1" value={headerLineNumber}
                                   onChange={(e) => setHeaderLineNumber(parseInt(e.target.value) || 1)}/>
                        </div>
                    </div>
                    <div className="modal-footer">
                        <button type="button" className="btn btn-secondary" data-bs-dismiss="modal">{t('button.annuler')}</button>
                        <button type="button" className="btn btn-primary" onClick={handleHeaderLineSubmit}>{t('button.confirmer')}</button>
                    </div>
                </div>
            </div>
        </div>
    </div>
}
