// EL3AB Chess Board PRO - Rendering, Drag & Drop, Arrows, Highlights, Pre-moves, Animations

const Board = {
  el: null,
  wrapperEl: null,
  squares: [],
  flipped: false,
  position: null,
  selectedSquare: null,
  legalMoves: [],
  lastMove: null,
  dragPiece: null,
  dragStartSquare: null,
  onMove: null,
  enabled: true,
  playerColor: 'w',

  // Arrow & highlight system
  arrows: [],
  highlights: [],
  arrowCanvas: null,
  arrowCtx: null,
  arrowDragStart: null,
  arrowDragCurrent: null,
  isRightDragging: false,

  // Pre-move system
  premove: null,
  premoveFrom: null,
  premoveTo: null,

  // Move navigation
  positionHistory: [],
  viewingIndex: -1,

  // Coordinate elements
  coordsFile: null,
  coordsRank: null,

  PIECES: {
    wK: '♚', wQ: '♛', wR: '♜', wB: '♝', wN: '♞', wP: '♟',
    bK: '♚', bQ: '♛', bR: '♜', bB: '♝', bN: '♞', bP: '♟'
  },

  FILES: ['a','b','c','d','e','f','g','h'],
  RANKS: ['8','7','6','5','4','3','2','1'],

  init(containerId, options = {}) {
    this.el = document.getElementById(containerId);
    if (!this.el) return;
    this.wrapperEl = this.el.closest('.board-wrapper') || this.el.parentElement;
    this.flipped = options.flipped || false;
    this.onMove = options.onMove || null;
    this.playerColor = options.playerColor || 'w';
    this.enabled = true;
    this.arrows = [];
    this.highlights = [];
    this.premove = null;
    this.premoveFrom = null;
    this.premoveTo = null;
    this.positionHistory = [];
    this.viewingIndex = -1;
    this.render();
    this.bindEvents();
    this.bindKeyboard();
    this.setupArrowCanvas();
    this.renderCoords();
  },

  render() {
    this.el.innerHTML = '';
    this.el.className = 'board';
    this.squares = [];

    const ranks = this.flipped ? [0,1,2,3,4,5,6,7] : [7,6,5,4,3,2,1,0];
    const files = this.flipped ? [7,6,5,4,3,2,1,0] : [0,1,2,3,4,5,6,7];

    for (let r = 0; r < 8; r++) {
      for (let f = 0; f < 8; f++) {
        const rank = ranks[r];
        const file = files[f];
        const sq = document.createElement('div');
        const isLight = (rank + file) % 2 === 0;
        const sqName = this.FILES[file] + this.RANKS[7 - rank];

        sq.className = 'square ' + (isLight ? 'square-light' : 'square-dark');
        sq.dataset.square = sqName;
        this.el.appendChild(sq);
        this.squares.push(sq);
      }
    }
  },

  renderCoords() {
    const settings = this.getSettings();
    if (settings.coords === false) return;

    if (this.coordsFile) this.coordsFile.remove();
    if (this.coordsRank) this.coordsRank.remove();

    const fileCoords = document.createElement('div');
    fileCoords.className = 'board-coords-file';
    const files = this.flipped ? [...this.FILES].reverse() : this.FILES;
    files.forEach(f => {
      const span = document.createElement('span');
      span.textContent = f;
      fileCoords.appendChild(span);
    });
    this.coordsFile = fileCoords;

    const rankCoords = document.createElement('div');
    rankCoords.className = 'board-coords-rank';
    const ranks = this.flipped ? ['1','2','3','4','5','6','7','8'] : ['8','7','6','5','4','3','2','1'];
    ranks.forEach(r => {
      const span = document.createElement('span');
      span.textContent = r;
      rankCoords.appendChild(span);
    });
    this.coordsRank = rankCoords;

    this.wrapperEl.appendChild(fileCoords);
    this.wrapperEl.appendChild(rankCoords);
  },

  setupArrowCanvas() {
    // Remove old canvas if exists
    const existing = this.wrapperEl.querySelector('.arrow-canvas');
    if (existing) existing.remove();

    const canvas = document.createElement('canvas');
    canvas.className = 'arrow-canvas';
    canvas.style.position = 'absolute';
    canvas.style.inset = '0';
    canvas.style.width = '100%';
    canvas.style.height = '100%';
    canvas.style.pointerEvents = 'none';
    canvas.style.zIndex = '5';
    this.wrapperEl.appendChild(canvas);
    this.arrowCanvas = canvas;
    this.arrowCtx = canvas.getContext('2d');
    this.resizeCanvas();
  },

  resizeCanvas() {
    if (!this.arrowCanvas || !this.el) return;
    const rect = this.el.getBoundingClientRect();
    this.arrowCanvas.width = rect.width;
    this.arrowCanvas.height = rect.height;
  },

  setPosition(chess) {
    this.position = chess;
    this.updatePieces();
  },

  updatePieces() {
    if (!this.position) return;
    const board = this.position.board();
    const assets = window.__themeAssets || {};

    this.squares.forEach(sq => {
      const sqName = sq.dataset.square;
      const file = this.FILES.indexOf(sqName[0]);
      const rank = 8 - parseInt(sqName[1]);
      const piece = board[rank][file];

      let pieceEl = sq.querySelector('.piece:not(.piece-ghost)');
      if (piece) {
        const key = piece.color + piece.type.toUpperCase();
        if (!pieceEl) {
          pieceEl = document.createElement('div');
          pieceEl.className = 'piece';
          sq.appendChild(pieceEl);
        }
        const customSrc = assets['piece-' + key];
        if (customSrc) {
          pieceEl.textContent = '';
          let img = pieceEl.querySelector('img');
          if (!img) {
            img = document.createElement('img');
            img.style.cssText = 'width:100%;height:100%;object-fit:contain;pointer-events:none;';
            pieceEl.appendChild(img);
          }
          img.src = customSrc;
        } else {
          const img = pieceEl.querySelector('img');
          if (img) img.remove();
          pieceEl.textContent = this.PIECES[key];
        }
        pieceEl.dataset.piece = key;
        pieceEl.dataset.color = piece.color;
      } else {
        if (pieceEl) pieceEl.remove();
      }
    });

    this.updateHighlights();
    this.renderPremoveGhost();
  },

  updateHighlights() {
    this.squares.forEach(sq => {
      sq.classList.remove('selected', 'legal-move', 'legal-capture', 'last-move', 'in-check', 'premove-from', 'premove-to', 'highlight-green', 'highlight-red', 'highlight-yellow');
    });

    // Last move highlight
    if (this.lastMove) {
      const fromSq = this.getSquareEl(this.lastMove.from);
      const toSq = this.getSquareEl(this.lastMove.to);
      if (fromSq) fromSq.classList.add('last-move');
      if (toSq) toSq.classList.add('last-move');
    }

    // Selected square & legal moves
    if (this.selectedSquare) {
      const selSq = this.getSquareEl(this.selectedSquare);
      if (selSq) selSq.classList.add('selected');

      const settings = this.getSettings();
      if (settings.legalMoves !== false) {
        this.legalMoves.forEach(move => {
          const sq = this.getSquareEl(move.to);
          if (sq) {
            if (move.captured) {
              sq.classList.add('legal-capture');
            } else {
              sq.classList.add('legal-move');
            }
          }
        });
      }
    }

    // Check highlight
    if (this.position && this.position.in_check()) {
      const turn = this.position.turn();
      const board = this.position.board();
      for (let r = 0; r < 8; r++) {
        for (let f = 0; f < 8; f++) {
          const p = board[r][f];
          if (p && p.type === 'k' && p.color === turn) {
            const sqName = this.FILES[f] + (8 - r);
            const sq = this.getSquareEl(sqName);
            if (sq) sq.classList.add('in-check');
          }
        }
      }
    }

    // Premove highlights
    if (this.premoveFrom) {
      const sq = this.getSquareEl(this.premoveFrom);
      if (sq) sq.classList.add('premove-from');
    }
    if (this.premoveTo) {
      const sq = this.getSquareEl(this.premoveTo);
      if (sq) sq.classList.add('premove-to');
    }

    // Square highlights from right-click
    this.highlights.forEach(h => {
      const sq = this.getSquareEl(h.square);
      if (sq) sq.classList.add('highlight-' + h.color);
    });
  },

  renderPremoveGhost() {
    // Remove existing ghosts
    this.squares.forEach(sq => {
      const ghost = sq.querySelector('.piece-ghost');
      if (ghost) ghost.remove();
    });

    if (!this.premoveFrom || !this.premoveTo || !this.position) return;

    const board = this.position.board();
    const file = this.FILES.indexOf(this.premoveFrom[0]);
    const rank = 8 - parseInt(this.premoveFrom[1]);
    const piece = board[rank][file];
    if (!piece) return;

    const toSq = this.getSquareEl(this.premoveTo);
    if (!toSq) return;

    const key = piece.color + piece.type.toUpperCase();
    const ghost = document.createElement('div');
    ghost.className = 'piece piece-ghost';
    const assets = window.__themeAssets || {};
    const customSrc = assets['piece-' + key];
    if (customSrc) {
      ghost.innerHTML = '<img src="' + customSrc + '" style="width:100%;height:100%;object-fit:contain;pointer-events:none;">';
    } else {
      ghost.textContent = this.PIECES[key];
    }
    ghost.style.opacity = '0.4';
    ghost.style.pointerEvents = 'none';
    toSq.appendChild(ghost);
  },

  getSquareEl(name) {
    return this.el ? this.el.querySelector('[data-square="' + name + '"]') : null;
  },

  getSettings() {
    try {
      return JSON.parse(localStorage.getItem('el3ab_settings') || '{}');
    } catch (e) {
      return {};
    }
  },

  bindEvents() {
    let isDragging = false;
    let dragEl = null;
    let startX, startY;
    const squareSize = () => this.el.getBoundingClientRect().width / 8;

    const handleStart = (e) => {
      // Right click for arrows/highlights
      if (e.button === 2) {
        e.preventDefault();
        this.handleRightClickStart(e);
        return;
      }

      if (e.button !== 0 && !e.touches) return;

      const touch = e.touches ? e.touches[0] : e;
      const sq = touch.target.closest('.square');
      if (!sq) return;

      const sqName = sq.dataset.square;
      const pieceEl = sq.querySelector('.piece:not(.piece-ghost)');

      // Clear arrows/highlights on left click
      if (this.arrows.length > 0 || this.highlights.length > 0) {
        this.clearAnnotations();
      }

      const turn = this.position ? this.position.turn() : 'w';
      const isPlayerTurn = turn === this.playerColor;

      // Click-to-move: if a square is selected and we click a valid target
      if (this.selectedSquare && sqName !== this.selectedSquare) {
        const move = this.legalMoves.find(m => m.to === sqName);
        if (move && isPlayerTurn && this.enabled) {
          this.makeUserMove(move);
          return;
        }
        // If clicking on own piece, re-select
        if (pieceEl && pieceEl.dataset.color === this.playerColor) {
          // Fall through to select new piece
        } else {
          // Try pre-move if not player's turn
          if (!isPlayerTurn && this.selectedSquare) {
            this.setPremove(this.selectedSquare, sqName);
            this.deselect();
            return;
          }
          this.deselect();
          return;
        }
      }

      if (!pieceEl) {
        this.deselect();
        return;
      }

      // Only select own pieces
      if (pieceEl.dataset.color !== this.playerColor) {
        this.deselect();
        return;
      }

      this.selectedSquare = sqName;
      if (isPlayerTurn) {
        this.legalMoves = this.position ? this.position.moves({ square: sqName, verbose: true }) : [];
      } else {
        this.legalMoves = [];
      }
      this.updateHighlights();

      // For premove: if not player's turn, mark the square as selected visually
      if (!isPlayerTurn) {
        const selSq = this.getSquareEl(sqName);
        if (selSq) selSq.classList.add('premove-from');
      }

      // Start drag
      isDragging = true;
      this.dragStartSquare = sqName;
      dragEl = pieceEl;
      startX = touch.clientX;
      startY = touch.clientY;

      dragEl.classList.add('dragging');
      const sqRect = sq.getBoundingClientRect();
      dragEl.style.width = sqRect.width * 0.85 + 'px';
      dragEl.style.height = sqRect.height * 0.85 + 'px';
      dragEl.style.left = (touch.clientX - sqRect.width * 0.425) + 'px';
      dragEl.style.top = (touch.clientY - sqRect.height * 0.425) + 'px';
      dragEl.style.fontSize = (sqRect.width * 0.75) + 'px';

      e.preventDefault();
    };

    const handleMove = (e) => {
      if (this.isRightDragging) {
        this.handleRightClickMove(e);
        return;
      }
      if (!isDragging || !dragEl) return;
      const touch = e.touches ? e.touches[0] : e;
      const sqSize = squareSize();
      dragEl.style.left = (touch.clientX - sqSize * 0.425) + 'px';
      dragEl.style.top = (touch.clientY - sqSize * 0.425) + 'px';
      e.preventDefault();
    };

    const handleEnd = (e) => {
      if (this.isRightDragging) {
        this.handleRightClickEnd(e);
        return;
      }
      if (!isDragging || !dragEl) return;
      isDragging = false;
      dragEl.classList.remove('dragging');
      dragEl.style = '';

      const touch = e.changedTouches ? e.changedTouches[0] : e;
      const rect = this.el.getBoundingClientRect();
      const x = touch.clientX - rect.left;
      const y = touch.clientY - rect.top;
      const sqSize = rect.width / 8;

      let fileIdx = Math.floor(x / sqSize);
      let rankIdx = Math.floor(y / sqSize);

      if (this.flipped) {
        fileIdx = 7 - fileIdx;
        rankIdx = 7 - rankIdx;
      }

      if (fileIdx >= 0 && fileIdx < 8 && rankIdx >= 0 && rankIdx < 8) {
        const targetSq = this.FILES[fileIdx] + (8 - rankIdx);
        if (targetSq !== this.dragStartSquare) {
          const turn = this.position ? this.position.turn() : 'w';
          const isPlayerTurn = turn === this.playerColor;

          if (isPlayerTurn && this.enabled) {
            const move = this.legalMoves.find(m => m.to === targetSq);
            if (move) {
              this.makeUserMove(move);
              dragEl = null;
              return;
            }
          } else if (!isPlayerTurn) {
            // Pre-move via drag
            this.setPremove(this.dragStartSquare, targetSq);
            this.deselect();
            dragEl = null;
            this.updatePieces();
            return;
          }
        }
      }

      this.updatePieces();
      dragEl = null;
    };

    // Prevent context menu on board
    this.el.addEventListener('contextmenu', (e) => e.preventDefault());

    this.el.addEventListener('mousedown', handleStart);
    document.addEventListener('mousemove', handleMove);
    document.addEventListener('mouseup', handleEnd);
    this.el.addEventListener('touchstart', handleStart, { passive: false });
    document.addEventListener('touchmove', handleMove, { passive: false });
    document.addEventListener('touchend', handleEnd);
  },

  // --- Right-click arrow/highlight system ---
  handleRightClickStart(e) {
    const rect = this.el.getBoundingClientRect();
    const x = (e.clientX || e.pageX) - rect.left;
    const y = (e.clientY || e.pageY) - rect.top;
    const sqSize = rect.width / 8;

    let fileIdx = Math.floor(x / sqSize);
    let rankIdx = Math.floor(y / sqSize);

    if (this.flipped) {
      fileIdx = 7 - fileIdx;
      rankIdx = 7 - rankIdx;
    }

    if (fileIdx < 0 || fileIdx > 7 || rankIdx < 0 || rankIdx > 7) return;

    const sqName = this.FILES[fileIdx] + (8 - rankIdx);
    this.arrowDragStart = sqName;
    this.arrowDragCurrent = sqName;
    this.isRightDragging = true;
    this.deselect();
  },

  handleRightClickMove(e) {
    if (!this.isRightDragging) return;
    const rect = this.el.getBoundingClientRect();
    const x = (e.clientX || e.pageX) - rect.left;
    const y = (e.clientY || e.pageY) - rect.top;
    const sqSize = rect.width / 8;

    let fileIdx = Math.floor(x / sqSize);
    let rankIdx = Math.floor(y / sqSize);

    if (this.flipped) {
      fileIdx = 7 - fileIdx;
      rankIdx = 7 - rankIdx;
    }

    fileIdx = Math.max(0, Math.min(7, fileIdx));
    rankIdx = Math.max(0, Math.min(7, rankIdx));

    const sqName = this.FILES[fileIdx] + (8 - rankIdx);
    if (sqName !== this.arrowDragCurrent) {
      this.arrowDragCurrent = sqName;
      this.drawArrows();
    }
  },

  handleRightClickEnd(e) {
    if (!this.isRightDragging) return;
    this.isRightDragging = false;

    const color = e.shiftKey ? 'red' : (e.altKey ? 'yellow' : 'green');

    if (this.arrowDragStart === this.arrowDragCurrent) {
      // Just a right-click on a square - toggle highlight
      const existingIdx = this.highlights.findIndex(h => h.square === this.arrowDragStart && h.color === color);
      if (existingIdx >= 0) {
        this.highlights.splice(existingIdx, 1);
      } else {
        // Remove any highlight on same square
        this.highlights = this.highlights.filter(h => h.square !== this.arrowDragStart);
        this.highlights.push({ square: this.arrowDragStart, color: color });
      }
      this.updateHighlights();
    } else {
      // Arrow from start to current
      const existingIdx = this.arrows.findIndex(a => a.from === this.arrowDragStart && a.to === this.arrowDragCurrent && a.color === color);
      if (existingIdx >= 0) {
        this.arrows.splice(existingIdx, 1);
      } else {
        this.arrows.push({ from: this.arrowDragStart, to: this.arrowDragCurrent, color: color });
      }
    }

    this.arrowDragStart = null;
    this.arrowDragCurrent = null;
    this.drawArrows();
  },

  clearAnnotations() {
    this.arrows = [];
    this.highlights = [];
    this.updateHighlights();
    this.drawArrows();
  },

  getSquareCenter(sqName) {
    const file = this.FILES.indexOf(sqName[0]);
    const rank = 8 - parseInt(sqName[1]);

    let col = file;
    let row = rank;

    if (this.flipped) {
      col = 7 - file;
      row = 7 - rank;
    }

    const rect = this.el.getBoundingClientRect();
    const sqSize = rect.width / 8;

    return {
      x: col * sqSize + sqSize / 2,
      y: row * sqSize + sqSize / 2
    };
  },

  drawArrows() {
    if (!this.arrowCtx || !this.arrowCanvas) return;
    this.resizeCanvas();
    const ctx = this.arrowCtx;
    const w = this.arrowCanvas.width;
    const h = this.arrowCanvas.height;
    ctx.clearRect(0, 0, w, h);

    const style = getComputedStyle(document.documentElement);
    const colorMap = {
      green: style.getPropertyValue('--arrow-green').trim() || 'rgba(21, 180, 90, 0.7)',
      red: style.getPropertyValue('--arrow-red').trim() || 'rgba(220, 50, 50, 0.7)',
      yellow: style.getPropertyValue('--arrow-yellow').trim() || 'rgba(220, 180, 30, 0.7)'
    };

    const allArrows = [...this.arrows];
    // Draw in-progress arrow
    if (this.isRightDragging && this.arrowDragStart && this.arrowDragCurrent && this.arrowDragStart !== this.arrowDragCurrent) {
      allArrows.push({ from: this.arrowDragStart, to: this.arrowDragCurrent, color: 'green' });
    }

    allArrows.forEach(arrow => {
      const from = this.getSquareCenter(arrow.from);
      const to = this.getSquareCenter(arrow.to);
      const col = colorMap[arrow.color] || colorMap.green;
      this.drawOneArrow(ctx, from.x, from.y, to.x, to.y, col);
    });
  },

  drawOneArrow(ctx, x1, y1, x2, y2, color) {
    const sqSize = this.arrowCanvas.width / 8;
    const headLen = sqSize * 0.35;
    const lineWidth = sqSize * 0.18;
    const angle = Math.atan2(y2 - y1, x2 - x1);

    ctx.save();
    ctx.strokeStyle = color;
    ctx.fillStyle = color;
    ctx.lineWidth = lineWidth;
    ctx.lineCap = 'round';

    // Draw line (shortened to not overlap arrowhead)
    const endX = x2 - headLen * 0.6 * Math.cos(angle);
    const endY = y2 - headLen * 0.6 * Math.sin(angle);
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    ctx.lineTo(endX, endY);
    ctx.stroke();

    // Draw arrowhead
    ctx.beginPath();
    ctx.moveTo(x2, y2);
    ctx.lineTo(x2 - headLen * Math.cos(angle - Math.PI / 6), y2 - headLen * Math.sin(angle - Math.PI / 6));
    ctx.lineTo(x2 - headLen * Math.cos(angle + Math.PI / 6), y2 - headLen * Math.sin(angle + Math.PI / 6));
    ctx.closePath();
    ctx.fill();
    ctx.restore();
  },

  // --- Pre-move system ---
  setPremove(from, to) {
    this.premoveFrom = from;
    this.premoveTo = to;
    this.premove = { from: from, to: to };
    this.updateHighlights();
    this.renderPremoveGhost();
  },

  clearPremove() {
    this.premove = null;
    this.premoveFrom = null;
    this.premoveTo = null;
    this.updateHighlights();
  },

  tryExecutePremove() {
    if (!this.premove || !this.position) return null;
    const turn = this.position.turn();
    if (turn !== this.playerColor) return null;

    const moves = this.position.moves({ square: this.premove.from, verbose: true });
    const match = moves.find(m => m.to === this.premove.to);
    const premoveCopy = this.premove;
    this.clearPremove();

    if (match) {
      return match;
    }
    return null;
  },

  // --- Keyboard navigation ---
  bindKeyboard() {
    document.addEventListener('keydown', (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
      if (e.key === 'ArrowLeft') {
        e.preventDefault();
        this.navigateBack();
      } else if (e.key === 'ArrowRight') {
        e.preventDefault();
        this.navigateForward();
      }
    });
  },

  pushPosition(fen) {
    // Called by Game after each move
    this.positionHistory.push(fen);
    this.viewingIndex = this.positionHistory.length - 1;
  },

  navigateBack() {
    if (this.viewingIndex <= 0) return;
    this.viewingIndex--;
    this.showPositionAt(this.viewingIndex);
  },

  navigateForward() {
    if (this.viewingIndex >= this.positionHistory.length - 1) return;
    this.viewingIndex++;
    this.showPositionAt(this.viewingIndex);
  },

  navigateTo(index) {
    if (index < 0 || index >= this.positionHistory.length) return;
    this.viewingIndex = index;
    this.showPositionAt(index);
  },

  showPositionAt(index) {
    const fen = this.positionHistory[index];
    if (!fen) return;
    const tempChess = new Chess(fen);
    const board = tempChess.board();
    const assets = window.__themeAssets || {};

    this.squares.forEach(sq => {
      const sqName = sq.dataset.square;
      const file = this.FILES.indexOf(sqName[0]);
      const rank = 8 - parseInt(sqName[1]);
      const piece = board[rank][file];

      let pieceEl = sq.querySelector('.piece');
      if (piece) {
        const key = piece.color + piece.type.toUpperCase();
        if (!pieceEl) {
          pieceEl = document.createElement('div');
          pieceEl.className = 'piece';
          sq.appendChild(pieceEl);
        }
        const customSrc = assets['piece-' + key];
        if (customSrc) {
          pieceEl.textContent = '';
          let img = pieceEl.querySelector('img');
          if (!img) {
            img = document.createElement('img');
            img.style.cssText = 'width:100%;height:100%;object-fit:contain;pointer-events:none;';
            pieceEl.appendChild(img);
          }
          img.src = customSrc;
        } else {
          const img = pieceEl.querySelector('img');
          if (img) img.remove();
          pieceEl.textContent = this.PIECES[key];
        }
        pieceEl.dataset.piece = key;
        pieceEl.dataset.color = piece.color;
      } else {
        if (pieceEl) pieceEl.remove();
      }
    });

    this.enabled = (index === this.positionHistory.length - 1);
  },

  isViewingLatest() {
    return this.viewingIndex === this.positionHistory.length - 1;
  },

  // --- Move actions ---
  makeUserMove(move) {
    // Ensure we're viewing the latest position
    if (!this.isViewingLatest()) {
      this.viewingIndex = this.positionHistory.length - 1;
      this.updatePieces();
      this.enabled = true;
    }

    if (move.flags && move.flags.includes('p')) {
      this.showPromotion(move);
    } else {
      this.confirmMove(move);
    }
  },

  showPromotion(move) {
    const overlay = document.createElement('div');
    overlay.className = 'promotion-modal';
    const color = this.position.turn();
    const pieces = ['q', 'r', 'b', 'n'];
    const symbols = {
      q: color === 'w' ? '♕' : '♛',
      r: color === 'w' ? '♖' : '♜',
      b: color === 'w' ? '♗' : '♝',
      n: color === 'w' ? '♘' : '♞'
    };

    const assets = window.__themeAssets || {};
    pieces.forEach(p => {
      const btn = document.createElement('div');
      btn.className = 'promotion-piece';
      const key = color + p.toUpperCase();
      const customSrc = assets['piece-' + key];
      if (customSrc) {
        btn.innerHTML = '<img src="' + customSrc + '" style="width:100%;height:100%;object-fit:contain;">';
      } else {
        btn.textContent = symbols[p];
      }
      btn.onclick = () => {
        overlay.remove();
        this.confirmMove({ from: move.from, to: move.to, promotion: p });
      };
      overlay.appendChild(btn);
    });

    this.wrapperEl.appendChild(overlay);
  },

  confirmMove(move) {
    this.lastMove = { from: move.from, to: move.to };
    this.clearAnnotations();
    this.deselect();
    if (this.onMove) {
      this.onMove(move);
    }
  },

  deselect() {
    this.selectedSquare = null;
    this.legalMoves = [];
    this.updateHighlights();
  },

  flip() {
    this.flipped = !this.flipped;
    this.render();
    this.updatePieces();
    this.renderCoords();
    this.setupArrowCanvas();
    this.drawArrows();
  },

  animateMove(from, to, callback) {
    const fromEl = this.getSquareEl(from);
    const toEl = this.getSquareEl(to);
    if (!fromEl || !toEl) { if (callback) callback(); return; }

    const pieceEl = fromEl.querySelector('.piece');
    if (!pieceEl) { if (callback) callback(); return; }

    const fromRect = fromEl.getBoundingClientRect();
    const toRect = toEl.getBoundingClientRect();
    const dx = toRect.left - fromRect.left;
    const dy = toRect.top - fromRect.top;

    pieceEl.style.transition = 'transform 0.2s cubic-bezier(0.25, 0.1, 0.25, 1)';
    pieceEl.style.transform = 'translate(' + dx + 'px, ' + dy + 'px)';
    pieceEl.style.zIndex = '10';

    const cleanup = () => {
      pieceEl.style.transition = '';
      pieceEl.style.transform = '';
      pieceEl.style.zIndex = '';
      if (callback) callback();
    };

    setTimeout(cleanup, 210);
  },

  // Enable/disable board interaction
  setEnabled(val) {
    this.enabled = val;
  }
};
