import {useNavigate, useParams, useSearchParams} from "react-router-dom";
import {LoadingProvider, useLoadingSwitcher} from "../../hooks/useLoading.jsx";
import {useFetch} from "../../hooks/useFetch.js";
import {AxiosError} from "../../components/AxiosError.jsx";
import {ThreeDots} from "react-loader-spinner";
import {useEffect, useReducer, useRef, useState} from "react";
import {apiAxios, CatList, getCatName} from "../../utils/Tools.js";
import {toast} from "react-toastify";
import {SimpleReducer} from "../../utils/SimpleReducer.jsx";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faAdd, faGavel, faTrashCan} from "@fortawesome/free-solid-svg-icons";
import "./CompetitionRegisterAdmin.css"
import * as XLSX from "xlsx-js-style";
import {useCountries} from "../../hooks/useCountries.jsx";

export function CompetitionRegisterAdmin({source}) {
    const {id} = useParams()
    const navigate = useNavigate()
    const [state, dispatch] = useReducer(SimpleReducer, [])
    const [clubFilter, setClubFilter] = useState("")
    const [catFilter, setCatFilter] = useState("")
    const [modalState, setModalState] = useState({})

    const setLoading = useLoadingSwitcher()
    const {data, error} = useFetch(`/competition/${id}/register/${source}`, setLoading, 1)

    const sortName = (a, b) => {
        if (a.data.fname === b.data.fname) return a.data.lname.localeCompare(b.data.lname);
        return a.data.fname.localeCompare(b.data.fname);
    }

    useEffect(() => {
        if (!data) return;
        data.forEach((d) => {
            dispatch({type: 'UPDATE_OR_ADD', payload: {id: d.id, data: d}})
        })
        dispatch({type: 'SORT', payload: sortName})
    }, [data, clubFilter, catFilter]);

    const sendRegister = (new_state) => {
        toast.promise(apiAxios.post(`/competition/${id}/register/${source}`, new_state), {
            pending: "Recherche en cours", success: "Combattant trouvé et ajouté/mis à jour", error: {
                render({data}) {
                    return data.response.data || "Combattant non trouvé"
                }
            }
        }).then((response) => {
            if (response.data.error) {
                return
            }
            dispatch({type: 'UPDATE_OR_ADD', payload: {id: response.data.id, data: response.data}})
            dispatch({type: 'SORT', payload: sortName})
            document.getElementById("closeModal").click();
        })
    }

    return <div>
        <h2>Combattants inscrits</h2>
        <button type="button" className="btn btn-link"
                onClick={() => source === "admin" ? navigate("/competition/" + id) : navigate("/competition/" + id + "/view")}>
            &laquo; retour
        </button>

        <div className="row">
            <div className="col-lg-9">
                {data ? <div className="">
                    <MakeCentralPanel
                        data={state.filter(s => (clubFilter.length === 0 || s.data.club.name === clubFilter) && (catFilter.length === 0 || s.data.categorie === catFilter))}
                        dispatch={dispatch} id={id} setModalState={setModalState} source={source}/>
                </div> : error ? <AxiosError error={error}/> : <Def/>}
            </div>
            <div className="col-lg-3">
                <div className="mb-1">
                    <button type="button" className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#registerModal"
                            onClick={() => setModalState({id: 0})}>Ajouter un combattant
                    </button>
                </div>
                <div className="mb-4">
                    <button type="button" className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#registerModal"
                            onClick={() => setModalState({id: -793548328091516928})}>Ajouter un invité
                    </button>
                </div>
                <QuickAdd sendRegister={sendRegister} source={source}/>
                <div className="card mb-4">
                    <div className="card-header">Filtre</div>
                    <div className="card-body">
                        <FiltreBar data={data} clubFilter={clubFilter} setClubFilter={setClubFilter} catFilter={catFilter}
                                   setCatFilter={setCatFilter} source={source}/>
                    </div>
                </div>
                {source === "admin" && <FileOutput data={data}/>}
            </div>
        </div>

        <Modal sendRegister={sendRegister} modalState={modalState} setModalState={setModalState} source={source}/>
    </div>
}

function QuickAdd({sendRegister, source}) {

    const handleAdd = (licence) => {
        console.log("Quick add licence: " + licence)

        sendRegister({
            licence: licence, fname: "", lname: "", weight: "", overCategory: 0, lockEdit: false, id: null
        })
    }

    return <div className="card mb-4">
        <div className="card-header">Ajout rapide</div>
        <div className="card-body">
            <div className="row">
                <span>N° de licence</span>
            </div>
            <div className="input-group">
                <input type="text" className="form-control" placeholder="12345" id="quickAddLicence"
                       onKeyDown={e => {
                           if (e.key === "Enter") {
                               const licence = e.target.value.trim()
                               if (licence.length === 0) return;
                               e.target.value = ""
                               handleAdd(licence)
                           }
                       }}/>
                <button className="btn btn-primary" type="button" id="quickAddBtn"
                        onClick={_ => {
                            const licence = document.getElementById("quickAddLicence").value.trim()
                            if (licence.length === 0) return;

                            document.getElementById("quickAddLicence").value = ""
                            handleAdd(licence)
                        }}><FontAwesomeIcon icon={faAdd} className="no-modal"/>
                </button>

                {source === "club" && <LoadingProvider>
                    <SearchMember sendRegister={sendRegister}/>
                </LoadingProvider>}
            </div>
        </div>
    </div>
}

function SearchMember({sendRegister}) {
    const setLoading = useLoadingSwitcher()
    const {data, error} = useFetch(`/club/members`, setLoading, 1)
    const [suggestions, setSuggestions] = useState([])

    const handleAdd = (name) => {
        const member = data.find(m => `${m.fname} ${m.lname}`.trim() === name);
        console.log("Quick add licence:", member)

        if (!member) {
            toast.error("Combattant non trouvé");
            return;
        }

        sendRegister({
            licence: member.licence, fname: member.fname, lname: member.lname, weight: "", overCategory: 0, lockEdit: false, id: null
        })
    }

    useEffect(() => {
        if (!data) return;

        const names = data.map(member => `${member.fname} ${member.lname}`.trim());
        names.sort((a, b) => a.localeCompare(b));
        setSuggestions(names);
    }, []);

    return <>
        {data ? <div className="row mb-3" style={{marginTop: "0.5em"}}>
            <span>Prénom et nom</span>
            <AutoCompleteInput suggestions={suggestions} handleAdd={handleAdd}/>
        </div> : error ? <AxiosError error={error}/> : <Def/>}
    </>
}

const AutoCompleteInput = ({suggestions = [], handleAdd}) => {
    const [inputValue, setInputValue] = useState('');
    const [filteredSuggestions, setFilteredSuggestions] = useState([]);
    const [showSuggestions, setShowSuggestions] = useState(false);
    const [activeSuggestion, setActiveSuggestion] = useState(0);
    const wrapperRef = useRef(null);

    // Filtre les suggestions
    useEffect(() => {
        if (inputValue.trim() === '') {
            setFilteredSuggestions([]);
            setShowSuggestions(false);
        } else {
            const filtered = suggestions.filter(suggestion => suggestion.toLowerCase().includes(inputValue.toLowerCase()));
            setFilteredSuggestions(filtered);
            setShowSuggestions(true);
            setActiveSuggestion(0); // Réinitialise la sélection active
        }
    }, [inputValue, suggestions]);

    // Ferme les suggestions si clic à l'extérieur
    useEffect(() => {
        const handleClickOutside = (event) => {
            if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
                setShowSuggestions(false);
            }
        };
        document.addEventListener('mousedown', handleClickOutside);
        return () => document.removeEventListener('mousedown', handleClickOutside);
    }, []);

    // Gestion du clic sur une suggestion
    const handleSuggestionClick = (suggestion) => {
        setInputValue(suggestion);
        setShowSuggestions(false); // Ferme automatiquement après sélection
    };

    // Navigation clavier
    const handleKeyDown = (e) => {
        // Touches directionnelles
        if (e.key === 'ArrowDown') {
            e.preventDefault();
            setActiveSuggestion(prev => prev < filteredSuggestions.length - 1 ? prev + 1 : prev);
        } else if (e.key === 'ArrowUp') {
            e.preventDefault();
            setActiveSuggestion(prev => (prev > 0 ? prev - 1 : 0));
        }
        // Validation avec Entrée
        else if (e.key === 'Enter' && filteredSuggestions.length > 0) {
            e.preventDefault();
            if (inputValue === filteredSuggestions[activeSuggestion]) {
                handleAdd(inputValue);
                setInputValue('');
            } else {
                setInputValue(filteredSuggestions[activeSuggestion]);
            }
            setShowSuggestions(false);
        }
        // Fermeture avec Échap
        else if (e.key === 'Escape') {
            setShowSuggestions(false);
        }
    };

    return (<div className="autocomplete-wrapper" ref={wrapperRef}>
        <div className="input-group">
            <input
                type="text"
                className="form-control"
                value={inputValue}
                onChange={(e) => setInputValue(e.target.value)}
                onKeyDown={handleKeyDown}
                onFocus={() => inputValue && setShowSuggestions(true)}
                placeholder="Rechercher..."
                aria-autocomplete="list"
                aria-expanded={showSuggestions}
                aria-controls="suggestions-list"
            />

            <button className="btn btn-primary" type="button" id="quickAddBtn"
                    onClick={_ => {
                        handleAdd(inputValue);
                        setInputValue(''); // Réinitialise le champ après l'ajout
                    }}>
                <FontAwesomeIcon icon={faAdd} className="no-modal"/>
            </button>
        </div>
        {showSuggestions && filteredSuggestions.length > 0 && (<ul
            id="suggestions-list"
            className="suggestions-list list-group"
            role="listbox"
        >
            {filteredSuggestions.map((suggestion, index) => (<li
                key={index}
                className={`list-group-item list-group-item-action ${index === activeSuggestion ? 'active' : ''}`}
                onClick={() => handleSuggestionClick(suggestion)}
                role="option"
                aria-selected={index === activeSuggestion}
            >
                {suggestion}
            </li>))}
        </ul>)}
    </div>);
};

function Modal({sendRegister, modalState, setModalState, source}) {
    const country = useCountries('fr')

    const [licence, setLicence] = useState("")
    const [fname, setFname] = useState("")
    const [lname, setLname] = useState("")
    const [weight, setWeight] = useState("")
    const [cat, setCat] = useState(0)
    const [gcat, setGCat] = useState("")
    const [club, setClub] = useState("")
    const [country_, setCountry_] = useState("FR")
    const [genre, setGenre] = useState("NA")
    const [editMode, setEditMode] = useState(false)
    const [lockEdit, setLockEdit] = useState(false)

    useEffect(() => {
        console.log(modalState)
        if (!modalState) {
            setLicence("")
            setFname("")
            setLname("")
            setWeight("")
            setCat(0)
            setEditMode(false)
            setLockEdit(false)
            setClub("")
            setGCat("")
            setCountry_("FR")
            setGenre("NA")
        } else {
            setLicence(modalState.licence ? modalState.licence : "")
            setFname(modalState.fname ? modalState.fname : "")
            setLname(modalState.lname ? modalState.lname : "")
            setWeight(modalState.weight ? modalState.weight : "")
            setCat(modalState.overCategory ? modalState.overCategory : 0)
            setEditMode(modalState.licence || (modalState.fname && modalState.lname))
            setLockEdit(modalState.lockEdit)
            setClub(modalState.club ? modalState.club.name : "")
            setGCat(modalState.categorie ? modalState.categorie : "")
            setCountry_(modalState.country ? modalState.country : "FR")
            setGenre(modalState.genre ? modalState.genre : "NA")
        }
    }, [modalState]);

    return <div className="modal fade" id="registerModal" tabIndex="-1" aria-labelledby="registerLabel"
                aria-hidden="true">
        <div className="modal-dialog">
            <div className="modal-content">
                <form onSubmit={e => {
                    e.preventDefault()
                    const new_state = {
                        licence: licence,
                        fname: fname,
                        lname: lname,
                        weight: weight,
                        overCategory: cat,
                        lockEdit: lockEdit,
                        id: modalState.id !== 0 ? modalState.id : null
                    }
                    if (modalState.id < 0) {
                        new_state.licence = -1
                        new_state.categorie = gcat
                        new_state.club = club
                        new_state.country = country_
                        new_state.genre = genre
                    }
                    setModalState(new_state)
                    sendRegister(new_state)
                }}>
                    <div className="modal-header">
                        <h1 className="modal-title fs-5"
                            id="registerLabel">{editMode ? "Modification d'" : "Ajouter "}un {modalState.id >= 0 ? "combattant" : "invité"}</h1>
                        <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div className="modal-body">
                        {modalState.id < 0 && <div className="mb-2">Les invités sont réservés aux membres non licenciés par la fédération. Les combattants inscrits via ce formulaire ne pourront pas voir leur résultat depuis leur profil.</div>}
                        <div className="card" style={{marginBottom: "1em"}}>
                            <div className="card-header">{modalState.id >= 0 ? "Recherche*" : "Information"}</div>
                            <div className="card-body">
                                <div className="row" hidden={modalState.id < 0}>
                                    <div className="col">
                                        <input type="number" min={0} step={1} className="form-control" placeholder="N° de licence" name="licence"
                                               value={licence} onChange={e => setLicence(e.target.value)} disabled={editMode}/>
                                    </div>
                                </div>
                                <h5 style={{textAlign: "center", marginTop: "0.25em"}} hidden={modalState.id < 0}>Ou</h5>
                                <div className="row">
                                    <div className="col">
                                        <input type="text" className="form-control" placeholder="Prénom" name="fname"
                                               disabled={editMode && modalState.id >= 0}
                                               value={fname} onChange={e => setFname(e.target.value)}/>
                                    </div>
                                    <div className="col">
                                        <input type="text" className="form-control" placeholder="Nom" name="lname"
                                               disabled={editMode && modalState.id >= 0}
                                               value={lname} onChange={e => setLname(e.target.value)}/>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div className="input-group mb-3" hidden={modalState.id >= 0}>
                            <span className="input-group-text" id="categorie">Club</span>
                            <input type="text" className="form-control" placeholder="Club" name="club"
                                   value={club} onChange={e => setClub(e.target.value)}/>
                        </div>

                        <div className="input-group mb-3" hidden={modalState.id >= 0}>
                            <span className="input-group-text" id="categorie">Catégorie</span>
                            <select id="inputState2" className="form-select" value={gcat}
                                    onChange={(e) => setGCat(e.target.value)}>
                                <option>-- Sélectionner catégorie --</option>
                                {CatList.map((cat, index) => {
                                    return (<option key={index} value={cat}>{getCatName(cat)}</option>)
                                })}
                            </select>
                        </div>

                        <div className="input-group mb-3" hidden={modalState.id >= 0}>
                            <span className="input-group-text" id="categorie">Pays</span>
                            <select id="inputState0" className="form-select" value={country_} onChange={(e) => setCountry_(e.target.value)}>
                                {country && Object.keys(country).sort((a, b) => {
                                    if (a < b) return -1
                                    if (a > b) return 1
                                    return 0
                                }).map((key, _) => {
                                    return (<option key={key} value={key}>{country[key]}</option>)
                                })}
                            </select>
                        </div>

                        <div className="input-group mb-3" hidden={modalState.id >= 0}>
                            <span className="input-group-text" id="categorie">Genre</span>
                            <select className="form-select" aria-label="categorie" name="categorie" value={genre}
                                    onChange={e => setGenre(e.target.value)}>
                                <option value={"NA"}>NA</option>
                                <option value={"H"}>H</option>
                                <option value={"F"}>F</option>
                            </select>
                        </div>

                        <div className="input-group mb-3">
                            <span className="input-group-text" id="weight">Poids (en kg)</span>
                            <input type="number" min={1} step={1} className="form-control" placeholder="42" aria-label="weight"
                                   name="weight" aria-describedby="weight" value={weight} onChange={e => setWeight(e.target.value)}/>
                        </div>

                        <div className="input-group mb-3" hidden={modalState.id < 0}>
                            <span className="input-group-text" id="categorie">Surclassement</span>
                            <select className="form-select" aria-label="categorie" name="categorie" value={cat}
                                    onChange={e => setCat(Number(e.target.value))}>
                                <option value={0}>Aucun</option>
                                <option value={1}>+1 catégorie</option>
                                <option value={2}>+2 catégorie</option>
                            </select>
                        </div>

                        {editMode && source === "admin" && <div className="form-check form-switch form-check-reverse" hidden={modalState.id < 0}>
                            <input className="form-check-input" type="checkbox" id="switchCheckReverse" checked={lockEdit}
                                   onChange={e => setLockEdit(e.target.checked)}/>
                            <label className="form-check-label" htmlFor="switchCheckReverse">Empêcher les membres/club de modifier cette
                                inscription</label>
                        </div>}
                    </div>
                    <div className="modal-footer">
                        <button type="submit" className="btn btn-primary">{editMode ? "Modifier" : "Ajouter"}</button>
                        <button type="reset" className="btn btn-secondary" data-bs-dismiss="modal" id="closeModal">Annuler</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
}

let allClub = []
let allCat = []

function FiltreBar({data, clubFilter, setClubFilter, catFilter, setCatFilter, source}) {
    useEffect(() => {
        if (!data) return;
        allClub.push(...data.map((e) => e.club?.name))
        allClub = allClub.filter((value, index, self) => self.indexOf(value) === index).filter(value => value != null).sort()
        allCat.push(...data.map((e) => e.categorie))
        allCat = allCat.filter((value, index, self) => self.indexOf(value) === index).filter(value => value != null).sort()
    }, [data]);

    return <div>
        {source === "admin" && <div className="mb-3">
            <select className="form-select" value={clubFilter} onChange={event => setClubFilter(event.target.value)}>
                <option value="">--- tout les clubs ---</option>
                {allClub && allClub.map((value, index) => {
                    return <option key={index} value={value}>{value}</option>
                })}
            </select>
        </div>}
        <div className="mb-3">
            <select className="form-select" value={catFilter} onChange={event => setCatFilter(event.target.value)}>
                <option value="">--- toute les catégories ---</option>
                {allCat && allCat.map((value, index) => {
                    return <option key={index} value={value}>{value}</option>
                })}
            </select>
        </div>
    </div>
}

function MakeCentralPanel({data, dispatch, id, setModalState, source}) {
    const [searchParams] = useSearchParams();
    const registerType = searchParams.get("type") || "FREE";

    return <>
        {(registerType === "FREE" || registerType === "CLUB_ADMIN") && source === "admin" &&
            <span>Tips 1: Il est possible de bannir un combattant, ce qui l'empêchera d'être réinscrit par un autre moyen que par un administrateur de cette compétition.
                Pour cela, cliquez sur la petite <FontAwesomeIcon icon={faGavel}/> à côté de son nom.<br/>
                Tips 2: Il est aussi possible de verrouiller les modifications de son inscription depuis sa fiche, ce qui l'empêchera d'être modifié/supprimé par lui-même et/ou un responsable de club.
        </span>}
        <div className="mb-4">
            <div className="list-group">
                {data.map((req, index) => (<div key={index} className="list-group-item" style={{padding: "0"}}>
                    <div className="row" style={{padding: "0", margin: "0"}}>
                        <div style={{padding: ".5rem 1rem"}}
                             className={"col d-flex justify-content-between align-items-start list-group-item-" + ((req.data.lockEdit && source !== "admin") ? "secondary " : "action")}
                             data-bs-toggle={(req.data.lockEdit && source !== "admin") ? "" : "modal"} data-bs-target="#registerModal"
                             onClick={_ => setModalState({...req.data, id: req.id})}>
                            <div className="row">
                                <span className="col-auto">{req.data.licence ? String(req.data.licence).padStart(5, '0') : "-------"}</span>
                                <div className="ms-2 col-auto">
                                    <div><strong>{req.data.fname} {req.data.lname}</strong> <small>{req.data.genre}</small></div>
                                    <small>{req.data.club?.name || "Sans club"}</small>
                                </div>
                            </div>
                            <div className="row">
                                <div className="col-auto" style={{textAlign: "right"}}>
                                    <small>{getCatName(req.data.categorie) + (req.data.overCategory === 0 ? "" : (" avec " + req.data.overCategory + " de surclassement"))}<br/>
                                        {req.data.weight ? req.data.weight : "---"} kg
                                    </small>
                                </div>
                            </div>
                        </div>
                        <div className="col-auto" style={{padding: "0 0.5rem 0 0", alignContent: "center"}}>
                            {(registerType === "FREE" || registerType === "CLUB_ADMIN") && source === "admin" &&
                                <button className="btn btn btn-danger no-modal" type="button" disabled={req.data.lockEdit && source !== "admin"}
                                        style={{margin: "0 0.25rem 0 0"}}
                                        onClick={e => {
                                            e.preventDefault()

                                            if (req.data.lockEdit && source !== "admin") return;
                                            if (!window.confirm("Êtes-vous sûr de vouloir désinscrire et bannir ce combattant de la compétition?\n(Vous pouvez le réinscrire plus tard)"))
                                                return;

                                            toast.promise(apiAxios.delete(`/competition/${id}/register/${req.data.id}/${source}?ban=true`), {
                                                pending: "Désinscription en cours", success: "Combattant désinscrit et bannie", error: {
                                                    render({data}) {
                                                        return data.response.data || "Erreur"
                                                    }
                                                }
                                            }).finally(() => {
                                                dispatch({type: 'REMOVE', payload: req.id})
                                            })
                                        }}>
                                    <FontAwesomeIcon icon={faGavel} className="no-modal"/>
                                </button>}
                            <button className="btn btn-danger no-modal" type="button" disabled={req.data.lockEdit && source !== "admin"}
                                    onClick={e => {
                                        e.preventDefault()

                                        if (req.data.lockEdit && source !== "admin") return;
                                        if (registerType === "HELLOASSO") {
                                            if (!window.confirm("Êtes-vous sûr de vouloir désinscrire ce combattant ?\nCela ne le désinscrira pas de la billetterie HelloAsso et ne le remboursera pas."))
                                                return;
                                        } else {
                                            if (!window.confirm("Êtes-vous sûr de vouloir désinscrire ce combattant ?"))
                                                return;
                                        }

                                        toast.promise(apiAxios.delete(`/competition/${id}/register/${req.data.id}/${source}?ban=false`), {
                                            pending: "Désinscription en cours", success: "Combattant désinscrit", error: {
                                                render({data}) {
                                                    return data.response.data || "Erreur"
                                                }
                                            }
                                        }).finally(() => {
                                            dispatch({type: 'REMOVE', payload: req.id})
                                        })
                                    }}>
                                <FontAwesomeIcon icon={faTrashCan} className="no-modal"/>
                            </button>
                        </div>
                    </div>
                </div>))}
            </div>
        </div>
    </>
}

function FileOutput({data}) {
    const handleFileDownload = () => {
        const dataOut = []
        for (const e of data) {
            const tmp = {
                licence: e.licence,
                nom: e.lname,
                prenom: e.fname,
                genre: e.genre,
                weight: e.weight,
                categorie: e.categorie,
                overCategory: e.overCategory,
                club: e.club ? e.club.name : '',
            }
            dataOut.push(tmp)
        }

        const wb = XLSX.utils.book_new();
        const ws = XLSX.utils.json_to_sheet(dataOut);
        XLSX.utils.sheet_add_aoa(ws, [["Licence", "Nom", "Prénom", "Genre", "Poids", "Catégorie normalizer", "Surclassement", "Club"]], {origin: 'A1'});

        ws["!cols"] = [{wch: 7}, {wch: 16}, {wch: 16}, {wch: 6}, {wch: 6}, {wch: 10}, {wch: 10}, {wch: 60}]

        XLSX.utils.book_append_sheet(wb, ws, "Feuille 1");
        XLSX.writeFile(wb, "output.xlsx");
    };

    return (
        <div>
            <button className="btn btn-primary" onClick={handleFileDownload}>Exporter les inscription</button>
        </div>
    );
}

function Def() {
    return <div className="list-group">
        <li className="list-group-item"><ThreeDots/></li>
        <li className="list-group-item"><ThreeDots/></li>
        <li className="list-group-item"><ThreeDots/></li>
        <li className="list-group-item"><ThreeDots/></li>
        <li className="list-group-item"><ThreeDots/></li>
    </div>
}
