// 等待G6加载完成后再注册自定义节点
function registerCustomNode() {
    if (typeof window.G6 === 'undefined') {
        console.log('G6库尚未加载，100ms后重试...');
        setTimeout(registerCustomNode, 100);
        return;
    }

    console.log('G6库已加载，开始注册自定义节点...');

    G6.registerNode(
        'hexagon-card',
    {
        draw(cfg, group) {
            const size = Array.isArray(cfg.size)
                ? cfg.size[0]
                : cfg.size || 110;
            const mastery = Math.max(
                0,
                Math.min(1, cfg.meta?.mastery_level ?? 0)
            );
            const hasMastery = Boolean(cfg.meta?.has_mastery);
            const percent = Math.round(mastery * 100);
            const locked = cfg.locked || false;
            const recommended = cfg.meta?.recommended;
            const hexagonPath = this.getHexagonPath(size);
            const palette = this.getPalette(mastery, locked, hasMastery);

            const ring = group.addShape('path', {
                attrs: {
                    path: hexagonPath,
                    stroke: palette.ring,
                    lineWidth: palette.ringWidth,
                    opacity: palette.ringOpacity,
                },
                name: 'ring-shape',
            });

            const hexagon = group.addShape('path', {
                attrs: {
                    path: hexagonPath,
                    fill: palette.fill,
                    stroke: palette.stroke,
                    lineWidth: palette.lineWidth,
                    shadowColor: palette.shadow,
                    shadowBlur: palette.shadow ? 12 : 0,
                    opacity: locked ? 0.55 : hasMastery ? 1 : 0.6,
                    cursor: locked ? 'not-allowed' : 'pointer',
                },
                name: 'hexagon-shape',
                draggable: true,
            });

            const cardWidth = size * 0.82;
            const cardHeight = size * 0.64;
            group.addShape('rect', {
                attrs: {
                    x: -cardWidth / 2,
                    y: -cardHeight / 2,
                    width: cardWidth,
                    height: cardHeight,
                    fill: palette.cardFill,
                    radius: 6,
                    opacity: locked ? 0.75 : hasMastery ? 0.95 : 0.6,
                    shadowColor: 'rgba(15, 23, 42, 0.12)',
                    shadowBlur: 8,
                },
                name: 'card-shape',
            });

            group.addShape('text', {
                attrs: {
                    text: `${cfg.id} · ${cfg.label || cfg.meta?.name || cfg.meta?.code || cfg.id}`,
                    x: 0,
                    y: -10,
                    fontSize: 22,
                    fontWeight: 800,
                    fill: locked ? '#94a3b8' : '#0f172a',
                    textAlign: 'center',
                    textBaseline: 'middle',
                },
                name: 'title-text',
            });

            group.addShape('text', {
                attrs: {
                    text: cfg.meta?.code || cfg.id,
                    x: 0,
                    y: 10,
                    fontSize: 15,
                    fontWeight: 700,
                    fill: '#334155',
                    textAlign: 'center',
                    textBaseline: 'middle',
                },
                name: 'code-text',
            });

            const barWidth = cardWidth - 16;
            const barHeight = 8;
            const barY = cardHeight / 2 - 4;

            group.addShape('text', {
                attrs: {
                    text: '掌握度',
                    x: -barWidth / 2,
                    y: barY - 10,
                    fontSize: 12,
                    fontWeight: 700,
                    fill: '#334155',
                    textAlign: 'left',
                    textBaseline: 'middle',
                },
                name: 'mastery-label',
            });

            group.addShape('rect', {
                attrs: {
                    x: -barWidth / 2,
                    y: barY,
                    width: barWidth,
                    height: barHeight,
                    fill: '#e5e7eb',
                    radius: 3,
                },
                name: 'progress-bg',
            });

            group.addShape('rect', {
                attrs: {
                    x: -barWidth / 2,
                    y: barY,
                    width: (barWidth * percent) / 100,
                    height: barHeight,
                    fill: palette.progress,
                    radius: 3,
                },
                name: 'progress-fill',
            });

            group.addShape('text', {
                attrs: {
                    text: `${percent}%`,
                    x: 0,
                    y: barY + barHeight / 2,
                    fontSize: 12,
                    fontWeight: 800,
                    fill: '#0f172a',
                    textAlign: 'center',
                    textBaseline: 'middle',
                },
                name: 'percent-text',
            });

            if (recommended && !locked) {
                group.addShape('circle', {
                    attrs: {
                        x: cardWidth / 2 - 8,
                        y: -cardHeight / 2 + 10,
                        r: 8,
                        fill: 'rgba(251, 191, 36, 0.15)',
                        stroke: '#f59e0b',
                    },
                    name: 'recommend-pill',
                });
                group.addShape('text', {
                    attrs: {
                        text: '荐',
                        x: cardWidth / 2 - 8,
                        y: -cardHeight / 2 + 10,
                        fontSize: 12,
                        fontWeight: 700,
                        fill: '#b45309',
                        textAlign: 'center',
                        textBaseline: 'middle',
                    },
                    name: 'recommend-text',
                });
            }

            if (locked) {
                group.addShape('rect', {
                    attrs: {
                        x: -cardWidth / 2,
                        y: -cardHeight / 2,
                        width: cardWidth,
                        height: cardHeight,
                        fill: '#ffffff',
                        opacity: 0.4,
                    },
                    name: 'lock-mask',
                });
                group.addShape('text', {
                    attrs: {
                        text: '🔒',
                        x: 0,
                        y: 0,
                        fontSize: 16,
                        textAlign: 'center',
                        textBaseline: 'middle',
                    },
                    name: 'lock-icon',
                });
            }

            if (percent < 40) {
                group.addShape('rect', {
                    attrs: {
                        x: -cardWidth / 2,
                        y: -cardHeight / 2,
                        width: cardWidth,
                        height: cardHeight,
                        fill: '#ffffff',
                        opacity: 0.15,
                    },
                    name: 'weak-mask',
                });
            }

            return hexagon;
        },

        setState(name, value, item) {
            const group = item.getContainer();
            const hexagon = group.find((e) => e.get('name') === 'hexagon-shape');
            if (!hexagon) return;

            if (name === 'hover') {
                hexagon.animate(
                    { lineWidth: value ? 4 : 3 },
                    { duration: 180 }
                );
                group.animate(
                    (ratio) => ({
                        matrix: [
                            1 + (value ? ratio * 0.05 : -ratio * 0.05),
                            0,
                            0,
                            0,
                            1 + (value ? ratio * 0.05 : -ratio * 0.05),
                            0,
                            0,
                            0,
                            1,
                        ],
                    }),
                    { duration: 200 }
                );
            }

            if (name === 'selected') {
                hexagon.attr('shadowColor', value ? '#fb923c' : undefined);
                hexagon.attr('shadowBlur', value ? 16 : 0);
            }

            if (name === 'weak') {
                hexagon.attr('opacity', value ? 0.75 : 1);
            }

            if (name === 'locked') {
                hexagon.attr('opacity', value ? 0.5 : 1);
                hexagon.attr('cursor', value ? 'not-allowed' : 'pointer');
            }
        },

        getPalette(mastery, locked, hasMastery) {
            if (!hasMastery) {
                return {
                    stroke: '#cbd5e1',
                    lineWidth: 3,
                    ring: '#e2e8f0',
                    ringWidth: 6,
                    ringOpacity: 0.35,
                    shadow: 'rgba(148, 163, 184, 0.15)',
                    progress: '#e5e7eb',
                    fill: '#f8fafc',
                    cardFill: '#ffffff',
                };
            }

            if (mastery >= 0.8) {
                return {
                    stroke: '#d3b55f',
                    lineWidth: 4,
                    ring: '#f7e4ad',
                    ringWidth: 8,
                    ringOpacity: 0.55,
                    shadow: 'rgba(212, 181, 95, 0.28)',
                    progress: '#22c55e',
                    fill: '#fffbeb',
                    cardFill: '#ffffff',
                };
            }

            if (mastery >= 0.6) {
                return {
                    stroke: '#34d399',
                    lineWidth: 3.5,
                    ring: '#bbf7d0',
                    ringWidth: 7,
                    ringOpacity: 0.45,
                    shadow: 'rgba(52, 211, 153, 0.25)',
                    progress: '#34d399',
                    fill: '#ecfdf3',
                    cardFill: '#ffffff',
                };
            }

            if (mastery >= 0.4) {
                return {
                    stroke: '#f59e0b',
                    lineWidth: 3.5,
                    ring: '#fde68a',
                    ringWidth: 7,
                    ringOpacity: 0.45,
                    shadow: 'rgba(245, 158, 11, 0.18)',
                    progress: '#f59e0b',
                    fill: '#fffbeb',
                    cardFill: '#fff7ed',
                };
            }

            return {
                stroke: '#f87171',
                lineWidth: 3,
                ring: '#fecaca',
                ringWidth: 8,
                ringOpacity: 0.55,
                shadow: 'rgba(248, 113, 113, 0.25)',
                progress: '#f87171',
                fill: '#fef2f2',
                cardFill: '#fff1f2',
            };
        },

        getHexagonPath(size) {
            const r = size / 2;
            const points = [];
            for (let i = 0; i < 6; i++) {
                const angle = (Math.PI / 3) * i - Math.PI / 2;
                points.push([r * Math.cos(angle), r * Math.sin(angle)]);
            }
            return [
                ['M', points[0][0], points[0][1]],
                ...points.slice(1).map((p) => ['L', p[0], p[1]]),
                ['Z'],
            ];
        },

        update(cfg, item) {
            const group = item.getContainer();
            const size = Array.isArray(cfg.size) ? cfg.size[0] : cfg.size || 110;
            const mastery = Math.max(
                0,
                Math.min(1, cfg.meta?.mastery_level ?? 0)
            );
            const hasMastery = Boolean(cfg.meta?.has_mastery);
            const percent = Math.round(mastery * 100);
            const locked = cfg.locked || false;
            const palette = this.getPalette(mastery, locked, hasMastery);

            const ring = group.find((e) => e.get('name') === 'ring-shape');
            if (ring) {
                ring.attr({
                    stroke: palette.ring,
                    lineWidth: palette.ringWidth,
                    opacity: palette.ringOpacity,
                });
            }

            const hexagon = group.find((e) => e.get('name') === 'hexagon-shape');
            if (hexagon) {
                hexagon.attr({
                    stroke: palette.stroke,
                    lineWidth: palette.lineWidth,
                    shadowColor: palette.shadow,
                    shadowBlur: palette.shadow ? 12 : 0,
                    opacity: locked ? 0.55 : hasMastery ? 1 : 0.6,
                    cursor: locked ? 'not-allowed' : 'pointer',
                    fill: palette.fill,
                });
            }

            const title = group.find((e) => e.get('name') === 'title-text');
            if (title) {
                title.attr({
                    text: `${cfg.id} · ${cfg.label || cfg.meta?.name || cfg.meta?.code || cfg.id}`,
                    fill: locked ? '#94a3b8' : '#0f172a',
                });
            }

            const codeText = group.find((e) => e.get('name') === 'code-text');
            if (codeText) {
                codeText.attr({
                    text: cfg.meta?.code || cfg.id,
                });
            }

            const progressFill = group.find((e) => e.get('name') === 'progress-fill');
            const progressBg = group.find((e) => e.get('name') === 'progress-bg');
            if (progressFill && progressBg) {
                const cardWidth = size * 0.82;
                const barWidth = cardWidth - 16;
                progressFill.attr({
                    width: (barWidth * percent) / 100,
                    fill: palette.progress,
                });
            }

            const card = group.find((e) => e.get('name') === 'card-shape');
            if (card) {
                card.attr({
                    fill: palette.cardFill,
                });
            }

            const percentText = group.find((e) => e.get('name') === 'percent-text');
            if (percentText) {
                percentText.attr({
                    text: `${percent}%`,
                });
            }
        },
    },
    'single-node'
);

    console.log('自定义节点注册完成');
}

// 启动注册流程
registerCustomNode();
