import { Vec3 } from 'cc';
import { GridType } from '../core/Define';
import { GameManager } from '../manager/GameManager';
import { forEachLevelEntityNode } from '../level/TileLayout';
import { entityWorldPositionForRole, worldToMoverCellForRole } from '../level/EntitySpawnPlacement';
import { PlayerController } from './PlayerController';
import { VehicleController } from './VehicleController';

/** 按逻辑格查找载具（gridTypes + 当前 committedCell） */
export function findVehicleAtCell(cell: Vec3): VehicleController | null {
    const gm = GameManager.instance;
    if (!gm) return null;
    const fromGrid = gm.getGameObjectAtCell(cell)?.getComponent(VehicleController);
    if (fromGrid) return fromGrid;
    const level = gm.curLevel;
    if (!level) return null;
    let found: VehicleController | null = null;
    forEachLevelEntityNode(level, (ch) => {
        if (found || !ch.name.includes('Vehicle')) return;
        const vc = ch.getComponent(VehicleController);
        if (!vc || !vehicleMatchesCell(vc, cell)) return;
        found = vc;
    });
    return found;
}

/** 双向绑定玩家与载具，并确保 Ride 格注册 */
export function linkRidePair(player: PlayerController, vehicle: VehicleController, cell: Vec3) {
    const gm = GameManager.instance;
    if (!gm) return;
    const config = gm.getCurLevel();
    const theme = config?.theme ?? gm.uiStyle;
    const deck = entityWorldPositionForRole(cell, config ?? undefined, theme, 'vehicle');
    player.setRideVehicle(vehicle);
    vehicle.setPlayer(player);
    vehicle.setDirection(player.direction);
    player.shareCommittedCell(cell);
    vehicle.shareCommittedCell(cell);
    vehicle.node.setPosition(deck);
    gm.addObjAtCell(cell, GridType.Ride, vehicle.node);
    player.setRideBaseFromVehicle(deck);
}

function playerLogicCell(player: PlayerController): Vec3 {
    const committed = player.getCommittedCell();
    if (committed) return committed.clone();
    const gm = GameManager.instance!;
    const config = gm.getCurLevel();
    const theme = config?.theme ?? gm.uiStyle;
    return worldToMoverCellForRole(
        player.node.position,
        config ?? undefined,
        theme,
        'player',
    );
}

function vehicleLogicCell(vehicle: VehicleController): Vec3 | null {
    const committed = vehicle.getCommittedCell();
    if (committed) return committed.clone();
    const spawn = vehicle.getSpawnCell() ?? vehicle.getCommittedCell();
    if (spawn) return spawn.clone();
    const gm = GameManager.instance;
    if (!gm) return null;
    const config = gm.getCurLevel();
    const theme = config?.theme ?? gm.uiStyle;
    return worldToMoverCellForRole(vehicle.node.position, config ?? undefined, theme, 'vehicle');
}

function vehicleMatchesCell(vehicle: VehicleController, cell: Vec3): boolean {
    const vCell = vehicleLogicCell(vehicle);
    return !!vCell && vCell.x === cell.x && vCell.y === cell.y;
}

/** 玩家与载具占同一逻辑格时绑定（不依赖 Ride 格是否已注册） */
export function tryLinkPlayerVehicle(player: PlayerController): boolean {
    const gm = GameManager.instance;
    const level = gm?.curLevel;
    if (!level) return false;

    const pCell = playerLogicCell(player);
    if (!pCell) return false;

    const existing = player.getRideVehicle();
    if (existing) {
        const vCell = vehicleLogicCell(existing);
        if (!vCell || vCell.x !== pCell.x || vCell.y !== pCell.y) {
            existing.setPlayer(null);
            player.setRideVehicle(null);
            return false;
        }
        linkRidePair(player, existing, pCell);
        return true;
    }

    let linked = false;
    forEachLevelEntityNode(level, (ch) => {
        if (linked || !ch.name.includes('Vehicle')) return;
        const vc = ch.getComponent(VehicleController);
        if (!vc || !vehicleMatchesCell(vc, pCell)) return;
        linkRidePair(player, vc, pCell);
        linked = true;
    });
    if (linked) return true;

    const rideVc = findVehicleAtCell(pCell);
    if (rideVc) {
        linkRidePair(player, rideVc, pCell);
        return true;
    }
    return false;
}

/** 载具侧：同格玩家自动设为骑手 */
export function tryLinkVehicleRider(vehicle: VehicleController): boolean {
    const gm = GameManager.instance;
    const level = gm?.curLevel;
    if (!level) return false;
    const vCell = vehicleLogicCell(vehicle);
    if (!vCell) return false;

    const rider = vehicle.getPlayer();
    if (rider) {
        const pCell = playerLogicCell(rider);
        if (pCell && pCell.x === vCell.x && pCell.y === vCell.y) {
            linkRidePair(rider, vehicle, vCell);
            return true;
        }
    }

    let matched = false;
    forEachLevelEntityNode(level, (ch) => {
        if (matched || !ch.name.includes('Player')) return;
        const pc = ch.getComponent(PlayerController);
        if (!pc) return;
        const pCell = playerLogicCell(pc);
        if (!pCell || pCell.x !== vCell.x || pCell.y !== vCell.y) return;
        linkRidePair(pc, vehicle, vCell);
        matched = true;
    });
    return matched;
}

/** 移动中强制位置联动（Unity OnMoving 语义） */
export function syncRidePositions(driver: 'player' | 'vehicle', player: PlayerController, vehicle: VehicleController) {
    if (driver === 'player') {
        const p = player.node.position;
        vehicle.node.setPosition(p.x, p.y, p.z);
    } else {
        player.setRideBaseFromVehicle(vehicle.node.position);
    }
}

export function resolveRideBind(player: PlayerController, cell: Vec3 | null): VehicleController | null {
    if (!cell) return null;
    return findVehicleAtCell(cell);
}
