import {useCountries} from "../../../hooks/useCountries.jsx";
import {useEffect, useReducer, useState} from "react";
import {CatList, getCatName} from "../../../utils/Tools.js";
import {CombName} from "../../../hooks/useComb.jsx";
import {useWS} from "../../../hooks/useWS.jsx";

function SelectReducer(state, action) {
    switch (action.type) {
        case 'TOGGLE_ID':
            return {
                ...state,
                [action.payload]: !(state[action.payload] || false)
            }
        case 'ADD_ALL':
            return {
                ...state,
                ...action.payload.reduce((acc, id) => {
                    acc[id] = false;
                    return acc;
                }, {})
            };
        case 'CLEAR_ACTIVE':
            const newState = {...state};
            Object.keys(newState).forEach(id => {
                newState[id] = false;
            });
            return newState;
        case 'REMOVE_ACTIVE':
            const filteredState = {...state};
            Object.keys(filteredState).forEach(id => {
                if (filteredState[id]) {
                    delete filteredState[id];
                }
            });
            return filteredState;
        case 'REMOVE_IN':
            const filteredState2 = {...state};
            Object.keys(filteredState2).forEach(id => {
                if (action.payload.includes(id)) {
                    delete filteredState2[id];
                }
            });
            return filteredState2;
        case 'REMOVE_ID':
            const newState2 = {...state};
            delete newState2[action.payload];
            return newState2;
        case 'REMOVE_ALL':
            return {};
        default:
            return state;
    }
}

export function SelectCombModalContent({data, setGroups}) {
    const country = useCountries('fr')
    const {dispatch} = useWS()
    const [dispo, dispoReducer] = useReducer(SelectReducer, {})
    const [select, selectReducer] = useReducer(SelectReducer, {})

    const [targetGroupe, setTargetGroupe] = useState("A")
    const [search, setSearch] = useState("")
    const [country_, setCountry_] = useState("")
    const [club, setClub] = useState("")
    const [gender, setGender] = useState({H: true, F: true, NA: true})
    const [cat, setCat] = useState(-1)
    const [weightMin, setWeightMin] = useState(0)
    const [weightMax, setWeightMax] = useState(0)

    const handleSubmit = (e) => {
        e.preventDefault();
        setGroups(prev => [...prev.filter(d => select[d.id] === undefined), ...Object.keys(select).map(id => {
            return {id: Number(id), poule: targetGroupe}
        })])

        dispoReducer({type: 'REMOVE_ALL'})
        selectReducer({type: 'REMOVE_ALL'})
        if (data == null)
            return
        dispoReducer({type: 'ADD_ALL', payload: data.map(d => d.id)})
    }


    useEffect(() => {
        const sendRegisterRemove = ({data}) => {
            dispoReducer({type: 'REMOVE_ID', payload: data})
            selectReducer({type: 'REMOVE_ID', payload: data})
        }
        dispatch({type: 'addListener', payload: {callback: sendRegisterRemove, code: 'sendRegisterRemove'}})
        return () => {
            dispatch({type: 'removeListener', payload: sendRegisterRemove})
        }
    }, []);

    useEffect(() => {
        if (data == null)
            return
        const selectedIds = Object.keys(select).map(g => Number(g))
        dispoReducer({type: 'ADD_ALL', payload: data.map(d => d.id).filter(id => !selectedIds.includes(id))})
    }, [data])

    function applyFilter(dataIn, dataOut) {
        Object.keys(dataIn).forEach((id) => {
                const comb = data.find(d => d.id === Number(id));
                if (comb == null)
                    return;
                if ((search === "" || comb.fname.toLowerCase().includes(search.toLowerCase()) || comb.lname.toLowerCase().includes(search.toLowerCase())
                        || (comb.fname + " " + comb.lname).toLowerCase().includes(search.toLowerCase()))
                    && (country_ === "" || comb.country === country_)
                    && (club === "" || comb.club_str === club)
                    && (gender.H && comb.genre === 'H' || gender.F && comb.genre === 'F' || gender.NA && comb.genre === 'NA')
                    && (cat === -1 || cat === Math.min(CatList.length, CatList.indexOf(comb.categorie) + comb.overCategory))
                    && (weightMin === 0 || comb.weight !== null && comb.weight >= weightMin)
                    && (weightMax === 0 || comb.weight !== null && comb.weight <= weightMax)) {
                    dataOut[id] = dataIn[id];
                }
            }
        )
    }

    let clubList = [];
    if (data != null) {
        clubList = data.map(d => d.club_str).filter((v, i, a) => v !== "" && a.indexOf(v) === i);
    }

    const dispoFiltered = {};
    applyFilter(dispo, dispoFiltered);

    const selectFiltered = {};
    applyFilter(select, selectFiltered);

    const moveComb = (event) => {
        event.preventDefault();
        switch (event.target.textContent) {
            case '>>':
                selectReducer({type: 'ADD_ALL', payload: Object.keys(dispoFiltered)})
                dispoReducer({type: 'REMOVE_IN', payload: Object.keys(dispoFiltered)});
                break;
            case '<<':
                dispoReducer({type: 'ADD_ALL', payload: Object.keys(selectFiltered)})
                selectReducer({type: 'REMOVE_IN', payload: Object.keys(selectFiltered)});
                break;
            case '>':
                selectReducer({type: 'ADD_ALL', payload: Object.keys(dispo).filter(id => dispo[id])})
                dispoReducer({type: 'REMOVE_ACTIVE'});
                break;
            case '<':
                dispoReducer({type: 'ADD_ALL', payload: Object.keys(select).filter(id => select[id])})
                selectReducer({type: 'REMOVE_ACTIVE'});
                break;
        }
    }

    return <>
        <div className="modal-header">
            <h1 className="modal-title fs-5" id="CategorieModalLabel">Sélectionner des combatants</h1>
            <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div className="modal-body">
            <div className="d-flex flex-wrap justify-content-around mb-1">
                <div className="col-md-5">
                    <label htmlFor="input4" className="form-label">Recherche</label>
                    <input type="text" className="form-control" id="input4" value={search} onChange={(e) => setSearch(e.target.value)}/>
                </div>

                <div style={{width: "12em"}}>
                    <label htmlFor="inputState0" className="form-label">Pays</label>
                    <select id="inputState0" className="form-select" value={country_} onChange={(e) => setCountry_(e.target.value)}>
                        <option value={""}>-- Tous --</option>
                        {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>
                    <label htmlFor="inputState1" className="form-label">Club</label>
                    <select id="inputState1" className="form-select" value={club} onChange={(e) => setClub(e.target.value)}>
                        <option value={""}>-- Tous --</option>
                        {clubList.sort((a, b) => a.localeCompare(b)).map((club) => (
                            <option key={club} value={club}>{club}</option>))}
                    </select>
                </div>
            </div>

            <div className="d-flex flex-wrap justify-content-around mb-1">
                <div>
                    <label className="form-label">Genre</label>
                    <div className="d-flex align-items-center">
                        <div className="form-check" style={{marginRight: '10px'}}>
                            <input className="form-check-input" type="checkbox" id="gridCheck" checked={gender.H}
                                   onChange={e => setGender((prev) => {
                                       return {...prev, H: e.target.checked}
                                   })}/>
                            <label className="form-check-label" htmlFor="gridCheck">H</label>
                        </div>
                        <div className="form-check" style={{marginRight: '10px'}}>
                            <input className="form-check-input" type="checkbox" id="gridCheck2" checked={gender.F}
                                   onChange={e => setGender((prev) => {
                                       return {...prev, F: e.target.checked}
                                   })}/>
                            <label className="form-check-label" htmlFor="gridCheck2">F</label>
                        </div>
                        <div className="form-check">
                            <input className="form-check-input" type="checkbox" id="gridCheck3" checked={gender.NA}
                                   onChange={e => setGender((prev) => {
                                       return {...prev, NA: e.target.checked}
                                   })}/>
                            <label className="form-check-label" htmlFor="gridCheck3">NA</label>
                        </div>
                    </div>
                </div>
                <div>
                    <label htmlFor="inputState2" className="form-label">Catégorie</label>
                    <select id="inputState2" className="form-select" value={cat} onChange={(e) => setCat(Number(e.target.value))}>
                        <option value={-1}>-- Tous --</option>
                        {CatList.map((cat, index) => {
                            return (<option key={index} value={index}>{getCatName(cat)}</option>)
                        })}
                    </select>
                </div>
                <div>
                    <label htmlFor="input5" className="form-label">Poids</label>
                    <div className="row-cols-sm-auto d-flex align-items-center">
                        <div style={{width: "4.25em"}}><input type="number" className="form-control" id="input5" value={weightMin} min="0"
                                                              name="999"
                                                              onChange={e => setWeightMin(Number(e.target.value))}/></div>
                        <div><span>à</span></div>
                        <div style={{width: "4.25em"}}><input type="number" className="form-control" value={weightMax} min="0" name="999"
                                                              onChange={e => setWeightMax(Number(e.target.value))}/></div>
                        <div><small>(0 = désactivé)</small></div>
                    </div>
                </div>
                <button style={{display: "none"}} onClick={event => event.preventDefault()}></button>
            </div>
            <hr/>
            <div className="row g-3">
                <div className="col-md">
                    <div style={{textAlign: "center"}}>Inscrit</div>
                    <div className="list-group overflow-y-auto" style={{maxHeight: "50vh"}}>
                        {dispoFiltered && Object.keys(dispoFiltered).length === 0 && <div>Aucun combattant disponible</div>}
                        {Object.keys(dispoFiltered).map((id) => (
                            <button key={id} type="button" className={"list-group-item list-group-item-action " + (dispoFiltered[id] ? "active" : "")}
                                    onClick={() => dispoReducer({type: 'TOGGLE_ID', payload: id})}>
                                <CombName combId={id}/>
                            </button>))}
                    </div>
                </div>
                <div className="col-auto" style={{margin: "0.5em auto"}}>
                    <div className="d-flex flex-sm-column align-items-center h-100 justify-content-center">
                        <button className="btn btn-secondary" style={{margin: "0.15em"}} onClick={moveComb}>&#62;&#62;</button>
                        <button className="btn btn-secondary" style={{margin: "0.15em"}} onClick={moveComb}>&#60;&#60;</button>
                        <button className="btn btn-secondary" style={{margin: "0.15em"}} onClick={moveComb}>&#62;</button>
                        <button className="btn btn-secondary" style={{margin: "0.15em"}} onClick={moveComb}>&#60;</button>
                    </div>
                </div>
                <div className="col-md">
                    <div style={{textAlign: "center"}}>Sélectionner</div>
                    <div className="list-group overflow-y-auto" style={{maxHeight: "50vh"}}>
                        {selectFiltered && Object.keys(selectFiltered).length === 0 && <div>Aucun combattant sélectionné</div>}
                        {Object.keys(selectFiltered).map((id) => (
                            <button key={id} type="button"
                                    className={"list-group-item list-group-item-action " + (selectFiltered[id] ? "active" : "")}
                                    onClick={() => selectReducer({type: 'TOGGLE_ID', payload: id})}>
                                <CombName combId={id}/>
                            </button>))}
                    </div>
                </div>
            </div>
        </div>
        <div className="modal-footer">
            <button type="button" className="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
            <div className="vr"></div>
            <label htmlFor="input6" className="form-label">Poule</label>
            <input type="text" className="form-control" id="input6" style={{width: "3em"}} maxLength={1} value={targetGroupe}
                   onChange={(e) => {
                       if (/^[a-zA-Z0-9]$/.test(e.target.value))
                           setTargetGroupe(e.target.value)
                   }}/>
            <button type="submit" className="btn btn-primary" data-bs-dismiss="modal" onClick={handleSubmit}>Ajouter</button>
        </div>
    </>
}
