#!/usr/bin/env node
/**
 * 自测 Unity 绘制排序（与 UnityDrawSort.ts 对齐）
 * 运行: node tools/verify-unity-draw-sort.mjs
 */

const UNITY_SORTING_ORDER = { nProp: 1, tilemap: 2, vehicle: 2, prop: 3, player: 4 };
const ORDER_SCALE = 10_000;
const DEPTH_SCALE = 100;
const TILE_ELEVATION_Y_THRESHOLD = 12;
const HALF_W = 50;
const HALF_H = 25;

function cellToWorldCenter(x, y) {
    const wx = (x - y) * HALF_W;
    const wy = (x + y) * HALF_H + HALF_H;
    return { x: wx, y: wy };
}

function unityTileIndividualSortingOrder(cellX, cellY) {
    return UNITY_SORTING_ORDER.tilemap - cellX - cellY;
}

function compareTileCellDepth(ax, ay, bx, by) {
    if (ay !== by) return by - ay;
    return bx - ax;
}

function compareUnityTileToTile(a, b) {
    const cellCmp = compareTileCellDepth(a.cellX, a.cellY, b.cellX, b.cellY);
    if (cellCmp !== 0) return cellCmp;
    const yCmp = Math.round(a.depthY * DEPTH_SCALE) - Math.round(b.depthY * DEPTH_SCALE);
    if (Math.abs(yCmp) >= TILE_ELEVATION_Y_THRESHOLD) return yCmp;
    return unityTileIndividualSortingOrder(a.cellX, a.cellY)
        - unityTileIndividualSortingOrder(b.cellX, b.cellY);
}

function tileInFrontOfTile(front, back, depthFront = 0, depthBack = 0) {
    const a = { cellX: front.x, cellY: front.y, depthY: depthFront };
    const b = { cellX: back.x, cellY: back.y, depthY: depthBack };
    return compareUnityTileToTile(a, b) > 0;
}

function compareIsoDrawOrder(ax, ay, bx, by) {
    const ka = ax + ay;
    const kb = bx + by;
    if (ka !== kb) return kb - ka;
    return ax - bx;
}

function wallFaceSamples(wallX, wallY) {
    return [{ x: wallX, y: wallY - 1 }, { x: wallX - 1, y: wallY }];
}

function compareWallActorIso(actor, wallX, wallY) {
    let actorAhead = 0;
    for (const face of wallFaceSamples(wallX, wallY)) {
        const iso = compareIsoDrawOrder(actor.x, actor.y, face.x, face.y);
        if (iso < 0) return iso;
        if (iso > actorAhead) actorAhead = iso;
    }
    return actorAhead;
}

function compareUnityEntityToWall(entity, tile) {
    const cell = { x: entity.cellX, y: entity.cellY };
    for (const face of wallFaceSamples(tile.cellX, tile.cellY)) {
        if (face.x === cell.x && face.y === cell.y) return 1;
    }
    const tileOrder = unityTileIndividualSortingOrder(tile.cellX, tile.cellY);
    if (tileOrder > entity.sortingOrder) return -1;
    const wallIso = compareWallActorIso(cell, tile.cellX, tile.cellY);
    if (wallIso < 0) {
        if (tile.cellX === cell.x && tile.cellY === cell.y - 1) return -1;
        if (tile.cellY < cell.y) return 1;
        return -1;
    }
    const tileAhead = (tile.cellX + tile.cellY) - (cell.x + cell.y);
    if (wallIso > 0 && tileAhead > 0) return -1;
    if (wallIso > 0) return wallIso;
    const yCmp = Math.round(entity.depthY * DEPTH_SCALE) - Math.round(tile.depthY * DEPTH_SCALE);
    if (yCmp !== 0) return yCmp;
    if (tileAhead !== 0) return -tileAhead;
    return compareIsoDrawOrder(tile.cellX, tile.cellY, cell.x, cell.y);
}

function compareUnityEntityToTile(entity, tile) {
    if (tile.tileName !== 'WallBlock') return 1;
    return compareUnityEntityToWall(entity, tile);
}

function entityInFrontOfTile(entity, tile) {
    return compareUnityEntityToTile(entity, tile) > 0;
}

function walkableUnderPlayer(playerCell, tileCell) {
    return entityInFrontOfTile(
        { sortingOrder: 4, cellX: playerCell.x, cellY: playerCell.y, centerY: 0, depthY: 0 },
        { cellX: tileCell.x, cellY: tileCell.y, tileName: 'Baseblock', centerY: 0, depthY: 0 },
    );
}

function playerBottomY(cellX, cellY) {
    return cellToWorldCenter(cellX, cellY).y - 0.35 * 90;
}

function wallFrontY(cellX, cellY) {
    const c = cellToWorldCenter(cellX, cellY);
    return Math.max(c.y, c.y + (1 - 0.67) * 115);
}

const cases = [
    {
        name: '砖↔砖：斜向路径 (0,-2)→(0,-1)→(0,0)→(1,0) 下方逐格遮挡',
        pass: tileInFrontOfTile({ x: 0, y: -2 }, { x: 0, y: -1 })
            && tileInFrontOfTile({ x: 0, y: -1 }, { x: 0, y: 0 })
            && tileInFrontOfTile({ x: 0, y: 0 }, { x: 1, y: 0 }),
    },
    {
        name: '砖↔砖：对角路径 (0,-3)→(1,-2)→(2,-1)→(3,0) 下方逐格遮挡',
        pass: tileInFrontOfTile({ x: 0, y: -3 }, { x: 1, y: -2 })
            && tileInFrontOfTile({ x: 1, y: -2 }, { x: 2, y: -1 })
            && tileInFrontOfTile({ x: 2, y: -1 }, { x: 3, y: 0 }),
    },
    {
        name: '砖↔砖：南侧 (0,-1) 挡住北侧 (0,0)',
        pass: tileInFrontOfTile({ x: 0, y: -1 }, { x: 0, y: 0 }),
    },
    {
        name: '砖↔砖：东南 (2,-2) 挡住西北 (0,-1)',
        pass: tileInFrontOfTile({ x: 2, y: -2 }, { x: 0, y: -1 }),
    },
    {
        name: '91614 出生 (0,-1) 不被北侧墙 (0,0) 挡住',
        pass: entityInFrontOfTile(
            { sortingOrder: 4, cellX: 0, cellY: -1, centerY: 0, depthY: 0 },
            { cellX: 0, cellY: 0, tileName: 'WallBlock', centerY: 0, depthY: 0 },
        ),
    },
    {
        name: '跨格路径砖：南侧 (0,-2) 不挡北侧角色 (0,-1)',
        pass: entityInFrontOfTile(
            { sortingOrder: 4, cellX: 0, cellY: -1, centerY: 0, depthY: 0 },
            { cellX: 0, cellY: -2, tileName: 'Baseblock', centerY: 0, depthY: 100 },
        ),
    },
    {
        name: '91614 真实Y：出生 (0,-1) 在 (0,0) 墙前',
        pass: entityInFrontOfTile(
            { sortingOrder: 4, cellX: 0, cellY: -1, centerY: 0, depthY: playerBottomY(0, -1) },
            { cellX: 0, cellY: 0, tileName: 'WallBlock', centerY: 0, depthY: wallFrontY(0, 0) },
        ),
    },
];

let failed = 0;
for (const c of cases) {
    const ok = !!c.pass;
    console.log(`${ok ? '✓' : '✗'} ${c.name}`);
    if (!ok) failed++;
}

if (failed > 0) {
    console.error(`\n${failed} case(s) failed`);
    process.exit(1);
}
console.log(`\nAll ${cases.length} cases passed.`);
