
/**
 * Направление обхода.
 * И для номеров рядов, и для нумерации мест оно выбирает линию присвоения:
 * сверху/снизу — горизонтальные ряды, слева/справа — вертикальные колонки.
 */
export type HallSeatFillDirection =
    | 'top_bottom'
    | 'bottom_top'
    | 'left_right'
    | 'right_left';

export const HALL_SEAT_FILL_DIRECTIONS: readonly HallSeatFillDirection[] = [
    'top_bottom',
    'bottom_top',
    'left_right',
    'right_left',
] as const;

/** Направление по умолчанию в форме «Номера рядов». */
export const HALL_SEAT_FILL_DIRECTION_DEFAULT_ROWS: HallSeatFillDirection = 'top_bottom';
/** Направление по умолчанию в форме «Нумерация мест». */
export const HALL_SEAT_FILL_DIRECTION_DEFAULT_SEAT_NUMBERS: HallSeatFillDirection = 'left_right';

/** Ключи в `local.ts` для подписей в селекте */
export const HALL_SEAT_FILL_DIRECTION_LANG_KEY: Record<HallSeatFillDirection, string> = {
    top_bottom: 'hall_seat_dir_top_bottom',
    bottom_top: 'hall_seat_dir_bottom_top',
    left_right: 'hall_seat_dir_left_right',
    right_left: 'hall_seat_dir_right_left',
};

function meanCoord(line: any[], axis: 'x' | 'y'): number {
    return line.reduce((s, p) => s + (axis === 'y' ? p.y : p.x), 0) / line.length;
}

/** Склейка мест в линии по одной оси (ряд по Y или колонка по X). */
export function clusterHallSeatsByAxis(
    seats: any[],
    axis: 'x' | 'y',
    tolerance: number,
): any[][] {
    if (!seats.length) {
        return [];
    }
    const sorted = [...seats].sort((a, b) => (axis === 'y' ? a.y - b.y : a.x - b.x));
    const lines: any[][] = [];
    for (const seat of sorted) {
        const lastLine = lines[lines.length - 1];
        if (!lastLine) {
            lines.push([seat]);
            continue;
        }
        const mean = meanCoord(lastLine, axis);
        const v = axis === 'y' ? seat.y : seat.x;
        if (Math.abs(v - mean) <= tolerance) {
            lastLine.push(seat);
        } else {
            lines.push([seat]);
        }
    }
    return lines;
}

function hallSeatsRowLinesTopBottom(seats: any[], tolerance: number): any[][] {
    const lines = clusterHallSeatsByAxis(seats, 'y', tolerance);
    const sortedLines = [...lines].sort((a, b) => meanCoord(a, 'y') - meanCoord(b, 'y'));
    return sortedLines.map((line) => [...line].sort((a, b) => a.x - b.x));
}

function hallSeatsRowLinesBottomTop(seats: any[], tolerance: number): any[][] {
    const lines = clusterHallSeatsByAxis(seats, 'y', tolerance);
    const sortedLines = [...lines].sort((a, b) => meanCoord(b, 'y') - meanCoord(a, 'y'));
    return sortedLines.map((line) => [...line].sort((a, b) => a.x - b.x));
}

function hallSeatsColumnLinesLeftRight(seats: any[], tolerance: number): any[][] {
    const lines = clusterHallSeatsByAxis(seats, 'x', tolerance);
    const sortedLines = [...lines].sort((a, b) => meanCoord(a, 'x') - meanCoord(b, 'x'));
    return sortedLines.map((line) => [...line].sort((a, b) => a.y - b.y));
}

function hallSeatsColumnLinesRightLeft(seats: any[], tolerance: number): any[][] {
    const lines = clusterHallSeatsByAxis(seats, 'x', tolerance);
    const sortedLines = [...lines].sort((a, b) => meanCoord(b, 'x') - meanCoord(a, 'x'));
    return sortedLines.map((line) => [...line].sort((a, b) => a.y - b.y));
}

/**
 * Линии в порядке обхода; все элементы одной линии получают общий индекс/лейбл.
 */
export function hallSeatsGroupedLinesOrdered(
    seats: any[],
    direction: HallSeatFillDirection,
    tolerance: number,
): any[][] {
    switch (direction) {
        case 'top_bottom':
            return hallSeatsRowLinesTopBottom(seats, tolerance);
        case 'bottom_top':
            return hallSeatsRowLinesBottomTop(seats, tolerance);
        case 'left_right':
            return hallSeatsColumnLinesLeftRight(seats, tolerance);
        case 'right_left':
            return hallSeatsColumnLinesRightLeft(seats, tolerance);
    }
}
