from __future__ import annotations

import glob
import os
from typing import Iterable

from .config import Config


def _tile_suffix(tile_id: str) -> str:
    parts = tile_id.split("_")
    return "_".join(parts[-3:]) if len(parts) >= 3 else tile_id


def _parse_tile_xy(tile_id: str) -> tuple[int, int] | None:
    parts = tile_id.split("_")
    coords = [p for p in parts if p.isdigit() and len(p) >= 3]
    if len(coords) >= 2:
        return int(coords[-2]), int(coords[-1])
    return None


def _unique(paths: Iterable[str]) -> list[str]:
    seen: set[str] = set()
    ordered: list[str] = []
    for path in paths:
        if path in seen:
            continue
        seen.add(path)
        ordered.append(path)
    return ordered


def candidate_citygml_lod2_paths(tile_id: str, cfg: Config) -> list[str]:
    candidates: list[str] = []
    suffix = _tile_suffix(tile_id)
    candidates.append(os.path.join(cfg.raw.citygml_lod2_dir, f"LoD2_{suffix}.gml"))

    xy = _parse_tile_xy(tile_id)
    if xy:
        x, y = xy
        candidates.append(os.path.join(cfg.raw.citygml_lod2_dir, f"LoD2_32_{x}_{y}_2_RP.gml"))
        x2 = x - (x % 2)
        y2 = y - (y % 2)
        candidates.append(os.path.join(cfg.raw.citygml_lod2_dir, f"LoD2_32_{x2}_{y2}_2_RP.gml"))

    return _unique(candidates)


def find_citygml_lod2(tile_id: str, cfg: Config) -> str | None:
    candidates = candidate_citygml_lod2_paths(tile_id, cfg)
    for path in candidates:
        if os.path.exists(path):
            return path

    suffix = _tile_suffix(tile_id)
    patterns: list[str] = [
        os.path.join(cfg.raw.citygml_lod2_dir, f"*{tile_id}*.gml"),
        os.path.join(cfg.raw.citygml_lod2_dir, f"*{suffix}*.gml"),
    ]
    xy = _parse_tile_xy(tile_id)
    if xy:
        x, y = xy
        patterns.insert(0, os.path.join(cfg.raw.citygml_lod2_dir, f"LoD2_32_{x}_{y}_*.gml"))

    for pattern in patterns:
        matches = sorted(glob.glob(pattern))
        if matches:
            return matches[0]

    return None
