/**
 * DragDropHandler.js - Handles drag-and-drop and click-to-move interactions
 * Provides both desktop and mobile-friendly move input
 */

export class DragDropHandler {
    constructor(game, renderer) {
        this.game = game;
        this.renderer = renderer;
        this.enabled = true;
        this.draggedPiece = null;
        this.selectedPiece = null;
    }

    /**
     * Setup all event listeners
     */
    setupEventListeners() {
        const board = this.renderer.boardElement;

        // Drag and drop events
        board.addEventListener('dragstart', (e) => this.onDragStart(e));
        board.addEventListener('dragover', (e) => this.onDragOver(e));
        board.addEventListener('drop', (e) => this.onDrop(e));
        board.addEventListener('dragend', (e) => this.onDragEnd(e));

        // Click events (for click-to-move and mobile)
        board.addEventListener('click', (e) => this.onClick(e));

        // Touch events for mobile
        board.addEventListener('touchstart', (e) => this.onTouchStart(e), { passive: false });
        board.addEventListener('touchmove', (e) => this.onTouchMove(e), { passive: false });
        board.addEventListener('touchend', (e) => this.onTouchEnd(e));
    }

    /**
     * Handle drag start
     * @param {DragEvent} e - Drag event
     */
    onDragStart(e) {
        if (!this.enabled) return;

        const pieceEl = e.target;
        if (!pieceEl.classList.contains('piece')) return;

        const square = pieceEl.parentElement;
        const row = parseInt(square.dataset.row);
        const col = parseInt(square.dataset.col);

        const piece = this.game.board.getPiece(row, col);

        // Only allow dragging pieces of current turn
        if (!piece || piece.color !== this.game.currentTurn) {
            e.preventDefault();
            return;
        }

        e.dataTransfer.setData('text/plain', JSON.stringify({ row, col }));
        e.dataTransfer.effectAllowed = 'move';

        this.draggedPiece = { piece, row, col };

        // Highlight legal moves
        const legalMoves = this.game.getLegalMoves(piece);
        this.renderer.highlightMoves(legalMoves);

        // Add dragging class
        pieceEl.classList.add('dragging');
    }

    /**
     * Handle drag over
     * @param {DragEvent} e - Drag event
     */
    onDragOver(e) {
        if (!this.enabled) return;

        e.preventDefault();
        e.dataTransfer.dropEffect = 'move';

        // Highlight drop target
        const square = e.target.closest('.square');
        if (square) {
            this.renderer.boardElement.querySelectorAll('.drop-target').forEach(s => {
                s.classList.remove('drop-target');
            });
            square.classList.add('drop-target');
        }
    }

    /**
     * Handle drop
     * @param {DragEvent} e - Drag event
     */
    onDrop(e) {
        if (!this.enabled) return;

        e.preventDefault();

        const square = e.target.closest('.square');
        if (!square) return;

        const toRow = parseInt(square.dataset.row);
        const toCol = parseInt(square.dataset.col);

        let from;
        try {
            from = JSON.parse(e.dataTransfer.getData('text/plain'));
        } catch (err) {
            return;
        }

        // Attempt move
        const result = this.game.makeMove(from.row, from.col, toRow, toCol);

        if (result.success) {
            // Re-render board
            this.renderer.renderBoard(this.game.board, this.game.gameState);

            // Show check indicator if in check
            if (result.gameStatus === 'check') {
                this.renderer.showCheckIndicator(this.game.currentTurn, this.game.board);
            }
        } else {
            // Show error feedback
            this.showError(result.error);
        }
    }

    /**
     * Handle drag end
     * @param {DragEvent} e - Drag event
     */
    onDragEnd(e) {
        if (!this.enabled) return;

        // Clean up
        const pieceEl = e.target;
        pieceEl.classList.remove('dragging');

        this.renderer.clearHighlights();
        this.renderer.boardElement.querySelectorAll('.drop-target').forEach(s => {
            s.classList.remove('drop-target');
        });

        this.draggedPiece = null;
    }

    /**
     * Handle click (for click-to-move)
     * @param {MouseEvent} e - Click event
     */
    onClick(e) {
        if (!this.enabled) return;

        const square = e.target.closest('.square');
        if (!square) return;

        const row = parseInt(square.dataset.row);
        const col = parseInt(square.dataset.col);

        if (!this.selectedPiece) {
            // First click - select piece
            const piece = this.game.board.getPiece(row, col);

            if (piece && piece.color === this.game.currentTurn) {
                this.selectedPiece = { piece, row, col };
                this.renderer.selectSquare(row, col);

                // Show legal moves
                const legalMoves = this.game.getLegalMoves(piece);
                this.renderer.highlightMoves(legalMoves);
            }
        } else {
            // Second click - attempt move
            const result = this.game.makeMove(
                this.selectedPiece.row,
                this.selectedPiece.col,
                row,
                col
            );

            if (result.success) {
                // Re-render board
                this.renderer.renderBoard(this.game.board, this.game.gameState);

                // Show check indicator if in check
                if (result.gameStatus === 'check') {
                    this.renderer.showCheckIndicator(this.game.currentTurn, this.game.board);
                }
            } else {
                // Check if clicking another piece of same color
                const newPiece = this.game.board.getPiece(row, col);
                if (newPiece && newPiece.color === this.game.currentTurn) {
                    // Select new piece
                    this.selectedPiece = { piece: newPiece, row, col };
                    this.renderer.deselectSquare();
                    this.renderer.selectSquare(row, col);

                    const legalMoves = this.game.getLegalMoves(newPiece);
                    this.renderer.highlightMoves(legalMoves);
                    return;
                }

                this.showError(result.error);
            }

            // Clear selection
            this.selectedPiece = null;
            this.renderer.deselectSquare();
            this.renderer.clearHighlights();
        }
    }

    /**
     * Handle touch start (mobile)
     * @param {TouchEvent} e - Touch event
     */
    onTouchStart(e) {
        if (!this.enabled) return;

        const touch = e.touches[0];
        const element = document.elementFromPoint(touch.clientX, touch.clientY);
        const square = element?.closest('.square');

        if (!square) return;

        e.preventDefault();

        const row = parseInt(square.dataset.row);
        const col = parseInt(square.dataset.col);
        const piece = this.game.board.getPiece(row, col);

        if (piece && piece.color === this.game.currentTurn) {
            this.selectedPiece = { piece, row, col };
            this.renderer.selectSquare(row, col);

            const legalMoves = this.game.getLegalMoves(piece);
            this.renderer.highlightMoves(legalMoves);
        }
    }

    /**
     * Handle touch move (mobile)
     * @param {TouchEvent} e - Touch event
     */
    onTouchMove(e) {
        if (!this.enabled || !this.selectedPiece) return;

        e.preventDefault();

        const touch = e.touches[0];
        const element = document.elementFromPoint(touch.clientX, touch.clientY);
        const square = element?.closest('.square');

        // Highlight potential drop target
        this.renderer.boardElement.querySelectorAll('.drop-target').forEach(s => {
            s.classList.remove('drop-target');
        });

        if (square) {
            square.classList.add('drop-target');
        }
    }

    /**
     * Handle touch end (mobile)
     * @param {TouchEvent} e - Touch event
     */
    onTouchEnd(e) {
        if (!this.enabled || !this.selectedPiece) return;

        e.preventDefault();

        const touch = e.changedTouches[0];
        const element = document.elementFromPoint(touch.clientX, touch.clientY);
        const square = element?.closest('.square');

        if (square) {
            const toRow = parseInt(square.dataset.row);
            const toCol = parseInt(square.dataset.col);

            const result = this.game.makeMove(
                this.selectedPiece.row,
                this.selectedPiece.col,
                toRow,
                toCol
            );

            if (result.success) {
                this.renderer.renderBoard(this.game.board, this.game.gameState);

                if (result.gameStatus === 'check') {
                    this.renderer.showCheckIndicator(this.game.currentTurn, this.game.board);
                }
            } else {
                this.showError(result.error);
            }
        }

        // Clear selection
        this.selectedPiece = null;
        this.renderer.deselectSquare();
        this.renderer.clearHighlights();
        this.renderer.boardElement.querySelectorAll('.drop-target').forEach(s => {
            s.classList.remove('drop-target');
        });
    }

    /**
     * Enable drag and drop
     */
    enable() {
        this.enabled = true;
    }

    /**
     * Disable drag and drop
     */
    disable() {
        this.enabled = false;
        this.selectedPiece = null;
        this.draggedPiece = null;
        this.renderer.clearAllHighlights();
    }

    /**
     * Show error message to user
     * @param {string} message - Error message
     */
    showError(message) {
        // This could be enhanced with a proper UI notification system
        console.warn('Move error:', message);

        // Flash the board briefly
        this.renderer.boardElement.classList.add('error-shake');
        setTimeout(() => {
            this.renderer.boardElement.classList.remove('error-shake');
        }, 500);
    }
}
