import {useRequestWS, useWS} from "../../../hooks/useWS.jsx";
import {useLoadingSwitcher} from "../../../hooks/useLoading.jsx";
import {compareCardOrder, useCards, useCardsDispatch} from "../../../hooks/useCard.jsx";
import React, {useEffect, useRef, useState} from "react";
import {toast} from "react-toastify";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faCaretLeft} from "@fortawesome/free-solid-svg-icons";
import {getToastMessage, scorePrint, virtual_end, virtualScore, win} from "../../../utils/Tools.js";
import {useTranslation} from "react-i18next";
import {faCircleQuestion} from "@fortawesome/free-regular-svg-icons";

export function ScorePanel({matchId, matchs, match, menuActions, admin = false}) {
    const {cards_v} = useCards();

    const onClickVoid = useRef(() => {
    });

    const vEnd = virtual_end(match, cards_v);
    return <div className="row" onClick={onClickVoid.current}>
        <ScorePanel_ matchId={matchId} matchs={matchs} match={match} menuActions={menuActions} onClickVoid_={onClickVoid} vEnd={vEnd}/>
        <CardPanel matchId={matchId} match={match} vEnd={admin ? false : vEnd} admin={admin}/>
    </div>
}

function ScorePanel_({matchId, matchs, match, menuActions, onClickVoid_, vEnd}) {
    const {sendRequest} = useWS()
    const setLoading = useLoadingSwitcher()
    const {t} = useTranslation("cm");

    const [end, setEnd] = useState(match?.end || false)
    const [scoreIn, setScoreIn] = useState("")
    const inputRef = useRef(null)
    const tableRef = useRef(null)
    const scoreRef = useRef([])
    const lastScoreClick = useRef(null)
    const scoreInRef = useRef(null)
    const {cards_v} = useCards();

    useEffect(() => {
        scoreInRef.current = scoreIn;
    }, [scoreIn]);

    useEffect(() => {
        menuActions.current.saveScore = (scoreRed, scoreBlue) => {
            const maxRound = (Math.max(...match.scores.map(s => s.n_round), -1) + 1) || 0;
            const newScore = {n_round: maxRound, s1: scoreRed, s2: scoreBlue};
            toast.promise(sendRequest('updateMatchScore', {matchId: matchId, ...newScore}), getToastMessage("toast.updateMatchScore", "cm"));
        }
        return () => menuActions.current.saveScore = undefined;
    }, [matchId])

    const handleScoreClick = (e, round, comb) => {
        e.stopPropagation();

        if (vEnd)
            return;

        const tableRect = tableRef.current.getBoundingClientRect();
        const rect = e.currentTarget.getBoundingClientRect();

        updateScore();

        const sel = inputRef.current;
        sel.style.top = (rect.y - tableRect.y) + "px";
        sel.style.left = (rect.x - tableRect.x) + "px";
        sel.style.width = rect.width + "px";
        sel.style.height = rect.height + "px";
        sel.style.display = "block";

        if (round === -1) {
            const maxRound = (Math.max(...match.scores.map(s => s.n_round), -1) + 1) || 0;
            setScoreIn("");
            console.log("Setting for new round", maxRound);
            lastScoreClick.current = {matchId: matchId, round: maxRound, comb};
        } else {
            const score = match.scores.find(s => s.n_round === round);
            const tmp= (comb === 1 ? score?.s1 : score?.s2)
            setScoreIn((tmp === -1000 ? "" : tmp) || "");
            lastScoreClick.current = {matchId: matchId, round, comb};
            setTimeout(() => inputRef.current.select(), 100);
        }
    }

    const updateScore = () => {
        if (lastScoreClick.current !== null) {
            const {matchId, round, comb} = lastScoreClick.current;
            lastScoreClick.current = null;

            const scoreIn_ = String(scoreInRef.current).trim() === "" ? -1000 : Number(scoreInRef.current);

            const score = matchs?.find(m => m.id === matchId)?.scores?.find(s => s.n_round === round);

            let newScore;
            if (score) {
                if (comb === 1)
                    newScore = {...score, s1: scoreIn_};
                else
                    newScore = {...score, s2: scoreIn_};

                if (newScore.s1 === score?.s1 && newScore.s2 === score?.s2)
                    return
            } else {
                newScore = {n_round: round, s1: (comb === 1 ? scoreIn_ : -1000), s2: (comb === 2 ? scoreIn_ : -1000)};
                if (newScore.s1 === -1000 && newScore.s2 === -1000)
                    return
            }

            setLoading(1)
            sendRequest('updateMatchScore', {matchId: matchId, ...newScore})
                .finally(() => {
                    setLoading(0)
                })
        }
    }

    const onClickVoid = () => {
        updateScore();

        const sel = inputRef.current;
        sel.style.display = "none";
        lastScoreClick.current = null;
    }
    onClickVoid_.current = onClickVoid;

    useEffect(() => {
        if (!match || match?.end === end)
            return;

        if (end) {
            if (win(match) === 0 && match.categorie_ord === -42) {
                toast.error(t('score.err1'));
                setEnd(false);
                return;
            }
        }

        setLoading(1)
        sendRequest('updateMatchEnd', {matchId: matchId, end})
            .finally(() => {
                setLoading(0)
            })
    }, [end]);

    useEffect(() => {
        onClickVoid()
    }, [matchId]);

    useEffect(() => {
        if (match?.scores)
            scoreRef.current = scoreRef.current.slice(0, match.scores.length);
    }, [match?.scores]);

    useEffect(() => {
        if (!match)
            return;
        setEnd(match.end);
    }, [match]);

    useEffect(() => {
        const handleClickOutside = (event) => {
            if (inputRef.current && !inputRef.current.contains(event.target)) {
                onClickVoid();
            }
        };
        document.addEventListener("mousedown", handleClickOutside);
        return () => {
            document.removeEventListener("mousedown", handleClickOutside);
        };
    }, [matchId, match]);

    const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
    const o = [...tooltipTriggerList]
    o.map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))

    const tt = t('score.spe')

    const maxRound = (match?.scores) ? (Math.max(...match.scores.map(s => s.n_round), -1) + 1) : 0;
    return <div ref={tableRef} className="col" style={{position: "relative"}}>
        <h6>{t('scores')} <FontAwesomeIcon icon={faCircleQuestion} role="button" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-title={tt}
                                           data-bs-html="true"/></h6>
        <table className="table table-striped">
            <thead>
            <tr>
                <th style={{textAlign: "center"}} scope="col">{t('manche')}</th>
                <th style={{textAlign: "center", minWidth: "4em"}} scope="col">{t('rouge')}</th>
                <th style={{textAlign: "center", minWidth: "4em"}} scope="col">{t('bleu')}</th>
            </tr>
            </thead>
            <tbody className={"table-group-divider" + (vEnd ? " table-secondary" : "")}>
            {match?.scores && match.scores.sort((a, b) => a.n_round - b.n_round).map(score => (
                <tr key={score.n_round}>
                    <th style={{textAlign: "center"}}>{score.n_round + 1}</th>
                    <td style={{textAlign: "center"}} ref={e => scoreRef.current[score.n_round * 2] = e}
                        onClick={e => handleScoreClick(e, score.n_round, 1)}>{scorePrint(virtualScore(match.c1, score, match, cards_v))}</td>
                    <td style={{textAlign: "center"}} ref={e => scoreRef.current[score.n_round * 2 + 1] = e}
                        onClick={e => handleScoreClick(e, score.n_round, 2)}>{scorePrint(virtualScore(match.c2, score, match, cards_v))}</td>
                </tr>
            ))}
            <tr>
                <th style={{textAlign: "center"}}></th>
                <td style={{textAlign: "center"}} ref={e => scoreRef.current[maxRound * 2] = e} onClick={e => handleScoreClick(e, -1, 1)}>-</td>
                <td style={{textAlign: "center"}} ref={e => scoreRef.current[maxRound * 2 + 1] = e} onClick={e => handleScoreClick(e, -1, 2)}>-
                </td>
            </tr>
            </tbody>
        </table>
        <div style={{textAlign: "right"}}>
            <div className="form-check" style={{display: "inline-block"}}>
                <input className="form-check-input" type="checkbox" id="checkboxEnd" name="checkboxEnd" checked={end || vEnd} disabled={vEnd}
                       onChange={e => setEnd(e.target.checked)}/>
                <label className="form-check-label" htmlFor="checkboxEnd">{t('terminé')}</label>
            </div>
        </div>
        <input ref={inputRef} type="number" className="form-control" style={{position: "absolute", top: 0, left: 0, display: "none"}} min="-999"
               max="999"
               value={scoreIn} onChange={e => setScoreIn(e.target.value)}
               onClick={e => e.stopPropagation()}
               onKeyDown={e => {
                   if (e.key === "Tab") {
                       if (lastScoreClick.current !== null) {
                           const {round, comb} = lastScoreClick.current;
                           const nextIndex = (round * 2 + (comb - 1)) + (e.shiftKey ? -1 : 1);
                           if (nextIndex >= 0 && nextIndex < scoreRef.current.length) {
                               e.preventDefault();
                               scoreRef.current[nextIndex].click();
                           }
                       }
                   } else if (e.key === "Enter") {
                       e.preventDefault();
                       onClickVoid();
                   }
               }}/>
    </div>
}

function CardPanel({matchId, match, vEnd, admin}) {
    const {sendRequest} = useWS();
    const setLoading = useLoadingSwitcher()
    const cardDispatch = useCardsDispatch();
    const {getCardInMatch, getHeightCardForCombInMatch} = useCards();
    const {t} = useTranslation("cm");

    const {data, refresh} = useRequestWS('getCardForMatch', matchId, setLoading);
    useEffect(() => {
        refresh('getCardForMatch', matchId);
    }, [matchId])

    useEffect(() => {
        if (!data)
            return;
        cardDispatch({type: 'SET_ALL', payload: data})
    }, [data])

    if (!match) {
        return <div className="col"></div>
    }
    const handleCard = (combId, type) => {
        setLoading(1)
        sendRequest('sendCardAdd', {matchId, combId, type})
            .then(() => {
                toast.success(t('cardAdded'));
            })
            .catch(err => {
                toast.error(err);
            })
            .finally(() => {
                setLoading(0)
            })
    }

    const confirmRm = (combId, type) => {
        function content({closeToast}) {
            return (
                <div className="flex items-center w-full">
                    <span>{t('ceCartonEstIssuDunCartonDéquipe')}</span>{' '}
                    <button
                        className="btn btn-sm btn-warning ml-2"
                        onClick={() => {
                            closeToast(true);
                            handleCardRm_(combId, type)
                        }}>
                        {t('confirmer')}
                    </button>
                </div>
            );
        }

        toast.warn(content);
    }

    const handleCardRm_ = (combId, type) => {
        setLoading(1)
        sendRequest('sendCardRm', {matchId, combId, type})
            .then(() => {
                toast.success(t('cardRemoved'));
            })
            .catch(err => {
                toast.error(err);
            })
            .finally(() => {
                setLoading(0)
            })
    }

    const cards = getCardInMatch(match)

    const handleCardRm = (combId, type) => {
        if (cards.find(c => c.comb === combId && c.type === type)?.teamCard) {
            confirmRm(combId, type)
        } else {
            handleCardRm_(combId, type)
        }
    }

    const MakeList = ({comb}) => {
        const card = getHeightCardForCombInMatch(comb, match);

        return <div className="btn-group-vertical" role="group">
            <button type="button" className="btn btn-sm btn-primary position-relative"
                    onClick={() => handleCard(comb, "BLUE")}
                    disabled={card && compareCardOrder(card, {type: "BLUE"}) >= 0 || vEnd}>{t('avertissement')}
                <span className="position-absolute top-0 start-100 p-2 text-danger-emphasis"
                      hidden={!cards.some(c => c.comb === comb && c.type === "BLUE")}>
                        <FontAwesomeIcon icon={faCaretLeft}/></span>
            </button>
            <button type="button" className="btn btn-sm btn-warning position-relative"
                    onClick={() => handleCard(comb, "YELLOW")}
                    disabled={card && compareCardOrder(card, {type: "YELLOW"}) >= 0 || vEnd}>{t('cartonJaune')}
                <span className="position-absolute top-0 start-100 p-2 text-danger-emphasis"
                      hidden={!cards.some(c => c.comb === comb && c.type === "YELLOW")}>
                        <FontAwesomeIcon icon={faCaretLeft}/></span>
            </button>
            <button type="button" className="btn btn-sm btn-danger position-relative"
                    onClick={() => handleCard(comb, "RED")}
                    disabled={card && compareCardOrder(card, {type: "RED"}) >= 0 || vEnd}>{t('cartonRouge')}
                <span className="position-absolute top-0 start-100 p-2 text-danger-emphasis"
                      hidden={!cards.some(c => c.comb === comb && c.type === "RED")}>
                        <FontAwesomeIcon icon={faCaretLeft}/></span>
            </button>
            <button type="button" className="btn btn-sm btn-dark position-relative"
                    onClick={() => handleCard(comb, "BLACK")}
                    disabled={card?.type !== "RED" || vEnd}>{t('cartonNoir')}
                <span className="position-absolute top-0 start-100 p-2 text-danger-emphasis"
                      hidden={!cards.some(c => c.comb === comb && c.type === "BLACK")}>
                        <FontAwesomeIcon icon={faCaretLeft}/></span>
            </button>
        </div>
    }

    const MakeListAdmin = ({comb}) => {
        const card = getHeightCardForCombInMatch(comb, match);

        return <div className="btn-group-vertical" role="group">
            <div className="btn-group" role="group">
                <button type="button" className="btn btn-sm btn-secondary">{t('ajouterUn')}</button>
                <button type="button" className="btn btn-sm btn-secondary">{t('supprimerUn')}</button>
            </div>
            <div className="btn-group" role="group">
                <button type="button" className="btn btn-sm btn-primary"
                        onClick={() => handleCard(comb, "BLUE")}
                        disabled={card && compareCardOrder(card, {type: "BLUE"}) >= 0 || vEnd}>{t('avertissement')}
                </button>
                <button type="button" className="btn btn-sm btn-primary"
                        onClick={() => handleCardRm(comb, "BLUE")}
                        disabled={!cards.some(c => c.comb === comb && c.type === "BLUE")}>{t('avertissement')}
                </button>
            </div>
            <div className="btn-group" role="group">
                <button type="button" className="btn btn-sm btn-warning"
                        onClick={() => handleCard(comb, "YELLOW")}
                        disabled={card && compareCardOrder(card, {type: "YELLOW"}) >= 0 || vEnd}>{t('cartonJaune')}
                </button>
                <button type="button" className="btn btn-sm btn-warning"
                        onClick={() => handleCardRm(comb, "YELLOW")}
                        disabled={!cards.some(c => c.comb === comb && c.type === "YELLOW")}>{t('cartonJaune')}
                </button>
            </div>
            <div className="btn-group" role="group">
                <button type="button" className="btn btn-sm btn-danger"
                        onClick={() => handleCard(comb, "RED")}
                        disabled={card && compareCardOrder(card, {type: "RED"}) >= 0 || vEnd}>{t('cartonRouge')}
                </button>
                <button type="button" className="btn btn-sm btn-danger"
                        onClick={() => handleCardRm(comb, "RED")}
                        disabled={!cards.some(c => c.comb === comb && c.type === "RED")}>{t('cartonRouge')}
                </button>
            </div>
            <div className="btn-group" role="group">
                <button type="button" className="btn btn-sm btn-dark"
                        onClick={() => handleCard(comb, "BLACK")}
                        disabled={card?.type !== "RED" || vEnd}>{t('cartonNoir')}
                </button>
                <button type="button" className="btn btn-sm btn-dark"
                        onClick={() => handleCardRm(comb, "BLACK")}
                        disabled={!cards.some(c => c.comb === comb && c.type === "BLACK")}>{t('cartonNoir')}
                </button>
            </div>
        </div>
    }

    return <div className="col">
        <h6>Carton</h6>
        <div className="bg-danger-subtle text-danger-emphasis" style={{padding: ".25em", borderRadius: "1em 1em 0 0"}}>
            <h6>Combattant rouge</h6>
            {admin ? <MakeListAdmin comb={match.c1}/> :
                <><span>{t('ajouterUn')}</span><MakeList comb={match.c1}/></>}
        </div>
        <div className="bg-info-subtle text-info-emphasis" style={{padding: ".25em", borderRadius: "0 0 1em 1em"}}>
            <h6>Combattant bleu</h6>
            {admin ? <MakeListAdmin comb={match.c2}/> :
                <><span>{t('ajouterUn')}</span><MakeList comb={match.c2}/></>}
        </div>
    </div>
}
