/**
 * Unity 2D 绘制排序（对齐主站 GraphicsSettings + 预制体 SortingOrder + TilemapRenderer Individual）
 *
 * - GraphicsSettings: TransparencySortMode=CustomAxis, axis=(0, 1, -0.26)
 * - TilemapRenderer: SortingOrder=2, Mode=Individual, SortOrder=TopRight → 每格 -(cellX+cellY)
 * - nProp=1, Tilemap/Vehicle=2, Prop=3, Player=4
 * - 仅贴图 WallBlock 可遮挡实体；可行走砖永在实体之下
 * - 砖↔砖：格子深度（南 y 小 → 前，同 y 东 x 大 → 前）→ JumpBlock 抬高 Y → Individual order
 */

import { Vec3 } from 'cc';
import { CommonDefine } from '../core/Define';
import { cellToWorldCenter } from '../core/GridCoords';

/** Unity GraphicsSettings.asset m_TransparencySortAxis */
export const UNITY_TRANSPARENCY_AXIS = { x: 0, y: 1, z: -0.26 } as const;

/** Unity SpriteRenderer / TilemapRenderer m_SortingOrder */
export const UNITY_SORTING_ORDER = {
    nProp: 1,
    tilemap: 2,
    vehicle: 2,
    prop: 3,
    player: 4,
} as const;

const ORDER_SCALE = 10_000;
const DEPTH_SCALE = 100;
/** JumpBlock 行走面比 Baseblock 抬高的最小 Y 差（px），超过则优先比 depthY */
const TILE_ELEVATION_Y_THRESHOLD = 12;

export function isWallBlockTileName(tileName: string): boolean {
    return tileName === CommonDefine.BlockWall;
}

export function isWalkableTileName(tileName: string): boolean {
    return tileName === CommonDefine.BlockBase || tileName === CommonDefine.BlockJump;
}

/** Unity TilemapRenderer Individual + TopRight：baseOrder - (cellX+cellY) */
export function unityTileIndividualSortingOrder(cellX: number, cellY: number): number {
    return UNITY_SORTING_ORDER.tilemap - cellX - cellY;
}

export function unityTransparencyDepth(worldX: number, worldY: number, worldZ = 0): number {
    return worldX * UNITY_TRANSPARENCY_AXIS.x
        + worldY * UNITY_TRANSPARENCY_AXIS.y
        + worldZ * UNITY_TRANSPARENCY_AXIS.z;
}

export function unityCompositeSortKey(
    sortingOrder: number,
    depthWorldY: number,
    depthWorldZ = 0,
    bias = 0,
): number {
    const depth = unityTransparencyDepth(0, depthWorldY, depthWorldZ);
    return sortingOrder * ORDER_SCALE + depth * DEPTH_SCALE + bias;
}

export function unityCellCenterY(cellX: number, cellY: number): number {
    return cellToWorldCenter(new Vec3(cellX, cellY, 0)).y;
}

export interface UnitySortableTile {
    cellX: number;
    cellY: number;
    tileName: string;
    centerY: number;
    depthY: number;
}

export interface UnitySortableEntity {
    sortingOrder: number;
    cellX: number;
    cellY: number;
    centerY: number;
    depthY: number;
    isPlayer: boolean;
    isPickable: boolean;
}

/** 返回值 > 0 表示 (ax,ay) 应排在 (bx,by) 之后（更靠前） */
export function compareIsoDrawOrder(ax: number, ay: number, bx: number, by: number): number {
    const ka = ax + ay;
    const kb = bx + by;
    if (ka !== kb) return kb - ka;
    return ax - bx;
}

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

function compareWallActorIso(
    actor: { x: number; y: number },
    wallX: number,
    wallY: number,
): number {
    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;
}

/** 返回值 > 0 实体更靠前；< 0 墙应挡住 */
function compareUnityEntityToWall(
    entity: UnitySortableEntity,
    tile: UnitySortableTile,
): number {
    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);
}

/** 砖块格子深度：南侧（cellY 小）更靠前；同行西侧（cellX 小）更靠前 */
export function compareTileCellDepth(ax: number, ay: number, bx: number, by: number): number {
    if (ay !== by) return by - ay;
    return bx - ax;
}

/**
 * 砖↔砖：格子深度优先（下方砖挡上方砖），JumpBlock 抬高再比 depthY。
 */
export function compareUnityTileToTile(a: UnitySortableTile, b: UnitySortableTile): number {
    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);
}

/**
 * 实体 vs 砖块
 * 非 WallBlock 永在实体之下；仅墙砖可遮挡。
 */
export function compareUnityEntityToTile(
    entity: UnitySortableEntity,
    tile: UnitySortableTile,
): number {
    if (!isWallBlockTileName(tile.tileName)) {
        return 1;
    }
    return compareUnityEntityToWall(entity, tile);
}

export function compareUnityEntityToEntity(a: UnitySortableEntity, b: UnitySortableEntity): number {
    const keyA = unityCompositeSortKey(a.sortingOrder, a.depthY);
    const keyB = unityCompositeSortKey(b.sortingOrder, b.depthY);
    if (keyA !== keyB) return keyA - keyB;
    const iso = (a.cellX + a.cellY) - (b.cellX + b.cellY);
    if (iso !== 0) return iso;
    if (a.isPlayer && !b.isPlayer) return 1;
    if (b.isPlayer && !a.isPlayer) return -1;
    return 0;
}
