import { DungeonGenerator } from '../dungeon/DungeonGenerator.js';

/**
 * GameEngine for Manual Dungeon Construction with Player Movement
 */
export class GameEngine {
    constructor() {
        this.dungeon = new DungeonGenerator();
        this.player = null;
        this.selectedEntity = null;
        this.isRunning = false;
        this.plannedPath = []; // Array of {x,y}

        // Callbacks
        this.onEntityUpdate = null;
        this.onEntityMove = null;
        this.onEntitySelect = null;
        this.onPathChange = null;
    }

    startMission(missionConfig) {

        this.dungeon.startDungeon(missionConfig);

        // Create player at center of first tile
        this.createPlayer(1.5, 2.5); // Center of 2x6 corridor

        this.isRunning = true;
    }

    createPlayer(x, y) {
        this.player = {
            id: 'p1',
            name: 'Barbarian',
            x: Math.floor(x),
            y: Math.floor(y),
            texturePath: '/assets/images/dungeon1/standees/barbaro.png'
        };

        if (this.onEntityUpdate) {
            this.onEntityUpdate(this.player);
        }
    }

    onCellClick(x, y) {
        // 1. SELECT / DESELECT PLAYER
        if (this.player && x === this.player.x && y === this.player.y) {
            if (this.selectedEntity === this.player) {
                // Toggle Deselect
                this.deselectPlayer();
            } else {
                // Select
                this.selectedEntity = this.player;
                if (this.onEntitySelect) {
                    this.onEntitySelect(this.player.id, true);
                }
            }
            return;
        }

        // 2. PLAN MOVEMENT (If player selected)
        if (this.selectedEntity === this.player) {
            this.planStep(x, y);
        }
    }

    deselectPlayer() {
        this.selectedEntity = null;
        this.plannedPath = [];
        if (this.onEntitySelect) this.onEntitySelect(this.player.id, false);
        if (this.onPathChange) this.onPathChange([]);
    }

    planStep(x, y) {
        // Determine start point (either current player pos or last planned step)
        const lastStep = this.plannedPath.length > 0
            ? this.plannedPath[this.plannedPath.length - 1]
            : { x: this.player.x, y: this.player.y };

        // Check Adjacency
        const dx = Math.abs(x - lastStep.x);
        const dy = Math.abs(y - lastStep.y);
        const isAdjacent = (dx + dy) === 1;

        // Check Walkability
        const isWalkable = this.canMoveTo(x, y);

        // Check if already in path (prevent loops for simplicity or allow backtracking? User said "mark contigua", implying adding)
        // If clicking the last added step, maybe remove it? (Undo)
        if (this.plannedPath.length > 0 && x === lastStep.x && y === lastStep.y) {
            // Clicked last step -> Undo
            this.plannedPath.pop();
            if (this.onPathChange) this.onPathChange(this.plannedPath);
            return;
        }

        if (isAdjacent && isWalkable) {
            // Check if not already visited in this path to prevent self-intersection weirdness
            const alreadyInPath = this.plannedPath.some(p => p.x === x && p.y === y);
            const isPlayerPos = this.player.x === x && this.player.y === y;

            if (!alreadyInPath && !isPlayerPos) {
                this.plannedPath.push({ x, y });
                if (this.onPathChange) {
                    this.onPathChange(this.plannedPath);
                }
            }
        }
    }

    executeMovePath() {
        if (!this.player || !this.plannedPath.length) return;

        // Clone path for the move event
        const path = [...this.plannedPath];

        // Update player logic verification immediately (teleport logic)
        // The visualization will handle the "botecitos"
        const finalDest = path[path.length - 1];
        this.player.x = finalDest.x;
        this.player.y = finalDest.y;

        // Trigger Movement Event (Renderer will animate)
        if (this.onEntityMove) {
            this.onEntityMove(this.player, path);
        }

        // Cleanup
        this.deselectPlayer();
    }

    canMoveTo(x, y) {
        // Check if cell is walkable (occupied by a tile)
        return this.dungeon.grid.isOccupied(x, y);
    }

    // Deprecated direct move
    movePlayer(x, y) {
        this.player.x = x;
        this.player.y = y;
        if (this.onEntityMove) this.onEntityMove(this.player, [{ x, y }]);
    }

    isPlayerAdjacentToDoor(doorCells) {
        if (!this.player) return false;

        // doorCells should be an array of {x, y} objects
        // If it sends a single object, wrap it
        const cells = Array.isArray(doorCells) ? doorCells : [doorCells];

        for (const cell of cells) {
            const dx = Math.abs(this.player.x - cell.x);
            const dy = Math.abs(this.player.y - cell.y);

            // Adjacent means distance of 1 in one direction and 0 in the other
            if ((dx === 1 && dy === 0) || (dx === 0 && dy === 1)) {
                return true;
            }
        }
        return false;
    }

    update(time) {
        // Minimal update loop
    }
}
