import {jsPDF} from 'jspdf'
import {useCardsStatic} from "../hooks/useCard.jsx";
import {
    CatList,
    getCatName,
    getShieldSize,
    getShieldTypeName,
    getSwordSize,
    getSwordTypeName,
    sortCategories,
    timePrint,
    virtualScore,
    win_end
} from "./Tools.js";
import {getMandatoryProtectionsList} from "../components/ProtectionSelector.jsx";
import {scoreToString2} from "./CompetitionTools.js";
import {TreeNode} from "./TreeUtils.js";
import {drawGraphForPdf} from "../pages/result/DrawGraph.jsx";
import autoTable from 'jspdf-autotable'

function combName(getComb, combId) {
    if (!combId)
        return "  "
    const comb = getComb(combId, null);
    if (comb) {
        if (comb.lname === "__team")
            return `${comb.fname}`
        return `${comb.fname} ${comb.lname}`
    } else {
        return `[Comb #${combId}]`
    }
}

export function makePDF(action, pagesList, name, c_name, getComb, t, logo) {
    //https://github.com/parallax/jsPDF/blob/ddbfc0f0250ca908f8061a72fa057116b7613e78/jspdf.js#L59
    const doc = new jsPDF('p', 'pt', 'a4');
    doc.setProperties({title: name, author: "FFSAF - Intranet", subject: c_name + " - " + name, creator: "FFSAF - Intranet"});

    for (let i = 0; i < pagesList.length; i++) {
        const context = {pdf_doc: doc, pdf_name: name, c_name, getComb, t, ...pagesList[i].params, logo}
        switch (pagesList[i].type) {
            case "categorie":
                generateCategoriePDF(context);
                break;
            case "podium":
                generatePodium(context);
                break;
            case "podiumClub":
                generateClubPodium(context);
                break;
            default:
                break
        }
        if (i !== pagesList.length - 1)
            doc.addPage();
    }

    switch (action) {
        case "show":
            window.open(doc.output('bloburl', {filename: name + '.pdf'}));
            break;
        case "print":
            const iframe = document.createElement('iframe'); //load content in an iframe to print later
            document.body.appendChild(iframe);

            iframe.style.display = 'none';
            iframe.src = doc.output('bloburl', {filename: name + '.pdf'});
            iframe.onload = function () {
                setTimeout(function () {
                    iframe.focus();
                    iframe.contentWindow.print();
                }, 1);
            };
            break;
        case "download":
        default:
            doc.save(name + '.pdf');
            break;
    }
}

function matchList(pdf_doc, matches, cat, cards_v, classement, getComb, t) {
    const {getHeightCardForCombInMatch} = useCardsStatic(cards_v);
    const liceName = (cat.liceName || "N/A").split(";");

    const getBG = (combId, match) => {
        const c = getHeightCardForCombInMatch(combId, match)
        if (!c)
            return ""
        let bg = "";
        let text = "#000";
        switch (c.type) {
            case "YELLOW":
                bg = "#ffc107";
                break;
            case "RED":
                bg = "#dc3545";
                text = "#FFF";
                break;
            case "BLACK":
                bg = "#000000";
                text = "#FFF";
                break;
            case "BLUE":
                bg = "#0d6efd";
                text = "#FFF";
                break;
        }
        return {fillColor: bg, textColor: text}
    }

    const head = [
        ...(classement ? [
            {content: t('place', {ns: "result"}), styles: {halign: "center"}},
        ] : [
            {content: t('no'), styles: {halign: "center"}},
            {content: t('poule'), styles: {halign: "center"}},
            {content: t('zone'), styles: {halign: "center"}},
        ]),
        {content: "", styles: {halign: "center"}},
        {content: t('rouge'), styles: {halign: "center"}},
        {content: t('résultat'), styles: {halign: "center"}},
        {content: t('blue'), styles: {halign: "center"}},
        {content: "", styles: {halign: "center"}},
    ]

    const body = matches.map((m, index) => ([
        ...(classement ? [
            {content: `${m.categorie_ord + 1}-${m.categorie_ord + 2}`, styles: {halign: "center", padding: "2pt 0"}}
        ] : [
            {content: index + 1, styles: {halign: "center", padding: "2pt 0"}},
            {content: m.poule, styles: {halign: "center"}},
            {content: liceName[index % liceName.length], styles: {halign: "center"}},
        ]),
        {content: m.end ? (m.win > 0 ? "X" : (m.win === 0 ? "-" : "")) : "  ", styles: {halign: "center", ...getBG(m.c1, m)}},
        {content: combName(getComb, m.c1), styles: {halign: "center", minWidth: "11em", paddingLeft: "0.2em"}},
        {content: scoreToString2(m, cards_v), styles: {halign: "center"}},
        {content: combName(getComb, m.c2), styles: {halign: "center", minWidth: "11em", paddingRight: "0.2em"}},
        {content: m.end ? (m.win < 0 ? "X" : (m.win === 0 ? "-" : "")) : "  ", styles: {halign: "center", ...getBG(m.c2, m)}},
    ]))

    autoTable(pdf_doc, {
        startY: pdf_doc.lastAutoTable.finalY + 7,
        styles: {fontSize: 10, cellPadding: 3},
        columnStyles: classement ? {
            0: {cellWidth: 35},
            1: {cellWidth: 15},
            2: {cellWidth: "auto"},
            3: {cellWidth: 110},
            4: {cellWidth: "auto"},
            5: {cellWidth: 15},
        } : {
            0: {cellWidth: 20},
            1: {cellWidth: 35},
            2: {cellWidth: 30},
            3: {cellWidth: 15},
            4: {cellWidth: "auto"},
            5: {cellWidth: 110},
            6: {cellWidth: "auto"},
            7: {cellWidth: 15},
        },
        head: [head],
        body: body,
        theme: 'grid',
    })
}

function buildTree(pdf_doc, treeData, treeRaw, matches, cat, cards_v, getComb, t, categorieEmpty, comb_count = 0) {
    function parseTree(data_in) {
        if (data_in?.data == null)
            return null

        const matchData = matches.find(m => m.id === data_in.data)
        const c1 = categorieEmpty ? null : getComb(matchData?.c1)
        const c2 = categorieEmpty ? null : getComb(matchData?.c2)

        const scores2 = []
        for (const score of matchData?.scores) {
            scores2.push({
                ...score,
                s1: virtualScore(matchData?.c1, score, matchData, cards_v),
                s2: virtualScore(matchData?.c2, score, matchData, cards_v)
            })
        }

        let node = new TreeNode({
            ...matchData,
            ...win_end(matchData, cards_v),
            scores: scores2,
            c1FullName: c1 !== null ? c1.fname + " " + c1.lname : null,
            c2FullName: c2 !== null ? c2.fname + " " + c2.lname : null
        })
        node.left = parseTree(data_in?.left)
        node.right = parseTree(data_in?.right)

        return node
    }


    let out = []
    for (let i = 0; i < treeRaw.length; i++) {
        if (treeRaw.at(i).level > -10) {
            out.push(parseTree(treeData.at(i)))
        }
    }

    const canvas = drawGraphForPdf(out, 24, cards_v)
    const imgData = canvas.toDataURL('image/png');
    const height = canvas.height * (pdf_doc.internal.pageSize.getWidth() - 80) / canvas.width;
    pdf_doc.addImage(imgData, 'PNG', 40, pdf_doc.lastAutoTable.finalY, pdf_doc.internal.pageSize.getWidth() - 80, height);

    pdf_doc.lastAutoTable.finalY += height;

    if (cat.fullClassement) {
        let size = 0;
        if (out.length > 0)
            size = out[0].getMaxChildrenAtDepth(out[0].death() - 1)

        const matches2 = cat.raw_trees?.filter(n => n.level <= -10).reverse().map(d => categorieEmpty ? ({}) : matches.find(m => m.id === d.match?.id))
        if (matches2.length === 0) {
            while (Math.ceil(comb_count / 2) - size > matches2.length)
                matches2.push({})
        }

        matches2.forEach((v, i) => {
            v.categorie_ord = (i + size) * 2
        })

        matchList(pdf_doc, matches2, cat, cards_v, true, getComb, t)
    }
}

function pouleList(pdf_doc, groups, getComb, t) {
    const groups2 = groups.map(g => {
        const comb = getComb(g.id);
        return {...g, name: comb ? comb.fname + " " + comb.lname : "", teamMembers: comb ? comb.teamMembers : []};
    }).sort((a, b) => {
        if (a.poule !== b.poule) {
            if (a.poule === '-') return 1;
            if (b.poule === '-') return -1;
            return a.poule.localeCompare(b.poule);
        }
        return a.name.localeCompare(b.name);
    }).reduce((acc, curr) => {
        const poule = curr.poule;
        if (!acc[poule]) {
            acc[poule] = [];
        }
        acc[poule].push(curr);
        return acc;
    }, {});

    autoTable(pdf_doc, {
        startY: pdf_doc.lastAutoTable.finalY + 7,
        styles: {fontSize: 10, cellPadding: 3},
        head: [Object.keys(groups2).map((poule) => ({content: `${t('poule')} ${poule}`, styles: {halign: "center"}}))],
        body: [Object.keys(groups2).map((poule) => ({
            content: groups2[poule].map(o => o.name).join(", "),
            styles: {halign: "center", valign: "middle"}
        }))],
        theme: 'grid',
    })
}

function makeHeader(pdf_doc, c_name, p_name, logo) {
    autoTable(pdf_doc, {
        startY: 20,
        body: [[
            {content: "", src: `${logo}`, rowSpan: 2, styles: {halign: 'center', valign: 'middle'}},
            {content: c_name, colSpan: 3, styles: {halign: "center", valign: 'middle', fontSize: 20}},
        ], [
            {content: p_name, colSpan: 3, styles: {halign: "center", valign: 'middle', fontSize: 20}}
        ]],
        theme: 'plain',
        columnStyles: {
            0: {cellWidth: 60, minCellHeight: 60},
        },
        didDrawCell: function (data) {
            if (data.column.index === 0 && data.row.index === 0) {
                const dim = data.cell.height - data.cell.padding('vertical');
                const textPos = data.cell;
                pdf_doc.addImage(data.cell.raw.src, textPos.x, textPos.y + data.cell.padding('vertical') / 2, dim, dim);
            }
        }
    })
}

function generateCategoriePDF({pdf_doc, cat, matches, groups, getComb, cards_v, c_name, categorieEmpty, t, logo}) {
    let catAverage = "---";
    let genreAverage = "H";
    let nbComb = 0;
    let time = 0;

    const marches2 = matches.filter(m => m.categorie === cat.id)
        .map(m => categorieEmpty ? ({...m, end: false, scores: []}) : m)

    if (marches2.length !== 0) {
        const genres = [];
        const cats = [];
        const combs_ = [];
        for (const m of marches2) {
            if (m.c1 && !combs_.includes(m.c1))
                combs_.push(m.c1);
            if (m.c2 && !combs_.includes(m.c2))
                combs_.push(m.c2);
        }

        combs_.map(cId => getComb(cId, null)).filter(c => c && c.categorie)
            .forEach(c => {
                cats.push(Math.min(CatList.length, CatList.indexOf(c.categorie) + c.overCategory))
                genres.push(c.genre)
            });

        const catAvg = Math.round(cats.reduce((a, b) => a + b, 0) / cats.length);

        nbComb = combs_.length;
        catAverage = CatList.at(catAvg) || "---";
        genreAverage = Math.round(genres.reduce((a, b) => a + (b === "F" ? 1 : 0), 0) / genres.length) > 0.5 ? "F" : "H";

        if (cat.preset && cat.preset.categories) {
            const catAvailable = cat.preset.categories.map(c => CatList.indexOf(c.categorie));
            let p;
            if (catAvailable.includes(catAvg)) {
                p = cat.preset.categories.find(c => CatList.indexOf(c.categorie) === catAvg);
            } else {
                p = cat.preset.categories.find(c => CatList.indexOf(c.categorie) ===
                    catAvailable.reduce((a, b) => Math.abs(b - catAvg) < Math.abs(a - catAvg) ? b : a));
            }
            time = {round: p.roundDuration, pause: p.pauseDuration}
        }
    }

    makeHeader(pdf_doc, c_name, cat.name, logo)

    autoTable(pdf_doc, {
        startY: pdf_doc.lastAutoTable.finalY,
        styles: {fontSize: 10, cellPadding: 3},
        body: [[
            {content: `${t('catégorieDâgeMoyenne')} : ${getCatName(catAverage)}`, styles: {halign: "left"}},
            {
                content: `${t('arme', {ns: 'common'})} : ${getSwordTypeName(cat.preset?.sword)} - ${t('taille')} ${getSwordSize(cat.preset?.sword, catAverage, genreAverage)}`,
                styles: {halign: "left"}
            },
            {
                content: `${t('bouclier', {ns: 'common'})} : ${getShieldTypeName(cat.preset?.shield)} - ${t('taille')} ${getShieldSize(cat.preset?.shield, catAverage)}`,
                styles: {halign: "left"}
            },
        ], [
            {content: `${t('duréeRound')} : ${timePrint(time.round)}`, styles: {halign: "left"}},
            {content: `${t('duréePause')} : ${timePrint(time.pause)}`, styles: {halign: "left"}},
            {content: `${t('nombreDeCombattants')} : ${nbComb}`, styles: {halign: "left"}},
        ], [
            {
                content: `${t('protectionObligatoire', {ns: 'common'})} ${getMandatoryProtectionsList(CatList.indexOf(catAverage) <= CatList.indexOf("JUNIOR") ?
                    cat.preset?.mandatoryProtection1 : cat.preset?.mandatoryProtection2, cat.preset?.shield, t).join(", ") || "---"}`,
                colSpan: 3,
                styles: {halign: "left"}
            },
        ]],
        theme: 'grid',
    })

    pouleList(pdf_doc, groups, getComb, t)

    if ((cat.type & 1) === 1)
        matchList(pdf_doc, marches2.filter(m => m.categorie_ord !== -42).sort((a, b) => a.categorie_ord - b.categorie_ord),
            cat, categorieEmpty ? [] : cards_v, false, getComb, t)

    if ((cat.type & 2) === 2) {
        pdf_doc.setFontSize(12);
        pdf_doc.text((cat.treeAreClassement ? t('classement') : t('tournois')) + ':', 40, pdf_doc.lastAutoTable.finalY + 16)
        pdf_doc.lastAutoTable.finalY += 16;
        buildTree(pdf_doc, cat.trees, cat.raw_trees, marches2, cat, categorieEmpty ? [] : cards_v, getComb, t, categorieEmpty, nbComb)
    }
}

function generatePodium({pdf_doc, data, t, logo, c_name, minRank = 4, maxRank = 4}) {
    makeHeader(pdf_doc, c_name, t('podium'), logo)

    const data2 = data.sort((a, b) => {
        let tmp = sortCategories(a.categorie, b.categorie);
        if (tmp !== 0)
            return tmp;
        return a.poule_name.localeCompare(b.poule_name)
    })

    let finalY2 = pdf_doc.lastAutoTable.finalY;
    let finalY3 = pdf_doc.lastAutoTable.finalY;
    for (let i = 0; i < data2.length; i++) {
        const p = data2[i];
        let pageNumber = pdf_doc.internal.getNumberOfPages()

        const body = Array.from({length: minRank}, () => []);
        for (const c of p.podium) {
            if (c.rank > maxRank)
                continue;

            if (body[c.rank - 1])
                body[c.rank - 1].push(c.name)
            else
                body[c.rank - 1] = [c.name]
        }
        for (let j = 0; j < body.length; j++) {
            if (body[j].length === 0)
                body[j].push("  ")
            body[j] = [
                {content: j + 1, styles: {halign: "center"}},
                {content: body[j].join(", "), styles: {halign: "center"}}
            ]
        }

        autoTable(pdf_doc, {
            startY: finalY3 + 7,
            margin: i % 2 ? {left: pdf_doc.internal.pageSize.getWidth() / 2 + 7} : {right: pdf_doc.internal.pageSize.getWidth() / 2 + 7},
            styles: {fontSize: 10, cellPadding: 3},
            columnStyles: {
                0: {cellWidth: 35},
                1: {cellWidth: "auto"},
            },
            pageBreak: "avoid",
            showHead: 'firstPage',
            head: [[
                {content: p.poule_name, colSpan: 2, styles: {halign: "center"}},
            ], [
                {content: t('place', {ns: "result"}), styles: {halign: "center"}},
                {content: t('combattants', {ns: 'result'}), styles: {halign: "center"}},
            ]],
            body: body,
            foot: [[
                {content: t('source') + " : " + p.source, colSpan: 2, styles: {halign: "left", fontSize: 8}},
            ]],
            rowPageBreak: 'auto',
            theme: 'grid',
        })

        if (i % 2 === 0) {
            finalY2 = pdf_doc.lastAutoTable.finalY;
            if (pageNumber !== pdf_doc.internal.getNumberOfPages())
                finalY3 = 33
        } else {
            pdf_doc.lastAutoTable.finalY = Math.max(finalY2, pdf_doc.lastAutoTable.finalY);
            finalY3 = pdf_doc.lastAutoTable.finalY;
        }
    }
    pdf_doc.lastAutoTable.finalY = Math.max(finalY2, pdf_doc.lastAutoTable.finalY);
}

function generateClubPodium({pdf_doc, data, t, logo, c_name}) {
    makeHeader(pdf_doc, c_name, t('podiumDesClubs'), logo)

    const body = data.map(c => [
        {content: [c.name], styles: {halign: "center"}},
        {content: c.score[0], styles: {halign: "center"}},
        {content: c.score[1], styles: {halign: "center"}},
        {content: c.score[2], styles: {halign: "center"}},
        {content: c.tt_score, styles: {halign: "center"}},
    ]);

    let rank = 0;
    let lastScores = null;
    let lastB = null;
    for (const b of body) {
        const scores = [b[1].content, b[2].content, b[3].content, b[4].content];
        if (lastScores !== scores) {
            rank++;
            b.unshift({content: rank, styles: {halign: "center"}})
            lastB = b
        } else {
            lastB[1].content.push(b[0].content);
            delete body.indexOf(b);
        }
    }
    for (const b of body) {
        b[1].content = b[1].content.join(", ")
    }

    autoTable(pdf_doc, {
        startY: pdf_doc.lastAutoTable.finalY + 7,
        styles: {fontSize: 10, cellPadding: 3},
        columnStyles: {
            0: {cellWidth: 35},
            1: {cellWidth: "auto"},
            2: {cellWidth: 45},
            3: {cellWidth: 45},
            4: {cellWidth: 45},
            5: {cellWidth: 40},
        },
        pageBreak: "avoid",
        showHead: 'firstPage',
        head: [[
            {content: t('place', {ns: "result"}), styles: {halign: "center"}},
            {content: t('club', {ns: 'result'}), styles: {halign: "center"}},
            {content: t('1er', {ns: 'result'}), styles: {halign: "center"}},
            {content: t('2eme', {ns: 'result'}), styles: {halign: "center"}},
            {content: t('3eme', {ns: 'result'}), styles: {halign: "center"}},
            {content: t('scores', {ns: 'result'}), styles: {halign: "center"}},
        ]],
        body: body,
        rowPageBreak: 'auto',
        theme: 'grid',
    })
}
