import "../style/home/home.css"
import { useNavigate } from "react-router-dom"
import {RefObject, useEffect, useRef, useState} from "react"
import {useAppFetcher, useUser} from "../App.tsx"
import {NULL_POS} from "../geo/Pos";
import {contains} from "../geo/Box";
import Draggable from "react-draggable"
import { FaShare } from "react-icons/fa"

interface Tactic {
    id: number
    name: string
    creationDate: number
}

interface Team {
    id: number
    name: string
    picture: string
    main_color: string
    second_color: string
}

export default function HomePage() {
    type UserDataResponse = { tactics: Tactic[]; teams: Team[]; sharedTactics: Tactic[] }
    const [{ teams, tactics, sharedTactics }, setInfo] = useState<UserDataResponse>({
        tactics: [],
        teams: [],
        sharedTactics: [],
    })

    console.log(sharedTactics)

    const navigate = useNavigate()
    const fetcher = useAppFetcher()

    useEffect(() => {
        async function initUserData() {
            const response = await fetcher.fetchAPIGet("user-data")
            if (response.status == 401) {
                navigate("/login")
                return // if unauthorized
            }
            setInfo(await response.json())
        }

        initUserData()
    }, [fetcher, navigate])

    tactics!.sort((a, b) => b.creationDate - a.creationDate)

    const lastTactics = tactics.slice(0, 5)
    return (
        <Home teams={teams!} allTactics={tactics!} lastTactics={lastTactics} sharedTactics={sharedTactics!} />
    )
}

function Home({
    lastTactics,
    allTactics,
    teams,
    sharedTactics,
}: {
    lastTactics: Tactic[]
    allTactics: Tactic[]
    teams: Team[]
    sharedTactics: Tactic[]
}) {
    return (
        <div id="main">
            <Body
                lastTactics={lastTactics}
                allTactics={allTactics}
                teams={teams}
                sharedTactics={sharedTactics}
            />
        </div>
    )
}

function Body({
    lastTactics,
    allTactics,
    teams,
    sharedTactics,
}: {
    lastTactics: Tactic[]
    allTactics: Tactic[]
    teams: Team[]
    sharedTactics: Tactic[]
}) {
    const widthPersonalSpace = 78
    const widthSideMenu = 100 - widthPersonalSpace
    return (
        <div id="body">
            <PersonalSpace width={widthPersonalSpace} allTactics={allTactics} teams={teams} sharedTactics={sharedTactics} />
            <SideMenu
                width={widthSideMenu}
                lastTactics={lastTactics}
                teams={teams}
            />
        </div>
    )
}

function SideMenu({
    width,
    lastTactics,
    teams,
}: {
    width: number
    lastTactics: Tactic[]
    teams: Team[]
}) {
    return (
        <div
            id="side-menu"
            style={{
                width: width + "%",
            }}>
            <div id="side-menu-content">
                <Team teams={teams} />
                <Tactic lastTactics={lastTactics} />
            </div>
        </div>
    )
}

function PersonalSpace({
    width,
    allTactics,
    teams,
    sharedTactics,
}: {
    width: number
    allTactics: Tactic[]
    teams: Team[]
    sharedTactics: Tactic[]
}) {
    return (
        <div
            id="personal-space"
            style={{
                width: width + "%",
            }}>
            <TitlePersonalSpace />
            <BodyPersonalSpace allTactics={allTactics} teams={teams} sharedTactics={sharedTactics}/>
        </div>
    )
}

function TitlePersonalSpace() {
    return (
        <div id="title-personal-space">
            <h2>Espace Personnel</h2>
        </div>
    )
}

function TableData({ allTactics, teams, isShared }: { allTactics: Tactic[], teams : Team[], isShared: boolean }) {
    const nbRow = Math.floor(allTactics.length / 3 + 1)
    const listTactic = Array(nbRow)
    for (let i = 0; i < nbRow; i++) {
        listTactic[i] = Array(0)
    }
    let i = 0
    let j = 0
    allTactics.forEach((tactic) => {
        listTactic[i].push(tactic)
        j++
        if (j === 3) {
            i++
            j = 0
        }
    })

    i = 0
    while (i < nbRow) {
        listTactic[i] = listTactic[i].map((tactic: Tactic, index: number) => (
            <DraggableTableDataElement
                key={index}
                tactic={tactic}
                teams={teams}
                isShared={isShared}
            />
        ))
        i++
    }
    if (nbRow == 1) {
        if (listTactic[0].length < 3) {
            for (let i = 0; i <= 3 - listTactic[0].length; i++) {
                listTactic[0].push(<td key={"tdNone" + i}></td>)
            }
        }
    }

    return listTactic.map((tactic, rowIndex) => (
        <tr key={rowIndex + "row"}>{tactic}</tr>
    ))
}

function DraggableTableDataElement({
                                       tactic,
                                       teams,
    isShared,
                                   }: {
    tactic: Tactic
    teams: Team[]
    isShared: boolean
}) {
    const ref = useRef<HTMLDivElement>(null)
    const [dragging, setDragging] = useState(false)
    const [hovered, setHovered] = useState(false)

    const handleButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
        event.stopPropagation()
        if (!dragging) {
            const userEmail = window.prompt(
                "Entrez l'email à qui partager la tactique :",
            )
            if (userEmail != null) {
                onShareTactic(userEmail, tactic)
            }
        } else {
            setDragging(false)
        }
    }

    const navigate = useNavigate()

    return (
        <Draggable
            position={NULL_POS}
            nodeRef={ref}
            onDrag={() => setDragging(true)}
            onStop={() => {
                if (dragging) {
                    if (ref.current) {
                        onDropTactic(
                            ref.current.getBoundingClientRect(),
                            tactic,
                            teams,
                        )
                    }
                }
            }}>
            <td
                key={tactic.id}
                ref={ref as RefObject<HTMLTableDataCellElement>}
                className="data"
                onClick={() => {
                    if (!dragging) {
                        navigate("/tactic/" + tactic.id + "/edit")
                    } else {
                        setDragging(false)
                    }
                }}
                onMouseEnter={() => setHovered(true)}
                onMouseLeave={() => setHovered(false)}>
                {truncateString(tactic.name, 25)}
                {hovered && (
                    <div className="share-icon-container">
                        <button
                            className="share-button share-icon-button"
                            onClick={handleButtonClick}>
                            <FaShare className="share-icon" />
                        </button>
                    </div>
                )}
            </td>
        </Draggable>
    )
}

function BodyPersonalSpace({ allTactics, teams, sharedTactics }: { allTactics: Tactic[], teams: Team[], sharedTactics: Tactic[]}) {
    return (
        <div id="body-personal-space">
            {allTactics.length == 0 ? (
                <p>Aucune tactique créée !</p>
            ) : (
                <table>
                    <tbody key="tbody">
                        <TableData allTactics={allTactics} teams={teams} isShared={false}/>
                        <TableData allTactics={sharedTactics} teams={teams} isShared={true}/>
                    </tbody>
                </table>
            )}
        </div>
    )
}

function Team({ teams }: { teams: Team[] }) {
    const navigate = useNavigate()
    return (
        <div id="teams">
            <div className="titre-side-menu">
                <h2 className="title">Mes équipes</h2>
                <button className="new" onClick={() => navigate("/team/new")}>
                    +
                </button>
            </div>
            <SetButtonTeam teams={teams} />
        </div>
    )
}

function Tactic({ lastTactics }: { lastTactics: Tactic[] }) {
    const navigate = useNavigate()

    return (
        <div id="tactic">
            <div className="titre-side-menu">
                <h2 className="title">Mes dernières tactiques</h2>
                <button
                    className="new"
                    id="create-tactic"
                    onClick={() => navigate("/tactic/new")}>
                    +
                </button>
            </div>
            <SetButtonTactic tactics={lastTactics} />
        </div>
    )
}

function SetButtonTactic({ tactics }: { tactics: Tactic[] }) {
    const lastTactics = tactics.map((tactic) => (
        <ButtonLastTactic key={tactic.id} tactic={tactic} />
    ))
    return <div className="set-button">{lastTactics}</div>
}

function SetButtonTeam({ teams }: { teams: Team[] }) {
    const listTeam = teams.map((team) => (
        <ButtonTeam key={team.id} team={team} />
    ))
    return <div className="set-button">{listTeam}</div>
}

function ButtonTeam({ team }: { team: Team }) {
    const name = truncateString(team.name, 20)
    const navigate = useNavigate()

    return (
        <div>
            <div
                id={"button-team" + team.id}
                className="button-side-menu data"
                onClick={() => {
                    navigate("/team/" + team.id)
                }}>
                {name}
            </div>
        </div>
    )
}

function ButtonLastTactic({ tactic }: { tactic: Tactic }) {
    const name = truncateString(tactic.name, 20)
    const navigate = useNavigate()

    return (
        <div
            id={"button" + tactic.id}
            className="button-side-menu data"
            onClick={() => {
                navigate("/tactic/" + tactic.id + "/edit")
            }}>
            {name}
        </div>
    )
}

function truncateString(name: string, limit: number): string {
    if (name.length > limit) {
        name = name.substring(0, limit) + "..."
    }
    return name
}


function onDropTactic(ref: DOMRect, tactic: Tactic, teams: Team[]) {
    let shared = false
    for (const team of teams) {
        if (
            contains(
                ref,
                document
                    .getElementById(`button-team-${team.id}`)!
                    .getBoundingClientRect(),
            )
        ) {
            if (!shared) {
                shareTacticToTeam(tactic, team)
                shared = true
            }
        }
    }
}

async function onShareTactic(email: string, tactic: Tactic) {
    const fetcher = useAppFetcher()
    const [user, ] = useUser()

    useEffect(() => {
        async function shareTactic() {
            const response = await fetcher.fetchAPI("user/share-tactic", {tacticId: tactic.id, userId: user})
        }
        shareTactic()
    }, [fetcher])
}

async function shareTacticToTeam(tactic: Tactic, team: Team) {
    const fetcher = useAppFetcher()

    if (
        confirm(
            "Etes-vous sûr de vouloir partager la tactique " +
            tactic.name +
            " avec l'équipe " +
            team.name,
        )
    ) {
        useEffect(() => {
            async function shareTacticToTeam() {
                const response = await fetcher.fetchAPI("team/share-tactic", {tacticId: tactic.id, teamId: team.id})
            }
            shareTacticToTeam()
        }, [fetcher])
    }
}
