import React, { useEffect, useRef, useState, useContext } from 'react';
import { PlayerDataContext, SocketContext } from '../../../App';

import mapImage from '../../../images/map.jpg';
import positionMapCoords from '../positions';
import pawnImages from '../../../constants/pawnImages';
import canPawnMove from './canPawnMove';
import getPositionAfterMove from './getPositionAfterMove';
import { pawnsAt } from './pawnHelpers';

const Map = ({ pawns, nowMoving, rolledNumber }) => {
    const player = useContext(PlayerDataContext);
    const socket = useContext(SocketContext);
    const canvasRef = useRef(null);

    const [hintPawn, setHintPawn] = useState();

    const paintPawn = (context, pawn, x, y, pawnWidth = 28, onDraw) => {
        const pawnHeight = Math.round((pawnWidth * 30) / 35);
        const touchableArea = new Path2D();
        const touchRadius = Math.max(6, Math.round(pawnWidth / 2));
        touchableArea.arc(x, y, touchRadius, 0, 2 * Math.PI);
        const image = new Image();
        const imgSrc = pawnImages[pawn.color] || pawnImages['red'];
        image.src = imgSrc;

        const drawAndCallback = () => {
            context.drawImage(image, x - Math.round(pawnWidth / 2), y - Math.round(pawnHeight / 2), pawnWidth, pawnHeight);
            if (typeof onDraw === 'function') onDraw();
        };

        if (image.complete) {
            drawAndCallback();
        } else {
            image.onload = drawAndCallback;
        }

        return touchableArea;
    };

    const handleCanvasClick = event => {
        const canvas = canvasRef.current;
        const ctx = canvas.getContext('2d');
        const rect = canvas.getBoundingClientRect(),
            cursorX = event.clientX - rect.left,
            cursorY = event.clientY - rect.top;
        for (const pawn of pawns) {
            if (pawn.touchableArea && ctx.isPointInPath(pawn.touchableArea, cursorX, cursorY)) {
                if (canPawnMove(pawn, rolledNumber)) socket.emit('game:move', pawn._id);
            }
        }
        setHintPawn(null);
    };

    const handleMouseMove = event => {
        if (!nowMoving || !rolledNumber) return;
        const canvas = canvasRef.current;
        const ctx = canvas.getContext('2d');
        const rect = canvas.getBoundingClientRect(),
            x = event.clientX - rect.left,
            y = event.clientY - rect.top;
        canvas.style.cursor = 'default';
        for (const pawn of pawns) {
            if (
                pawn.touchableArea &&
                ctx.isPointInPath(pawn.touchableArea, x, y) &&
                player.color === pawn.color &&
                canPawnMove(pawn, rolledNumber)
            ) {
                const pawnPosition = getPositionAfterMove(pawn, rolledNumber);
                if (pawnPosition) {
                    canvas.style.cursor = 'pointer';
                    if (hintPawn && hintPawn.id === pawn._id) return;
                    setHintPawn({ id: pawn._id, position: pawnPosition, color: 'grey' });
                    return;
                }
            }
        }
        setHintPawn(null);
    };

    useEffect(() => {
        const rerenderCanvas = () => {
            const canvas = canvasRef.current;
            const ctx = canvas.getContext('2d');
            const image = new Image();
            image.src = mapImage;
            image.onload = function () {
                ctx.drawImage(image, 0, 0);
                // draw pawns grouped by position with 2-row layout
                const drawn = new Set();
                pawns.forEach((pawn, index) => {
                    if (drawn.has(pawn._id)) return;
                    const group = pawnsAt(pawns, pawn.position);
                    const total = group.length;
                    const center = positionMapCoords[pawn.position];
                    if (!center) return;

                    const slotOffsetX = 14; // horizontal spacing
                    const slotOffsetY = 2; // minimal vertical spacing between rows

                    // helper to draw a single representative pawn for a color group
                    // and show a small badge with the count when there are multiple pawns
                    const drawColorGroup = (pawnGroup, x, y, baseWidth) => {
                        if (!pawnGroup || pawnGroup.length === 0) return null;
                        const rep = pawnGroup[0];
                        // draw pawn and then badge after image renders so badge is on top
                        const touch = paintPawn(ctx, rep, x, y, baseWidth, () => {
                                if (pawnGroup.length > 1) {
                                    const badgeRadius = 8; // smaller badge
                                    const badgeX = x + Math.round(baseWidth / 2) - 4; // slightly closer to pawn edge
                                    const badgeY = y - Math.round(baseWidth / 2) + 4;
                                    ctx.beginPath();
                                    ctx.fillStyle = 'rgba(0,0,0,0.85)';
                                    ctx.arc(badgeX, badgeY, badgeRadius, 0, Math.PI * 2);
                                    ctx.fill();
                                    ctx.fillStyle = 'white';
                                    ctx.font = '10px Arial'; // smaller text
                                    ctx.textAlign = 'center';
                                    ctx.textBaseline = 'middle';
                                    ctx.fillText(String(pawnGroup.length), badgeX, badgeY);
                                }
                        });
                        const foundIndex = pawns.findIndex(pp => pp._id === rep._id);
                        if (foundIndex !== -1) pawns[foundIndex].touchableArea = touch;
                        return touch;
                    };

                    // group pawns by color so same-color pawns stack vertically (tight)
                    const colorGroups = {};
                    group.forEach(g => {
                        if (!g) return;
                        if (!colorGroups[g.color]) colorGroups[g.color] = [];
                        colorGroups[g.color].push(g);
                    });
                    const colors = Object.keys(colorGroups);
                    const nColors = colors.length;
                    const colorSpacing = slotOffsetX; // horizontal spacing between different colors

                    colors.forEach((color, ci) => {
                        const pawnsOfColor = colorGroups[color];
                        const x = center.x + (ci - (nColors - 1) / 2) * colorSpacing;
                        const baseWidth = pawnsOfColor.length > 1 ? 20 : total === 1 ? 28 : 24;
                        drawColorGroup(pawnsOfColor, x, center.y, baseWidth);
                        pawnsOfColor.forEach(p => drawn.add(p._id));
                    });

                    // badge for >6 pawns
                    if (total > 6) {
                        const badgeX = center.x + slotOffsetX + 12;
                        const badgeY = center.y - slotOffsetY - 12;
                        ctx.beginPath();
                        ctx.fillStyle = 'rgba(0,0,0,0.75)';
                        ctx.arc(badgeX, badgeY, 12, 0, Math.PI * 2);
                        ctx.fill();
                        ctx.fillStyle = 'white';
                        ctx.font = '11px Arial';
                        ctx.textAlign = 'center';
                        ctx.textBaseline = 'middle';
                        ctx.fillText(String(total), badgeX, badgeY);
                    }
                });
                if (hintPawn) {
                    // draw hint as a grey circle at target position
                    const pos = positionMapCoords[hintPawn.position];
                    if (pos) {
                        ctx.beginPath();
                        ctx.fillStyle = 'rgba(128,128,128,0.6)';
                        ctx.arc(pos.x, pos.y, 14, 0, Math.PI * 2);
                        ctx.fill();
                    }
                }
            };
        };
        rerenderCanvas();
    }, [hintPawn, pawns]);

    return (
        <canvas
            className='canvas-container'
            width={460}
            height={460}
            ref={canvasRef}
            onClick={handleCanvasClick}
            onMouseMove={handleMouseMove}
        />
    );
};
export default Map;
