"""Замок на зону: пока задача в работе, её файлы не берёт вторая задача.

Гейт G3 ловит пересечение зон в плане, но плана мало: взять в работу задачу, чья зона
уже занята, он не мешает. Прошлый прогон так и развалился — двое правили одну зону
одновременно, и сводить пришлось руками.

Замка на диске нет: занятость — это статус `in-progress` соседней задачи. Поэтому
закрытие, провал и сброс отпускают зону сами, без отдельной уборки.
"""

from __future__ import annotations

from .gates import _zones_overlap

BUSY = ("in-progress",)


def _norm(path: str) -> str:
    return path.strip().strip("/")


def _paths(zone: str) -> list[str]:
    """Зона — один путь или несколько через запятую.

    Пустые куски и пробелы вокруг запятых путями не считаются: `"a/, ,b/"`
    даёт `["a", "b"]`, а не запирает всех подряд из-за мусора между запятыми.
    """
    return [p for p in (_norm(part) for part in (zone or "").split(",")) if p]


def _common_path(p1: str, p2: str) -> str:
    """Общий путь двух пересекающихся путей — тот, что лежит выше по дереву."""
    return p1 if len(p1.split("/")) <= len(p2.split("/")) else p2


def holder(state: dict, tid: str) -> tuple[dict, str] | None:
    """Задача в работе, занявшая зону задачи `tid`, и общий путь. None — зона свободна.

    Пустая зона не запирает и не запирается: «нигде» — это не «везде».
    Зона из нескольких путей через запятую сравнивается путь-к-пути: пересекает
    ли задачу любая пара путей из двух зон, а не совпадают ли зоны целиком строкой.
    """
    tasks = state.get("tasks", [])
    me = next((t for t in tasks if t.get("id") == tid), None)
    if me is None:
        return None
    mine = _paths(me.get("zone") or "")
    if not mine:
        return None
    for other in tasks:
        if other.get("id") == tid or other.get("status") not in BUSY:
            continue
        theirs = _paths(other.get("zone") or "")
        if not theirs:
            continue
        for p1 in mine:
            for p2 in theirs:
                if _zones_overlap(p1, p2):
                    return other, _common_path(p1, p2)
    return None


def refusal(tid: str, other: dict, path: str) -> list[str]:
    return [
        f"зона задачи {tid} занята: её держит задача {other['id']} "
        f"(зона {other.get('zone')}), общий путь {path}",
        f"  Дождитесь её закрытия или снимите: chekan task reset {other['id']}",
    ]
