/**
 * BoardRenderer.js - Chess board visual rendering
 * Renders board and pieces to DOM using CSS Grid
 */

export class BoardRenderer {
    constructor(boardElement, config = {}) {
        this.boardElement = boardElement;
        this.selectedSquare = null;
        this.highlightedMoves = [];

        this.config = {
            showCoordinates: config.showCoordinates !== false,
            pieceStyle: config.pieceStyle || 'symbols',
            highlightLastMove: config.highlightLastMove !== false,
            ...config
        };
    }

    /**
     * Render complete board state
     * @param {Board} board - Game board
     * @param {GameState} gameState - Game state
     */
    renderBoard(board, gameState) {
        this.boardElement.innerHTML = '';

        // Create 64 squares
        for (let row = 0; row < 8; row++) {
            for (let col = 0; col < 8; col++) {
                const square = this.createSquare(row, col);
                const piece = board.getPiece(row, col);

                if (piece) {
                    const pieceElement = this.createPieceElement(piece);
                    square.appendChild(pieceElement);
                }

                this.boardElement.appendChild(square);
            }
        }

        // Add coordinates if enabled
        if (this.config.showCoordinates) {
            this.addCoordinates();
        }

        // Highlight last move if enabled
        if (this.config.highlightLastMove && gameState) {
            const lastMove = gameState.getLastMove();
            if (lastMove) {
                this.highlightLastMove(lastMove);
            }
        }
    }

    /**
     * Create a single square element
     * @param {number} row - Row index
     * @param {number} col - Column index
     * @returns {HTMLElement} Square element
     */
    createSquare(row, col) {
        const square = document.createElement('div');
        square.className = 'square';
        square.classList.add((row + col) % 2 === 0 ? 'light' : 'dark');
        square.dataset.row = row;
        square.dataset.col = col;

        return square;
    }

    /**
     * Create a piece element
     * @param {Piece} piece - Chess piece
     * @returns {HTMLElement} Piece element
     */
    createPieceElement(piece) {
        const pieceEl = document.createElement('div');
        pieceEl.className = `piece ${piece.color} ${piece.type}`;
        pieceEl.draggable = true;

        if (this.config.pieceStyle === 'symbols') {
            // Piece symbols are rendered via CSS ::before pseudo-elements
            // No need to set innerHTML - CSS handles it based on classes
        } else {
            // For image-based pieces
            pieceEl.style.backgroundImage = `url(assets/pieces/${piece.color}-${piece.type}.svg)`;
        }

        return pieceEl;
    }

    /**
     * Highlight legal moves for a piece
     * @param {Position[]} moves - Array of legal positions
     */
    highlightMoves(moves) {
        this.clearHighlights();

        moves.forEach(move => {
            const square = this.getSquare(move.row, move.col);
            if (square) {
                square.classList.add('legal-move');

                // Different highlight for captures
                const piece = this.getPieceElement(square);
                if (piece) {
                    square.classList.add('has-piece');
                }
            }
        });

        this.highlightedMoves = moves;
    }

    /**
     * Clear all move highlights
     */
    clearHighlights() {
        this.highlightedMoves.forEach(move => {
            const square = this.getSquare(move.row, move.col);
            if (square) {
                square.classList.remove('legal-move', 'has-piece');
            }
        });

        this.highlightedMoves = [];
    }

    /**
     * Highlight last move
     * @param {Move} move - Last move
     */
    highlightLastMove(move) {
        const fromSquare = this.getSquare(move.from.row, move.from.col);
        const toSquare = this.getSquare(move.to.row, move.to.col);

        if (fromSquare) {
            fromSquare.classList.add('last-move');
        }
        if (toSquare) {
            toSquare.classList.add('last-move');
        }
    }

    /**
     * Select a square
     * @param {number} row - Row index
     * @param {number} col - Column index
     */
    selectSquare(row, col) {
        this.deselectSquare();

        const square = this.getSquare(row, col);
        if (square) {
            square.classList.add('selected');
            this.selectedSquare = { row, col };
        }
    }

    /**
     * Deselect current square
     */
    deselectSquare() {
        if (this.selectedSquare) {
            const square = this.getSquare(this.selectedSquare.row, this.selectedSquare.col);
            if (square) {
                square.classList.remove('selected');
            }
            this.selectedSquare = null;
        }
    }

    /**
     * Update a single square
     * @param {number} row - Row index
     * @param {number} col - Column index
     * @param {Piece|null} piece - Piece or null
     */
    updateSquare(row, col, piece) {
        const square = this.getSquare(row, col);
        if (!square) return;

        // Remove existing piece
        const existingPiece = this.getPieceElement(square);
        if (existingPiece) {
            existingPiece.remove();
        }

        // Add new piece if provided
        if (piece) {
            const pieceElement = this.createPieceElement(piece);
            square.appendChild(pieceElement);
        }
    }

    /**
     * Get square element at position
     * @param {number} row - Row index
     * @param {number} col - Column index
     * @returns {HTMLElement|null} Square element
     */
    getSquare(row, col) {
        return this.boardElement.querySelector(
            `.square[data-row="${row}"][data-col="${col}"]`
        );
    }

    /**
     * Get piece element within a square
     * @param {HTMLElement} square - Square element
     * @returns {HTMLElement|null} Piece element
     */
    getPieceElement(square) {
        return square.querySelector('.piece');
    }

    /**
     * Add rank and file coordinates to board
     */
    addCoordinates() {
        const files = 'abcdefgh';
        const ranks = '87654321';

        // Add file labels (a-h) at bottom
        for (let col = 0; col < 8; col++) {
            const square = this.getSquare(7, col);
            if (square) {
                const label = document.createElement('div');
                label.className = 'coordinate file-label';
                label.textContent = files[col];
                square.appendChild(label);
            }
        }

        // Add rank labels (1-8) on left
        for (let row = 0; row < 8; row++) {
            const square = this.getSquare(row, 0);
            if (square) {
                const label = document.createElement('div');
                label.className = 'coordinate rank-label';
                label.textContent = ranks[row];
                square.appendChild(label);
            }
        }
    }

    /**
     * Show check indicator on king
     * @param {string} color - King color
     * @param {Board} board - Game board
     */
    showCheckIndicator(color, board) {
        const kingPos = board.findKing(color);
        if (!kingPos) return;

        const square = this.getSquare(kingPos.row, kingPos.col);
        if (square) {
            square.classList.add('in-check');
        }
    }

    /**
     * Clear check indicator
     * @param {string} color - King color
     * @param {Board} board - Game board
     */
    clearCheckIndicator(color, board) {
        const kingPos = board.findKing(color);
        if (!kingPos) return;

        const square = this.getSquare(kingPos.row, kingPos.col);
        if (square) {
            square.classList.remove('in-check');
        }
    }

    /**
     * Animate piece movement
     * @param {number} fromRow - Source row
     * @param {number} fromCol - Source column
     * @param {number} toRow - Target row
     * @param {number} toCol - Target column
     * @param {Function} callback - Callback after animation
     */
    animateMove(fromRow, fromCol, toRow, toCol, callback) {
        const fromSquare = this.getSquare(fromRow, fromCol);
        const toSquare = this.getSquare(toRow, toCol);

        if (!fromSquare || !toSquare) {
            if (callback) callback();
            return;
        }

        const piece = this.getPieceElement(fromSquare);
        if (!piece) {
            if (callback) callback();
            return;
        }

        // Calculate positions
        const fromRect = fromSquare.getBoundingClientRect();
        const toRect = toSquare.getBoundingClientRect();

        const deltaX = toRect.left - fromRect.left;
        const deltaY = toRect.top - fromRect.top;

        // Apply animation
        piece.style.transform = `translate(${deltaX}px, ${deltaY}px)`;
        piece.style.transition = 'transform 0.3s ease-out';

        // Complete animation
        setTimeout(() => {
            piece.style.transform = '';
            piece.style.transition = '';
            if (callback) callback();
        }, 300);
    }

    /**
     * Clear all visual highlights and selections
     */
    clearAllHighlights() {
        this.clearHighlights();
        this.deselectSquare();

        // Remove last-move highlights
        this.boardElement.querySelectorAll('.last-move').forEach(square => {
            square.classList.remove('last-move');
        });

        // Remove check indicators
        this.boardElement.querySelectorAll('.in-check').forEach(square => {
            square.classList.remove('in-check');
        });
    }
}
