import {useEffect, useRef, useState} from "react";
import {useRequestWS, useWS} from "../../../hooks/useWS.jsx";
import {LoadingProvider, useLoadingSwitcher} from "../../../hooks/useLoading.jsx";
import {toast} from "react-toastify";
import {build_tree, resize_tree} from "../../../utils/TreeUtils.js"
import {ConfirmDialog} from "../../../components/ConfirmDialog.jsx";
import {CategoryContent} from "./CategoryAdminContent.jsx";

export function CMAdmin() {
    const [catId, setCatId] = useState(null);
    const [cat, setCat] = useState(null);
    const {dispatch} = useWS();

    useEffect(() => {
        const categoryListener = ({data}) => {
            if (!cat || data.id !== cat.id)
                return
            setCat({
                ...cat,
                name: data.name,
                liceName: data.liceName,
                type: data.type
            })
        }
        dispatch({type: 'addListener', payload: {callback: categoryListener, code: 'sendCategory'}})
        return () => dispatch({type: 'removeListener', payload: categoryListener})
    }, []);

    return <>
        <div className="card">
            <div className='card-header'>
                <CategoryHeader cat={cat} setCatId={setCatId}/>
            </div>

            <div className="card-body">
                <LoadingProvider>
                    <div className="row">
                        <CategoryContent cat={cat} catId={catId} setCat={setCat}/>
                    </div>
                </LoadingProvider>
            </div>
        </div>
    </>
}

function CategoryHeader({cat, setCatId}) {
    const setLoading = useLoadingSwitcher()
    const bthRef = useRef();
    const confirmRef = useRef();
    const [modal, setModal] = useState({})
    const [confirm, setConfirm] = useState({})

    const {data: cats, setData: setCats} = useRequestWS('getAllCategory', {}, setLoading);
    const {dispatch} = useWS();

    useEffect(() => {
        const categoryListener = ({data}) => {
            setCats([
                ...cats.filter(c => c.id !== data.id),
                data
            ])
        }
        dispatch({type: 'addListener', payload: {callback: categoryListener, code: 'sendCategory'}})
        return () => dispatch({type: 'removeListener', payload: categoryListener})
    }, [cats]);

    useEffect(() => {
        if (cats && cats.length > 0 && !cat) {
            setCatId(cats.sort((a, b) => a.name.localeCompare(b.name))[0].id);
        }
    }, [cats]);

    const handleCatChange = (e) => {
        const selectedCatId = e.target.value;
        if (selectedCatId !== "-1") {
            setCatId(selectedCatId);
        } else { // New category
            setModal({});
            bthRef.current.click();
            console.log(cat);
            e.target.value = cat?.id;
        }
    }

    return <div className="row">
        <div className="col-auto">
            <div className="input-group">
                <h5 style={{margin: "auto 0.5em auto 0"}}>Edition de la catégorie</h5>
                <select className="form-select" onChange={handleCatChange}>
                    {cats && cats.sort((a, b) => a.name.localeCompare(b.name)).map(c => (
                        <option key={c.id} value={c.id}>{c.name}</option>))}
                    {cats && <option value={-1}>Nouvelle...</option>}
                </select>
            </div>
        </div>
        <div className="col" style={{margin: "auto 0", textAlign: "center"}}>
            {cat &&
                <div>Type: {(cat.type & 1) !== 0 ? "Poule" : ""}{cat.type === 3 ? " & " : ""}{(cat.type & 2) !== 0 ? "Tournois" : ""} |
                    Lice: {cat.liceName}</div>}
        </div>
        <div className="col-auto">
            <button className="btn btn-primary float-end" onClick={() => {
                setModal(cat);
                bthRef.current.click();
            }} disabled={cat === null}>Modifier
            </button>
        </div>


        <button ref={bthRef} data-bs-toggle="modal" data-bs-target="#CategorieModal" style={{display: "none"}}>open</button>
        <div className="modal fade" id="CategorieModal" tabIndex="-1" aria-labelledby="CategorieModalLabel"
             aria-hidden="true">
            <div className="modal-dialog">
                <div className="modal-content">
                    <ModalContent state={modal} setCatId={setCatId} setConfirm={setConfirm} confirmRef={confirmRef}/>
                </div>
            </div>
        </div>

        <button ref={confirmRef} data-bs-toggle="modal" data-bs-target="#confirm-dialog" style={{display: "none"}}>open</button>
        <ConfirmDialog id="confirm-dialog" onConfirm={confirm.confirm ? confirm.confirm : () => {
        }} onCancel={confirm.cancel ? confirm.cancel : () => {
        }} title={confirm ? confirm.title : ""} message={confirm ? confirm.message : ""}/>
    </div>
}

function ModalContent({state, setCatId, setConfirm, confirmRef}) {
    const [name, setName] = useState("")
    const [lice, setLice] = useState("1")
    const [poule, setPoule] = useState(true)
    const [tournoi, setTournoi] = useState(false)
    const [size, setSize] = useState(4)
    const [loserMatch, setLoserMatch] = useState(1)

    const {sendRequest} = useWS();

    useEffect(() => {
        setName(state.name || "");
        setLice(state.liceName || "1");
        setPoule(((state.type || 1) & 1) !== 0);
        setTournoi((state.type & 2) !== 0);

        if (state?.trees && state.trees.length >= 1) {
            const tree = state.trees[0];
            setSize(tree.getMaxChildrenAtDepth(tree.death() - 1) * 2);

            if (state.trees.length === 1) {
                setLoserMatch(0);
            } else if (state.trees.length === 2) {
                setLoserMatch(1);
            } else {
                setLoserMatch(-1);
            }
        } else {
            setSize(4);
            setLoserMatch(1);
        }
    }, [state])

    const handleSubmit = (e) => {
        e.preventDefault();

        const regex = /^([^;]+;)*[^;]+$/;
        if (regex.test(lice.trim()) === false) {
            toast.error("Le format du nom des lices est invalide. Veuillez séparer les noms par des ';'.");
            return;
        }

        const nType = (poule ? 1 : 0) + (tournoi ? 2 : 0);
        if (nType === 0) {
            toast.error("Au moins un type (poule ou tournoi) doit être sélectionné.");
            return;
        }

        if (state?.id) {
            const applyChanges = () => {
                const newData = {
                    id: state.id,
                    name: name.trim(),
                    liceName: lice.trim(),
                    type: nType
                }

                let nbMatch = -1;
                let oldSubTree = -1;
                const oldTrees = state?.trees || [];
                if (oldTrees.length >= 1) {
                    const tree = state.trees[0];
                    nbMatch = tree.getMaxChildrenAtDepth(tree.death() - 1);
                    if (state.trees.length === 1)
                        oldSubTree = 0
                    else if (state.trees.length === 2)
                        oldSubTree = 1
                }

                console.log(tournoi, size, nbMatch, loserMatch, oldSubTree);
                if (tournoi && (size !== nbMatch * 2 || loserMatch !== oldSubTree)) {
                    setConfirm({
                        title: "Changement de l'arbre du tournoi",
                        message: `Voulez-vous vraiment changer la taille de l'arbre du tournoi ou les matchs pour les perdants ? Cela va modifier les matchs existants (incluant des possibles suppressions)!`,
                        confirm: () => {
                            const trees2 = build_tree(size, loserMatch)
                            const newTrees = []

                            let i = 0;
                            for (; i < oldTrees.length && i < trees2.length; i++) {
                                newTrees.push(oldTrees[i]);
                                resize_tree(newTrees.at(i), trees2.at(i));
                            }

                            for (; i < trees2.length; i++) {
                                newTrees.push(trees2.at(i));
                            }

                            toast.promise(sendRequest('updateTrees', {categoryId: state.id, trees: newTrees}),
                                {
                                    pending: 'Mise à jour des arbres du tournoi...',
                                    success: 'Arbres mis à jour !',
                                    error: 'Erreur lors de la mise à jour des arbres'
                                }
                            ).then(__ => {
                                toast.promise(sendRequest('updateCategory', newData),
                                    {
                                        pending: 'Mise à jour de la catégorie...',
                                        success: 'Catégorie mise à jour !',
                                        error: 'Erreur lors de la mise à jour de la catégorie'
                                    }
                                )
                            })
                        }
                    })
                    confirmRef.current.click();
                } else {
                    toast.promise(sendRequest('updateCategory', newData),
                        {
                            pending: 'Mise à jour de la catégorie...',
                            success: 'Catégorie mise à jour !',
                            error: 'Erreur lors de la mise à jour de la catégorie'
                        }
                    )
                }
            }

            if (nType !== state.type) {
                let typeStr = "";
                if ((state.type & 1) !== 0 && (nType & 1) === 0)
                    typeStr += "poule ";
                if ((state.type & 2) !== 0 && (nType & 2) === 0)
                    typeStr += "tournoi ";

                setConfirm({
                    title: "Changement de type de catégorie",
                    message: `Voulez-vous vraiment enlever la partie ${typeStr} de la catégorie. Cela va supprimer les matchs contenus dans cette partie !`,
                    confirm: () => {
                        setTimeout(() =>
                            applyChanges(), 500);
                    }
                })
                confirmRef.current.click();
            } else {
                applyChanges();
            }
        } else {
            toast.promise(sendRequest('createCategory', {name: name.trim(), liceName: lice.trim(), type: nType}),
                {
                    pending: 'Création de la catégorie...',
                    success: 'Catégorie créée !',
                    error: 'Erreur lors de la création de la catégorie'
                }
            ).then(id => {
                setCatId(id);

                if (tournoi) {
                    const trees = build_tree(size, loserMatch)
                    console.log("Creating trees for new category:", trees);

                    toast.promise(sendRequest('updateTrees', {categoryId: id, trees: trees}),
                        {
                            pending: 'Création des arbres du tournoi...',
                            success: 'Arbres créés !',
                            error: 'Erreur lors de la création des arbres'
                        }
                    )
                }
            })
        }

        const data = {
            name: name.trim(),
            liceName: lice.trim(),
            type: poule + (tournoi << 1),
            size: size,
            loserMatch: loserMatch
        }
        console.log("Submitting category data:", data);
    }

    return <form onSubmit={handleSubmit}>
        <div className="modal-header">
            <h1 className="modal-title fs-5" id="CategorieModalLabel">Ajouter une catégorie</h1>
            <button type="button" className="btn-close" data-bs-dismiss="modal"
                    aria-label="Close"></button>
        </div>
        <div className="modal-body">
            <div className="mb-3">
                <label htmlFor="nameInput1" className="form-label">Nom</label>
                <input type="text" className="form-control" id="nameInput1" placeholder="Epée bouclier" name="name" value={name}
                       onChange={e => setName(e.target.value)}/>
            </div>

            <div className="mb-3">
                <label htmlFor="liceInput1" className="form-label">Nom des lices <small>(séparée par des ';')</small></label>
                <input type="text" className="form-control" id="liceInput1" placeholder="1;2" name="lice" value={lice}
                       onChange={e => setLice(e.target.value)}/>
            </div>


            <div className="mb-3">
                <label className="form-label">Type</label>
                <div className="form-check form-switch">
                    <input className="form-check-input" type="checkbox" role="switch" id="switchCheckDefault" name="poule" checked={poule}
                           onChange={e => setPoule(e.target.checked)}/>
                    <label className="form-check-label" htmlFor="switchCheckDefault">Poule</label>
                </div>

                <div className="form-check form-switch">
                    <input className="form-check-input" type="checkbox" role="switch" id="switchCheckDefault2" name="trournoi" checked={tournoi}
                           onChange={e => setTournoi(e.target.checked)}/>
                    <label className="form-check-label" htmlFor="switchCheckDefault2">Tournoi</label>
                </div>
            </div>

            <div className="mb-3">
                <label htmlFor="sizeInput1" className="form-label">Nombre de combattants</label>
                <input type="number" className="form-control" id="sizeInput1" placeholder="4" name="size" disabled={!tournoi} value={size}
                       onChange={e => setSize(Number.parseInt(e.target.value))}/>
            </div>

            <div className="mb-3">
                <span>Match pour les perdants du tournoi:</span>
                <div className="form-check">
                    <input className="form-check-input" type="radio" name="radioDefault" id="radioDefault1" disabled={!tournoi}
                           checked={loserMatch === -1} onChange={e => {
                        if (e.target.checked) setLoserMatch(-1)
                    }}/>
                    <label className="form-check-label" htmlFor="radioDefault1">
                        Tous les matchs
                    </label>
                </div>
                <div className="form-check">
                    <input className="form-check-input" type="radio" name="radioDefault" id="radioDefault2" disabled={!tournoi}
                           checked={loserMatch === 1} onChange={e => {
                        if (e.target.checked) setLoserMatch(1)
                    }}/>
                    <label className="form-check-label" htmlFor="radioDefault2">
                        Demi-finales et finales
                    </label>
                </div>
                <div className="form-check">
                    <input className="form-check-input" type="radio" name="radioDefault" id="radioDefault3" disabled={!tournoi}
                           checked={loserMatch === 0} onChange={e => {
                        if (e.target.checked) setLoserMatch(0)
                    }}/>
                    <label className="form-check-label" htmlFor="radioDefault3">
                        Finales uniquement
                    </label>
                </div>
            </div>

        </div>
        <div className="modal-footer">
            <button type="button" className="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
            <button type="submit" className="btn btn-primary" data-bs-dismiss="modal">Enregistrer</button>
        </div>
    </form>
}
