class Game2048 {
    constructor() {
        this.size = 4;
        this.grid = [];
        this.score = 0;
        this.gameWon = false;
        this.gameOver = false;
        this.moved = false;
        this.stats = { moves: 0, startTime: null, gameTime: 0, maxTile: 2, mergeCount: 0 };

        this.initializeGrid();
        this.updateDisplay();
        this.addRandomTile();
        this.addRandomTile();
        this.updateDisplay();
        this.bindEvents();
        this.startTimer();
    }

    initializeGrid() {
        this.grid = [];
        for (let i = 0; i < this.size; i++) {
            this.grid[i] = [];
            for (let j = 0; j < this.size; j++) {
                this.grid[i][j] = 0;
            }
        }
    }

    addRandomTile() {
        const emptyCells = [];
        for (let i = 0; i < this.size; i++) {
            for (let j = 0; j < this.size; j++) {
                if (this.grid[i][j] === 0) emptyCells.push({ x: i, y: j });
            }
        }
        if (emptyCells.length > 0) {
            const cell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
            const value = Math.random() < 0.9 ? 2 : 4;
            this.grid[cell.x][cell.y] = value;
            this.createTileElement(cell.x, cell.y, value, true);
        }
    }

    createTileElement(x, y, value, isNew = false) {
        const container = document.getElementById('tile-container');
        const tile = document.createElement('div');
        tile.className = `tile tile-${value}`;
        if (isNew) tile.classList.add('tile-new');
        tile.textContent = value;
        tile.style.left = `${y * 25}%`;
        tile.style.top = `${x * 25}%`;
        tile.dataset.x = x;
        tile.dataset.y = y;
        tile.dataset.value = value;
        container.appendChild(tile);
        setTimeout(() => tile.classList.remove('tile-new'), 200);
    }

    updateDisplay() {
        const container = document.getElementById('tile-container');
        container.innerHTML = '';
        for (let i = 0; i < this.size; i++) {
            for (let j = 0; j < this.size; j++) {
                if (this.grid[i][j] !== 0) this.createTileElement(i, j, this.grid[i][j]);
            }
        }
        document.getElementById('score').textContent = this.score;
    }

    move(direction) {
        if (this.gameOver) return;
        this.moved = false;

        switch (direction) {
            case 'up': this.moveUp(); break;
            case 'down': this.moveDown(); break;
            case 'left': this.moveLeft(); break;
            case 'right': this.moveRight(); break;
        }

        if (this.moved) {
            this.stats.moves++;
            this.addRandomTile();
            this.updateDisplay();

            if (this.isGameWon() && !this.gameWon) {
                this.gameWon = true;
                this.showEndScreen('你赢了！🎉');
            } else if (this.isGameOver()) {
                this.gameOver = true;
                this.showEndScreen('游戏结束！');
            }
        }
    }

    moveLeft() {
        for (let i = 0; i < this.size; i++) {
            const row = this.grid[i].filter(v => v !== 0);
            const merged = [];
            for (let j = 0; j < row.length - 1; j++) {
                if (row[j] === row[j + 1] && !merged[j] && !merged[j + 1]) {
                    row[j] *= 2; this.score += row[j]; this.stats.mergeCount++;
                    this.stats.maxTile = Math.max(this.stats.maxTile, row[j]);
                    row[j + 1] = 0; merged[j] = true;
                }
            }
            const newRow = row.filter(v => v !== 0);
            while (newRow.length < this.size) newRow.push(0);
            for (let j = 0; j < this.size; j++) {
                if (this.grid[i][j] !== newRow[j]) this.moved = true;
                this.grid[i][j] = newRow[j];
            }
        }
    }

    moveRight() {
        for (let i = 0; i < this.size; i++) {
            const row = this.grid[i].filter(v => v !== 0);
            const merged = [];
            for (let j = row.length - 1; j > 0; j--) {
                if (row[j] === row[j - 1] && !merged[j] && !merged[j - 1]) {
                    row[j] *= 2; this.score += row[j]; this.stats.mergeCount++;
                    this.stats.maxTile = Math.max(this.stats.maxTile, row[j]);
                    row[j - 1] = 0; merged[j] = true;
                }
            }
            const newRow = row.filter(v => v !== 0);
            while (newRow.length < this.size) newRow.unshift(0);
            for (let j = 0; j < this.size; j++) {
                if (this.grid[i][j] !== newRow[j]) this.moved = true;
                this.grid[i][j] = newRow[j];
            }
        }
    }

    moveUp() {
        for (let j = 0; j < this.size; j++) {
            const col = [];
            for (let i = 0; i < this.size; i++) { if (this.grid[i][j] !== 0) col.push(this.grid[i][j]); }
            const merged = [];
            for (let i = 0; i < col.length - 1; i++) {
                if (col[i] === col[i + 1] && !merged[i] && !merged[i + 1]) {
                    col[i] *= 2; this.score += col[i]; this.stats.mergeCount++;
                    this.stats.maxTile = Math.max(this.stats.maxTile, col[i]);
                    col[i + 1] = 0; merged[i] = true;
                }
            }
            const newCol = col.filter(v => v !== 0);
            while (newCol.length < this.size) newCol.push(0);
            for (let i = 0; i < this.size; i++) {
                if (this.grid[i][j] !== newCol[i]) this.moved = true;
                this.grid[i][j] = newCol[i];
            }
        }
    }

    moveDown() {
        for (let j = 0; j < this.size; j++) {
            const col = [];
            for (let i = 0; i < this.size; i++) { if (this.grid[i][j] !== 0) col.push(this.grid[i][j]); }
            const merged = [];
            for (let i = col.length - 1; i > 0; i--) {
                if (col[i] === col[i - 1] && !merged[i] && !merged[i - 1]) {
                    col[i] *= 2; this.score += col[i]; this.stats.mergeCount++;
                    this.stats.maxTile = Math.max(this.stats.maxTile, col[i]);
                    col[i - 1] = 0; merged[i] = true;
                }
            }
            const newCol = col.filter(v => v !== 0);
            while (newCol.length < this.size) newCol.unshift(0);
            for (let i = 0; i < this.size; i++) {
                if (this.grid[i][j] !== newCol[i]) this.moved = true;
                this.grid[i][j] = newCol[i];
            }
        }
    }

    isGameWon() {
        for (let i = 0; i < this.size; i++)
            for (let j = 0; j < this.size; j++)
                if (this.grid[i][j] === 2048) return true;
        return false;
    }

    isGameOver() {
        for (let i = 0; i < this.size; i++)
            for (let j = 0; j < this.size; j++) {
                if (this.grid[i][j] === 0) return false;
                const c = this.grid[i][j];
                if ((i > 0 && this.grid[i-1][j] === c) || (i < this.size-1 && this.grid[i+1][j] === c) ||
                    (j > 0 && this.grid[i][j-1] === c) || (j < this.size-1 && this.grid[i][j+1] === c))
                    return false;
            }
        return true;
    }

    showEndScreen(text) {
        const message = document.getElementById('game-message');
        message.className = 'game-message ' + (this.gameWon ? 'game-won' : 'game-over');
        message.style.display = 'flex';
        message.querySelector('p').innerHTML =
            `${text}<br><span style="font-size:16px;opacity:0.8;">` +
            `得分 ${this.score} · 步数 ${this.stats.moves} · ` +
            `最大方块 ${this.stats.maxTile} · 用时 ${this.stats.gameTime}秒</span>`;
    }

    restart() {
        this.score = 0;
        this.gameWon = false;
        this.gameOver = false;
        this.moved = false;
        this.stats = { moves: 0, startTime: null, gameTime: 0, maxTile: 2, mergeCount: 0 };
        this.initializeGrid();
        this.addRandomTile();
        this.addRandomTile();
        this.updateDisplay();
        document.getElementById('game-message').style.display = 'none';
        this.startTimer();
    }

    startTimer() {
        this.stats.startTime = Date.now();
        if (this.timerInterval) clearInterval(this.timerInterval);
        this.timerInterval = setInterval(() => {
            if (!this.gameOver && this.stats.startTime) {
                this.stats.gameTime = Math.floor((Date.now() - this.stats.startTime) / 1000);
            }
        }, 1000);
    }

    bindEvents() {
        document.getElementById('retry-btn').addEventListener('click', () => this.restart());
    }
}

let game;
document.addEventListener('DOMContentLoaded', () => {
    game = new Game2048();
    window.game2048 = game;
});
