import { isHallNamedSectorType, isHallSeatSectorType } from './hallPolygon';

const INT_RE = /^\d+$/;

/** Натуральная сортировка: целые по значению, остальное — localeCompare. */
export function compareHallSeatLabels(a: string, b: string): number {
    const aInt = INT_RE.test(a);
    const bInt = INT_RE.test(b);
    if (aInt && bInt) {
        return Number(a) - Number(b);
    }
    if (aInt !== bInt) {
        return aInt ? -1 : 1;
    }
    return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
}

/**
 * Склеить последовательные целые в диапазоны: `1,2,5,6` → `1-2, 5-6`.
 * Нецелые / пустые («?») не склеиваются с соседями.
 */
export function formatHallSeatNumberRanges(rawNumbers: Array<string | null | undefined>): string {
    const labels = rawNumbers.map((n) => {
        if (n == null || String(n).trim() === '') {
            return '?';
        }
        return String(n).trim();
    });
    const unique = Array.from(new Set(labels));
    unique.sort(compareHallSeatLabels);

    const parts: string[] = [];
    let i = 0;
    while (i < unique.length) {
        const start = unique[i]!;
        if (!INT_RE.test(start)) {
            parts.push(start);
            i += 1;
            continue;
        }
        let end = start;
        let endNum = Number(start);
        let j = i + 1;
        while (j < unique.length) {
            const next = unique[j]!;
            if (!INT_RE.test(next)) {
                break;
            }
            const nextNum = Number(next);
            if (nextNum !== endNum + 1) {
                break;
            }
            end = next;
            endNum = nextNum;
            j += 1;
        }
        parts.push(start === end ? start : `${start}-${end}`);
        i = j;
    }
    return parts.join(', ');
}

function sectorDisplayName(el: { label?: string; type?: string }): string {
    const label = (el.label ?? '').trim();
    if (label) {
        return label;
    }
    return el.type === 'zone' ? 'Сектор без мест' : 'Сектор';
}

function formatRowBlock(rowKey: string, seats: any[]): string {
    const rowLabel = rowKey === '' ? '(без ряда)' : `Ряд ${rowKey}`;
    const ranges = formatHallSeatNumberRanges(seats.map((s) => s.seatNumber));
    return `  ${rowLabel}: места ${ranges}`;
}

function groupSeatsByRow(seats: any[]): Array<{ rowKey: string; seats: any[] }> {
    const byRow = new Map<string, any[]>();
    seats.forEach((seat) => {
        const rowKey = (seat.seatRow == null || String(seat.seatRow).trim() === '')
            ? ''
            : String(seat.seatRow).trim();
        const arr = byRow.get(rowKey) ?? [];
        arr.push(seat);
        byRow.set(rowKey, arr);
    });
    const keys = Array.from(byRow.keys()).sort((a, b) => {
        if (a === '' && b !== '') {
            return 1;
        }
        if (b === '' && a !== '') {
            return -1;
        }
        return compareHallSeatLabels(a, b);
    });
    return keys.map((rowKey) => ({ rowKey, seats: byRow.get(rowKey)! }));
}

/** Текстовая сводка зала: сектора, ряды, места с диапазонами. */
export function buildHallSummaryText(layout: any[]): string {
    const seats = layout.filter((e) => e.type === 'seat');
    const named = layout.filter((e) => isHallNamedSectorType(e.type));
    const lines: string[] = [];

    lines.push(`Всего мест: ${seats.length}`);
    lines.push('');

    const assignedIds = new Set<string>();

    named.forEach((sector) => {
        const name = sectorDisplayName(sector);
        if (sector.type === 'zone') {
            lines.push(`Сектор «${name}» — без мест`);
            lines.push('');
            return;
        }
        if (!isHallSeatSectorType(sector.type)) {
            return;
        }
        const sectorSeats = seats.filter((s) => String(s.sector ?? '') === String(sector._id));
        sectorSeats.forEach((s) => assignedIds.add(s._id));

        lines.push(`Сектор «${name}»`);
        if (!sectorSeats.length) {
            lines.push('  Мест: 0');
            lines.push('');
            return;
        }
        groupSeatsByRow(sectorSeats).forEach(({ rowKey, seats: rowSeats }) => {
            lines.push(formatRowBlock(rowKey, rowSeats));
        });
        lines.push(`  Мест: ${sectorSeats.length}`);
        lines.push('');
    });

    const orphans = seats.filter((s) => !assignedIds.has(s._id));
    if (orphans.length) {
        lines.push(`Места вне сектора: ${orphans.length}`);
        groupSeatsByRow(orphans).forEach(({ rowKey, seats: rowSeats }) => {
            lines.push(formatRowBlock(rowKey, rowSeats));
        });
        lines.push('');
    }

    while (lines.length && lines[lines.length - 1] === '') {
        lines.pop();
    }
    return lines.join('\n');
}
