import $ from 'jquery';
import axios from 'axios';

const CELL_SIZE = 80;
const CELL_GAP = 16;
const GRID_UNIT = CELL_SIZE + CELL_GAP;
const MIN_ZOOM = 0.05;
const MAX_ZOOM = 3;
const ZOOM_FACTOR = 0.1;
const SCROLL_SENSITIVITY = 0.6;

function parseData(elementId, fallback) {
    const el = document.getElementById(elementId);
    if (!el) {
        return fallback;
    }

    try {
        return JSON.parse(el.textContent ?? 'null') ?? fallback;
    } catch (error) {
        console.error(`Failed to parse payload for ${elementId}`, error);
        return fallback;
    }
}

function computeContentDimensions(rows) {
    const maxX = Math.max(0, ...rows.map((row) => row.location.x));
    const maxY = Math.max(0, ...rows.map((row) => row.location.y));

    const width = Math.max(1, maxX + 1) * (CELL_SIZE + CELL_GAP);
    const height = Math.max(1, maxY + 1) * (CELL_SIZE + CELL_GAP);

    return { width, height };
}

function applyStatusClass(element, status) {
    const targetStatus = status ?? 'unknown';
    element.classList.forEach((name) => {
        if (name.startsWith('status-')) {
            element.classList.remove(name);
        }
    });
    element.classList.add(`status-${targetStatus}`);
}

function createCell(row) {
    const cell = document.createElement('div');
    cell.classList.add('map-cell');
    cell.dataset.rowId = String(row.id);
    cell.style.left = `${row.location.x * (CELL_SIZE + CELL_GAP)}px`;
    cell.style.top = `${row.location.y * (CELL_SIZE + CELL_GAP)}px`;
    cell.style.width = `${CELL_SIZE}px`;
    cell.style.height = `${CELL_SIZE}px`;

    applyStatusClass(cell, row.status);

    const countBadge = document.createElement('div');
    countBadge.classList.add('map-cell-count');
    countBadge.dataset.role = 'vine-count';
    countBadge.textContent = String(row.vine_count ?? 0);

    const varietyLabel = document.createElement('div');
    varietyLabel.classList.add('map-cell-variety');
    varietyLabel.dataset.role = 'variety-label';
    varietyLabel.textContent = row.variety?.label ?? 'Unassigned';

    cell.appendChild(countBadge);
    cell.appendChild(varietyLabel);

    return cell;
}

export default function initMapEdit() {
    const $root = $('[data-page="vineyard-map-edit"]');
    if (!$root.length) {
        return;
    }

    const rows = parseData('vineyard-edit-rows', []);
    const routes = parseData('vineyard-edit-routes', {});

    const mapViewport = $root.find('[data-role="map-container"]')[0];
    if (!mapViewport) {
        return;
    }

    let currentRows = [...rows];
    const rowElements = new Map();
    const locationIndex = new Map();
    const coordinateKey = (x, y) => `${x}:${y}`;
    const parseCoordinateKey = (key) => {
        const [x, y] = key.split(':').map((value) => parseInt(value, 10));
        return { x, y };
    };

    let selectedRow = null;
    let relocationTarget = null;
    let currentMode = 'edit';
    const removeSelection = new Set();
    const addSelection = new Set();
    const addMarkers = new Map();

    let isSelectingArea = false;
    let selectionBox = null;
    let selectionStartPoint = null;
    let selectionMerge = false;
    let selectionMode = null;
    let selectionMoved = false;
    let suppressNextClick = false;

    mapViewport.innerHTML = '';
    const mapContent = document.createElement('div');
    mapContent.classList.add('vineyard-map-grid');
    mapViewport.appendChild(mapContent);

    const selectionLayer = document.createElement('div');
    selectionLayer.classList.add('map-selection-layer');
    mapViewport.appendChild(selectionLayer);

    const pendingMarker = document.createElement('div');
    pendingMarker.classList.add('pending-cell');
    pendingMarker.style.width = `${CELL_SIZE}px`;
    pendingMarker.style.height = `${CELL_SIZE}px`;
    mapContent.appendChild(pendingMarker);

    let contentDimensions = computeContentDimensions(currentRows);

    const viewportState = {
        scale: 1,
        translateX: 0,
        translateY: 0,
    };

    let viewportAdjusted = false;

    const markViewportAdjusted = () => {
        viewportAdjusted = true;
    };

    const clampTransform = () => {
        const viewportWidth = mapViewport.clientWidth;
        const viewportHeight = mapViewport.clientHeight;
        const scaledWidth = contentDimensions.width * viewportState.scale;
        const scaledHeight = contentDimensions.height * viewportState.scale;

        if (scaledWidth <= viewportWidth) {
            viewportState.translateX = (viewportWidth - scaledWidth) / 2;
        } else {
            const minX = viewportWidth - scaledWidth;
            viewportState.translateX = Math.min(0, Math.max(minX, viewportState.translateX));
        }

        if (scaledHeight <= viewportHeight) {
            viewportState.translateY = (viewportHeight - scaledHeight) / 2;
        } else {
            const minY = viewportHeight - scaledHeight;
            viewportState.translateY = Math.min(0, Math.max(minY, viewportState.translateY));
        }
    };

    const applyTransform = () => {
        clampTransform();
        mapContent.style.transform = `translate(${viewportState.translateX}px, ${viewportState.translateY}px) scale(${viewportState.scale})`;
    };

    const fitContentToViewport = ({ force = false } = {}) => {
        if (viewportAdjusted && !force) {
            applyTransform();
            return;
        }

        if (!contentDimensions.width || !contentDimensions.height) {
            viewportState.scale = 1;
            viewportState.translateX = 0;
            viewportState.translateY = 0;
            applyTransform();
            return;
        }

        const viewportWidth = mapViewport.clientWidth || 1;
        const viewportHeight = mapViewport.clientHeight || 1;
        const scaleX = viewportWidth / contentDimensions.width;
        const scaleY = viewportHeight / contentDimensions.height;
        const fittedScale = Math.min(1, Math.min(scaleX, scaleY));

        const scale = Math.min(MAX_ZOOM, Math.max(fittedScale, Math.min(MIN_ZOOM, fittedScale)));
        viewportState.scale = scale;
        viewportState.translateX = (viewportWidth - contentDimensions.width * viewportState.scale) / 2;
        viewportState.translateY = (viewportHeight - contentDimensions.height * viewportState.scale) / 2;

        applyTransform();
    };

    const mapPointFromViewport = (x, y) => ({
        x: (x - viewportState.translateX) / viewportState.scale,
        y: (y - viewportState.translateY) / viewportState.scale,
    });

    const mapPointFromEvent = (event) => {
        const rect = mapViewport.getBoundingClientRect();
        const viewportX = event.clientX - rect.left;
        const viewportY = event.clientY - rect.top;
        return {
            viewport: { x: viewportX, y: viewportY, width: rect.width, height: rect.height },
            map: mapPointFromViewport(viewportX, viewportY),
        };
    };

    const mapRectFromClientRect = (rect) => {
        const viewportRect = mapViewport.getBoundingClientRect();
        const left = rect.left - viewportRect.left;
        const top = rect.top - viewportRect.top;
        const right = rect.right - viewportRect.left;
        const bottom = rect.bottom - viewportRect.top;

        const topLeft = mapPointFromViewport(left, top);
        const bottomRight = mapPointFromViewport(right, bottom);

        return {
            left: Math.min(topLeft.x, bottomRight.x),
            top: Math.min(topLeft.y, bottomRight.y),
            right: Math.max(topLeft.x, bottomRight.x),
            bottom: Math.max(topLeft.y, bottomRight.y),
        };
    };

    const updateContentSize = ({ preferFit = false } = {}) => {
        contentDimensions = computeContentDimensions(currentRows);
        mapContent.style.width = `${contentDimensions.width}px`;
        mapContent.style.height = `${contentDimensions.height}px`;

        if (!viewportAdjusted || preferFit) {
            fitContentToViewport({ force: preferFit });
        } else {
            applyTransform();
        }
    };

    const mountRow = (row) => {
        const cell = createCell(row);
        mapContent.appendChild(cell);
        rowElements.set(Number(row.id), cell);
        locationIndex.set(coordinateKey(row.location.x, row.location.y), Number(row.id));
    };

    currentRows.forEach(mountRow);
    updateContentSize({ preferFit: true });

    const refreshCellStates = () => {
        rowElements.forEach((element, rowId) => {
            const isSelected = currentMode === 'edit' && selectedRow && Number(selectedRow.id) === rowId;
            const isMarkedForRemoval = removeSelection.has(rowId) && currentMode === 'remove';
            element.classList.toggle('selected', Boolean(isSelected));
            element.classList.toggle('remove-selected', Boolean(isMarkedForRemoval));
        });
    };

    const $rowForm = $root.find('[data-role="row-form"]');
    const $deleteButton = $rowForm.find('[data-control="delete-row"]');
    const $saveRowButton = $rowForm.find('button[type="submit"]');
    const $relocationTarget = $root.find('[data-role="relocation-target"]');
    const $removeCommit = $root.find('[data-control="commit-remove-selection"]');
    const $removeCount = $root.find('[data-role="remove-selection-count"]');
    const $removeClear = $root.find('[data-control="clear-remove-selection"]');
    const $addCommit = $root.find('[data-control="commit-add-selection"]');
    const $addClear = $root.find('[data-control="clear-add-selection"]');
    const $addCount = $root.find('[data-role="add-selection-count"]');
    const $addVineCount = $root.find('[name="add_vine_count"]');
    const $clearRelocation = $root.find('[data-control="clear-relocation"]');
    const $modeSwitch = $root.find('[data-role="mode-switch"]');
    const $modeButtons = $modeSwitch.find('[data-mode]');
    const $modePanels = $root.find('[data-mode-panel]');
    const $feedback = $root.find('[data-role="map-feedback"]');

    const setFeedback = (message, tone = 'info') => {
        if (!$feedback.length) {
            return;
        }

        $feedback.removeClass('feedback-info feedback-success feedback-error');

        if (!message) {
            $feedback.text('');
            return;
        }

        $feedback.addClass(`feedback-${tone}`);
        $feedback.text(message);
    };

    const updateActionAvailability = () => {
        const removeActive = currentMode === 'remove';
        const addActive = currentMode === 'add';

        $clearRelocation.prop('disabled', !relocationTarget);
        $removeCommit.prop('disabled', !(removeActive && removeSelection.size > 0));
        $removeClear.prop('disabled', removeSelection.size === 0);
        $addCommit.prop('disabled', !(addActive && addSelection.size > 0));
        $addClear.prop('disabled', addSelection.size === 0);

        if (currentMode !== 'edit') {
            $saveRowButton.prop('disabled', true);
            $deleteButton.prop('disabled', true);
        }
    };

    const updatePendingMarker = () => {
        const target = currentMode === 'edit' ? relocationTarget : null;
        if (target) {
            pendingMarker.style.left = `${target.x * GRID_UNIT}px`;
            pendingMarker.style.top = `${target.y * GRID_UNIT}px`;
            pendingMarker.style.display = 'block';
        } else {
            pendingMarker.style.display = 'none';
        }
    };

    const populateRowForm = (row) => {
        $rowForm.find('[name="row_id"]').val(row?.id ?? '');
        $rowForm.find('[name="location"]').val(row ? `${row.location.x},${row.location.y}` : '');
        $rowForm.find('[name="vine_count"]').val(row?.vine_count ?? '');
        $deleteButton.prop('disabled', !row);
        $saveRowButton.prop('disabled', !row);
        updateActionAvailability();
    };

    const stageRelocation = (coords) => {
        relocationTarget = coords;
        if (coords) {
            $relocationTarget.text(`${coords.x},${coords.y}`);
        } else {
            $relocationTarget.text('None');
        }
        updatePendingMarker();
        updateActionAvailability();
    };

    const updateAddUi = () => {
        $addCount.text(String(addSelection.size));
        updateActionAvailability();
    };

    const ensureAddMarker = (coords) => {
        const key = coordinateKey(coords.x, coords.y);
        if (addMarkers.has(key)) {
            return addMarkers.get(key);
        }

        const marker = document.createElement('div');
        marker.classList.add('add-marker');
        marker.style.left = `${coords.x * GRID_UNIT}px`;
        marker.style.top = `${coords.y * GRID_UNIT}px`;
        marker.style.width = `${CELL_SIZE}px`;
        marker.style.height = `${CELL_SIZE}px`;
        mapContent.appendChild(marker);
        addMarkers.set(key, marker);
        return marker;
    };

    const stageAddTarget = (coords) => {
        const key = coordinateKey(coords.x, coords.y);
        if (addSelection.has(key) || locationIndex.has(key)) {
            return;
        }

        addSelection.add(key);
        ensureAddMarker(coords);
    };

    const removeAddTargetByKey = (key) => {
        if (!addSelection.has(key)) {
            return;
        }

        addSelection.delete(key);
        const marker = addMarkers.get(key);
        if (marker) {
            marker.remove();
            addMarkers.delete(key);
        }
    };

    const clearAddTargets = ({ silent = false } = {}) => {
        if (addSelection.size === 0) {
            if (!silent) {
                updateAddUi();
            }
            return;
        }

        addSelection.forEach((key) => {
            const marker = addMarkers.get(key);
            if (marker) {
                marker.remove();
            }
        });

        addSelection.clear();
        addMarkers.clear();

        if (!silent) {
            updateAddUi();
        }
    };

    const cancelAreaSelection = () => {
        if (selectionBox) {
            selectionBox.remove();
        }
        selectionBox = null;
        selectionStartPoint = null;
        isSelectingArea = false;
        selectionMerge = false;
        selectionMode = null;
        selectionMoved = false;
    };

    const beginAreaSelection = (event) => {
        if (event.button !== 0) {
            return;
        }

        if (!(currentMode === 'remove' || currentMode === 'add')) {
            return;
        }

        if (event.target.closest('[data-row-id]')) {
            return;
        }

        cancelAreaSelection();

        isSelectingArea = true;
        selectionMode = currentMode;
        selectionMerge = event.shiftKey;
        selectionMoved = false;

        selectionBox = document.createElement('div');
        selectionBox.classList.add('selection-box');
        selectionLayer.appendChild(selectionBox);

        const rect = mapViewport.getBoundingClientRect();
        const startX = event.clientX - rect.left;
        const startY = event.clientY - rect.top;
        selectionStartPoint = { x: startX, y: startY };

        Object.assign(selectionBox.style, {
            left: `${startX}px`,
            top: `${startY}px`,
            width: '0px',
            height: '0px',
        });

        event.preventDefault();
    };

    const updateAreaSelection = (event) => {
        if (!isSelectingArea || !selectionBox || !selectionStartPoint) {
            return;
        }

        const rect = mapViewport.getBoundingClientRect();
        const currentX = event.clientX - rect.left;
        const currentY = event.clientY - rect.top;

        const left = Math.min(selectionStartPoint.x, currentX);
        const top = Math.min(selectionStartPoint.y, currentY);
        const width = Math.abs(currentX - selectionStartPoint.x);
        const height = Math.abs(currentY - selectionStartPoint.y);

        if (!selectionMoved && (width > 3 || height > 3)) {
            selectionMoved = true;
        }

        Object.assign(selectionBox.style, {
            left: `${left}px`,
            top: `${top}px`,
            width: `${width}px`,
            height: `${height}px`,
        });
    };

    const finalizeAreaSelection = () => {
        if (!isSelectingArea) {
            return;
        }

        const boxRect = selectionBox?.getBoundingClientRect() ?? null;

        if (selectionBox) {
            selectionBox.remove();
        }

        const mode = selectionMode;
        const merge = selectionMerge;
        const moved = selectionMoved;

        selectionBox = null;
        selectionStartPoint = null;
        isSelectingArea = false;
        selectionMode = null;
        selectionMerge = false;
        selectionMoved = false;

        suppressNextClick = moved;

        if (!moved || !boxRect || !mode) {
            return;
        }

        suppressNextClick = true;

        if (mode === 'remove') {
            const intersectingRows = [];
            rowElements.forEach((element, rowId) => {
                const cellRect = element.getBoundingClientRect();
                const fullyContained =
                    cellRect.left >= boxRect.left &&
                    cellRect.right <= boxRect.right &&
                    cellRect.top >= boxRect.top &&
                    cellRect.bottom <= boxRect.bottom;

                if (fullyContained) {
                    intersectingRows.push(rowId);
                }
            });

            if (!merge) {
                removeSelection.clear();
            }

            intersectingRows.forEach((rowId) => removeSelection.add(rowId));
            updateRemoveUi();
            const size = removeSelection.size;
            setFeedback(
                size
                    ? `Marked ${size} row${size === 1 ? '' : 's'} for deletion.`
                    : 'No rows selected yet. Click rows to mark them for deletion.',
                'info'
            );
            return;
        }

        if (mode === 'add') {
            const bounds = mapRectFromClientRect(boxRect);
            const totalColumns = Math.max(1, Math.ceil(contentDimensions.width / GRID_UNIT));
            const totalRows = Math.max(1, Math.ceil(contentDimensions.height / GRID_UNIT));

            const startX = Math.max(0, Math.min(Math.floor(bounds.left / GRID_UNIT), totalColumns - 1));
            const endX = Math.max(startX, Math.min(Math.ceil(bounds.right / GRID_UNIT), totalColumns));
            const startY = Math.max(0, Math.min(Math.floor(bounds.top / GRID_UNIT), totalRows - 1));
            const endY = Math.max(startY, Math.min(Math.ceil(bounds.bottom / GRID_UNIT), totalRows));

            const coords = [];

            for (let x = startX; x < endX; x += 1) {
                for (let y = startY; y < endY; y += 1) {
                    const key = coordinateKey(x, y);
                    if (locationIndex.has(key)) {
                        continue;
                    }

                    const cellLeft = x * GRID_UNIT;
                    const cellTop = y * GRID_UNIT;
                    const cellRight = cellLeft + CELL_SIZE;
                    const cellBottom = cellTop + CELL_SIZE;

                    const fullyContained =
                        cellLeft >= bounds.left &&
                        cellRight <= bounds.right &&
                        cellTop >= bounds.top &&
                        cellBottom <= bounds.bottom;

                    if (fullyContained) {
                        coords.push({ x, y });
                    }
                }
            }

            if (!merge) {
                clearAddTargets({ silent: true });
            }

            coords.forEach((coord) => stageAddTarget(coord));
            updateAddUi();
            const size = addSelection.size;
            setFeedback(
                size
                    ? `Staged ${size} new row${size === 1 ? '' : 's'} for creation.`
                    : 'No empty squares selected yet.',
                'info'
            );
        }
    };

    const handleWheel = (event) => {
        if (event.ctrlKey) {
            event.preventDefault();

            const previousScale = viewportState.scale;
            const direction = -event.deltaY;
            const scaleDelta = direction > 0 ? 1 + ZOOM_FACTOR : 1 - ZOOM_FACTOR;
            const nextScale = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, viewportState.scale * scaleDelta));

            if (nextScale === previousScale) {
                return;
            }

            const rect = mapViewport.getBoundingClientRect();
            const offsetX = event.clientX - rect.left;
            const offsetY = event.clientY - rect.top;
            const zoomRatio = nextScale / previousScale;

            viewportState.translateX = offsetX - (offsetX - viewportState.translateX) * zoomRatio;
            viewportState.translateY = offsetY - (offsetY - viewportState.translateY) * zoomRatio;
            viewportState.scale = nextScale;

            markViewportAdjusted();
            applyTransform();
            return;
        }

        event.preventDefault();

        if (event.shiftKey) {
            viewportState.translateX -= event.deltaY * SCROLL_SENSITIVITY;
            viewportState.translateX -= event.deltaX * SCROLL_SENSITIVITY;
        } else {
            viewportState.translateY -= event.deltaY * SCROLL_SENSITIVITY;
            viewportState.translateX -= event.deltaX * SCROLL_SENSITIVITY;
        }

        markViewportAdjusted();
        applyTransform();
    };

    const updateRemoveUi = () => {
        $removeCount.text(String(removeSelection.size));
        refreshCellStates();
        updateActionAvailability();
    };

    $clearRelocation.on('click', () => {
        if (!relocationTarget) {
            return;
        }

        stageRelocation(null);
        setFeedback('Staged move cleared.', 'info');
    });

    $addClear.on('click', () => {
        if (addSelection.size === 0) {
            return;
        }

        clearAddTargets();
        setFeedback('Selection cleared.', 'info');
    });

    $addCommit.on('click', async () => {
        if (addSelection.size === 0) {
            return;
        }

        if (!routes.add) {
            console.error('Add route not configured');
            setFeedback('Create route is not configured.', 'error');
            return;
        }

        const vineInput = parseInt($addVineCount.val(), 10);
        const vineCount = Number.isFinite(vineInput) ? Math.max(0, vineInput) : 0;

        const selectionKeys = Array.from(addSelection.values());
        const entries = selectionKeys.map((key) => {
            const coords = parseCoordinateKey(key);
            return {
                key,
                x: coords.x,
                y: coords.y,
                payload: {
                    location: `${coords.x},${coords.y}`,
                    vine_count: vineCount,
                },
            };
        });

        const rowsPayload = entries.map((entry) => entry.payload);

        if (rowsPayload.length === 0) {
            setFeedback('No empty squares selected yet.', 'info');
            return;
        }

        try {
            const response = await axios.post(routes.add, { rows: rowsPayload });
            const createdIds = Array.isArray(response.data?.created) ? response.data.created : [];
            if (!createdIds.length) {
                setFeedback('Rows were created but the response did not return their identifiers.', 'error');
                return;
            }

            clearAddTargets({ silent: true });

            const processed = Math.min(createdIds.length, entries.length);
            for (let index = 0; index < processed; index += 1) {
                const rawId = createdIds[index];
                const numericId = Number(rawId);
                if (!Number.isFinite(numericId) || numericId <= 0) {
                    continue;
                }

                const entry = entries[index];
                const newRow = {
                    id: numericId,
                    location: { x: entry.x, y: entry.y },
                    vine_count: entry.payload.vine_count,
                    status: 'inactive',
                    variety: null,
                };

                upsertRow(newRow);
                locationIndex.set(entry.key, numericId);

                const element = createCell(newRow);
                mapContent.appendChild(element);
                rowElements.set(numericId, element);
            }

            selectedRow = null;
            updateAddUi();
            updateContentSize();
            refreshCellStates();

            const requestedCount = entries.length;
            const createdCount = Math.min(createdIds.length, requestedCount);
            if (createdCount === requestedCount) {
                setFeedback(`Added ${createdCount} new row${createdCount === 1 ? '' : 's'}.`, 'success');
            } else {
                setFeedback(
                    `Added ${createdCount} new row${createdCount === 1 ? '' : 's'}. Some selections may require a refresh to appear.`,
                    'info'
                );
            }
        } catch (error) {
            console.error('Failed to add rows', error);
            setFeedback('Unable to add the selected rows. Please try again.', 'error');
        }
    });

    const setMode = (mode) => {
        if (currentMode === mode) {
            return;
        }

        currentMode = mode;

        cancelAreaSelection();

        $modeButtons.removeClass('active');
        $modeButtons.filter(`[data-mode="${mode}"]`).addClass('active');

        $modePanels.removeClass('active');
        $modePanels.filter(`[data-mode-panel="${mode}"]`).addClass('active');

        if (mode !== 'edit') {
            selectedRow = null;
            populateRowForm(null);
            stageRelocation(null);
        }

        if (mode !== 'remove') {
            removeSelection.clear();
        }

        if (mode !== 'add') {
            clearAddTargets({ silent: true });
        }

        updateRemoveUi();
        updateAddUi();
        updatePendingMarker();

        switch (mode) {
            case 'edit':
                setFeedback('Edit mode active. Select a row to adjust head count or click an empty cell to stage a move.', 'info');
                break;
            case 'add':
                setFeedback('Add mode active. Select empty squares to stage new rows, then create them.', 'info');
                break;
            case 'remove':
                setFeedback('Remove mode active. Select rows to delete, then confirm the removal.', 'info');
                break;
        }
    };

    const handleModeClick = (event) => {
        const mode = $(event.currentTarget).data('mode');
        if (typeof mode === 'string') {
            setMode(mode);
        }
    };

    $modeButtons.on('click', handleModeClick);

    populateRowForm(null);
    stageRelocation(null);
    updateRemoveUi();
    updateAddUi();
    currentMode = null;
    setMode('edit');

    const computeCoordinatesFromEvent = (event) => {
        const { viewport, map } = mapPointFromEvent(event);

        if (viewport.x < 0 || viewport.y < 0 || viewport.x > viewport.width || viewport.y > viewport.height) {
            return null;
        }

        if (map.x < 0 || map.y < 0) {
            return null;
        }

        const cellX = Math.floor(map.x / GRID_UNIT);
        const cellY = Math.floor(map.y / GRID_UNIT);

        const innerX = map.x - cellX * GRID_UNIT;
        const innerY = map.y - cellY * GRID_UNIT;

        if (innerX > CELL_SIZE || innerY > CELL_SIZE) {
            return null;
        }

        return { x: cellX, y: cellY };
    };

    const findRowById = (rowId) => currentRows.find((row) => Number(row.id) === Number(rowId)) ?? null;

    const upsertRow = (row) => {
        const index = currentRows.findIndex((existing) => Number(existing.id) === Number(row.id));
        if (index >= 0) {
            currentRows[index] = row;
        } else {
            currentRows.push(row);
        }
    };

    const removeRowFromCollections = (rowId) => {
        const numericId = Number(rowId);
        const row = findRowById(numericId);
        currentRows = currentRows.filter((entry) => Number(entry.id) !== numericId);
        if (row) {
            locationIndex.delete(coordinateKey(row.location.x, row.location.y));
        }
        rowElements.get(numericId)?.remove();
        rowElements.delete(numericId);
        removeSelection.delete(numericId);
    };

    mapViewport.addEventListener('click', (event) => {
        if (suppressNextClick) {
            suppressNextClick = false;
            return;
        }

        const cell = event.target.closest('[data-row-id]');
        if (cell) {
            event.stopPropagation();
            const rowId = Number(cell.dataset.rowId);
            if (!Number.isFinite(rowId)) {
                return;
            }

            if (currentMode === 'remove') {
                const multi = event.shiftKey;

                if (multi) {
                    if (removeSelection.has(rowId)) {
                        removeSelection.delete(rowId);
                    } else {
                        removeSelection.add(rowId);
                    }
                } else if (removeSelection.size === 1 && removeSelection.has(rowId)) {
                    removeSelection.clear();
                } else {
                    removeSelection.clear();
                    removeSelection.add(rowId);
                }

                updateRemoveUi();
                const size = removeSelection.size;
                setFeedback(
                    size
                        ? `Marked ${size} row${size === 1 ? '' : 's'} for deletion.`
                        : 'No rows selected yet. Click rows to mark them for deletion.',
                    'info'
                );
                return;
            }

            if (currentMode === 'add') {
                setFeedback('Add mode works with empty squares. Click an open grid space to stage a new row.', 'info');
                return;
            }

            selectedRow = findRowById(rowId);
            populateRowForm(selectedRow);
            stageRelocation(null);
            refreshCellStates();
            if (selectedRow) {
                setFeedback(
                    `Editing row #${selectedRow.id} at ${selectedRow.location.x},${selectedRow.location.y}.`,
                    'info'
                );
            }
            return;
        }

        if (currentMode === 'remove') {
            setFeedback('Remove mode is active. Click existing rows to mark them for removal.', 'info');
            return;
        }

        const coords = computeCoordinatesFromEvent(event);
        if (!coords) {
            setFeedback('Click inside a square on the grid to select a location.', 'info');
            return;
        }

        const locationKey = coordinateKey(coords.x, coords.y);
        const existingRowId = locationIndex.get(locationKey);

        if (currentMode === 'edit') {
            if (existingRowId) {
                selectedRow = findRowById(existingRowId);
                populateRowForm(selectedRow);
                stageRelocation(null);
                refreshCellStates();
                if (selectedRow) {
                    setFeedback(
                        `Editing row #${selectedRow.id} at ${selectedRow.location.x},${selectedRow.location.y}.`,
                        'info'
                    );
                }
                return;
            }

            if (!selectedRow) {
                setFeedback('Select a row first before staging a new location.', 'info');
                stageRelocation(null);
                return;
            }

            stageRelocation(coords);
            setFeedback(`Staged new location ${coords.x},${coords.y}. Save the row to move it.`, 'info');
            return;
        }

        if (currentMode === 'add') {
            if (existingRowId) {
                setFeedback('That square already contains a row. Choose an empty location.', 'error');
                return;
            }

            const key = coordinateKey(coords.x, coords.y);
            const multi = event.shiftKey;

            if (multi) {
                if (addSelection.has(key)) {
                    removeAddTargetByKey(key);
                } else {
                    stageAddTarget(coords);
                }
            } else {
                if (addSelection.size === 1 && addSelection.has(key)) {
                    clearAddTargets();
                    setFeedback('Selection cleared.', 'info');
                    return;
                }

                clearAddTargets({ silent: true });
                stageAddTarget(coords);
            }

            updateAddUi();
            const size = addSelection.size;
            setFeedback(
                size
                    ? `Staged ${size} new row${size === 1 ? '' : 's'} for creation.`
                    : 'No empty squares selected yet.',
                'info'
            );
            return;
        }
    });

    mapViewport.addEventListener('wheel', handleWheel, { passive: false });
    mapViewport.addEventListener('mousedown', beginAreaSelection);
    window.addEventListener('mousemove', updateAreaSelection);
    window.addEventListener('mouseup', finalizeAreaSelection);

    $rowForm.on('submit', async (event) => {
        event.preventDefault();
        if (!selectedRow) {
            setFeedback('Select a row to edit before saving changes.', 'info');
            return;
        }

        if (!routes.update) {
            console.error('Update route not configured');
            setFeedback('Update route is not configured.', 'error');
            return;
        }

        if (relocationTarget) {
            const occupied = locationIndex.get(coordinateKey(relocationTarget.x, relocationTarget.y));
            if (occupied && Number(occupied) !== Number(selectedRow.id)) {
                setFeedback('Another row already occupies the staged location.', 'error');
                return;
            }
        }

        const stagedLocation = relocationTarget
            ? `${relocationTarget.x},${relocationTarget.y}`
            : undefined;

        const payload = {
            rows: [
                {
                    id: selectedRow.id,
                    vine_count: parseInt($rowForm.find('[name="vine_count"]').val(), 10) || 0,
                    location: stagedLocation,
                },
            ],
        };

        try {
            await axios.post(routes.update, payload);

            const previousKey = coordinateKey(selectedRow.location.x, selectedRow.location.y);

            const updatedRow = {
                ...selectedRow,
                vine_count: payload.rows[0].vine_count,
                location: stagedLocation
                    ? { x: relocationTarget.x, y: relocationTarget.y }
                    : selectedRow.location,
            };

            upsertRow(updatedRow);
            selectedRow = updatedRow;

            if (stagedLocation) {
                locationIndex.delete(previousKey);
                locationIndex.set(
                    coordinateKey(updatedRow.location.x, updatedRow.location.y),
                    Number(updatedRow.id)
                );
            }

            const element = rowElements.get(Number(updatedRow.id));
            if (element) {
                const badge = element.querySelector('[data-role="vine-count"]');
                if (badge) {
                    badge.textContent = String(updatedRow.vine_count);
                }
                element.style.left = `${updatedRow.location.x * (CELL_SIZE + CELL_GAP)}px`;
                element.style.top = `${updatedRow.location.y * (CELL_SIZE + CELL_GAP)}px`;
                applyStatusClass(element, updatedRow.status);
            }

            populateRowForm(selectedRow);
            stageRelocation(null);
            refreshCellStates();
            updateContentSize();
            const feedbackMessage = stagedLocation
                ? `Row updated and moved to ${stagedLocation}.`
                : 'Row updated successfully.';
            setFeedback(feedbackMessage, 'success');
        } catch (error) {
            console.error('Failed to update row', error);
            setFeedback('Unable to update the selected row. Please try again.', 'error');
        }
    });

    $deleteButton.on('click', async (event) => {
        event.preventDefault();
        if (!selectedRow) {
            setFeedback('Select a row first before trying to delete it.', 'info');
            return;
        }

        const destroyRoute = routes.destroy?.replace('__ROW__', String(selectedRow.id));
        if (!destroyRoute) {
            console.error('Destroy route not configured');
            setFeedback('Delete route is not configured.', 'error');
            return;
        }

        if (!window.confirm('Remove the selected row from the vineyard map?')) {
            setFeedback('Deletion cancelled.', 'info');
            return;
        }

        try {
            await axios.post(destroyRoute, { _method: 'DELETE' });
            const rowId = selectedRow.id;
            removeRowFromCollections(rowId);
            selectedRow = null;
            populateRowForm(null);
            stageRelocation(null);
            refreshCellStates();
            updateContentSize();
            setFeedback('Row deleted successfully.', 'success');
        } catch (error) {
            console.error('Failed to remove row', error);
            setFeedback('Unable to delete the selected row. Please try again.', 'error');
        }
    });

    $removeCommit.on('click', async () => {
        if (currentMode !== 'remove' || removeSelection.size === 0) {
            return;
        }

        if (!routes.remove) {
            console.error('Remove route not configured');
            setFeedback('Remove route is not configured.', 'error');
            return;
        }

        if (!window.confirm(`Delete ${removeSelection.size} selected row(s)?`)) {
            setFeedback('Deletion cancelled.', 'info');
            return;
        }

        const ids = Array.from(removeSelection);

        try {
            await axios.post(routes.remove, { rows: ids });

            ids.forEach((rowId) => {
                removeRowFromCollections(rowId);
                if (selectedRow && Number(selectedRow.id) === Number(rowId)) {
                    selectedRow = null;
                }
            });

            populateRowForm(selectedRow);
            stageRelocation(null);
            updateContentSize();
            removeSelection.clear();
            updateRemoveUi();
            setFeedback(`Deleted ${ids.length} row${ids.length === 1 ? '' : 's'}.`, 'success');
        } catch (error) {
            console.error('Failed to delete selected rows', error);
            setFeedback('Unable to delete the selected rows. Please try again.', 'error');
        }
    });

    $removeClear.on('click', () => {
        if (removeSelection.size === 0) {
            return;
        }

        removeSelection.clear();
        updateRemoveUi();
        setFeedback('Selection cleared.', 'info');
    });
}
