# -*- coding: utf-8 -*-
# gui/components/model_view/contour/contour_geometry_component_part2.py

# -*- coding: utf-8 -*-
# gui/components/model_view/_mv_grid_sel_geom.py
# Геометрия / помощники полигонов, поиск ячеек

from __future__ import annotations

from typing import Optional, Tuple, TYPE_CHECKING

if TYPE_CHECKING:  # pragma: no cover
    from gui.components.model_view_widget import ModelViewWidget

class ContourGeometryComponentPart2:
    def _find_cell_by_point(
        self: "ModelViewWidget",
        x: float, y: float,
        eps: float = 1e-4,
        prefer_selected: bool = False,
    ) -> Optional[Tuple[int, Tuple[float, float, float, float]]]:
        def project_dist2(bounds: tuple[float, float, float, float]) -> float:
            mn_x, mx_x, mn_y, mx_y = bounds
            px = min(max(x, mn_x), mx_x)
            py = min(max(y, mn_y), mx_y)
            return (x - px) ** 2 + (y - py) ** 2

        candidates: list[tuple[float, int, tuple[float, float, float, float]]] = []
        selected_candidates: list[tuple[float, int, tuple[float, float, float, float]]] = []
        all_cells: list[tuple[float, int, tuple[float, float, float, float]]] = []
        selected_all_cells: list[tuple[float, int, tuple[float, float, float, float]]] = []

        for cell_id, bounds in self._grid_cells.items():
            mn_x, mx_x, mn_y, mx_y = bounds
            dist2 = project_dist2(bounds)
            row = (dist2, cell_id, bounds)
            all_cells.append(row)
            if cell_id in self._selected_cells:
                selected_all_cells.append(row)
            if (mn_x - eps) <= x <= (mx_x + eps) and (mn_y - eps) <= y <= (mx_y + eps):
                candidates.append(row)
                if cell_id in self._selected_cells:
                    selected_candidates.append(row)

        if prefer_selected and selected_candidates:
            selected_candidates.sort(key=lambda item: item[0])
            _, best_id, best_bounds = selected_candidates[0]
            return best_id, best_bounds

        if prefer_selected and selected_all_cells:
            selected_all_cells.sort(key=lambda item: item[0])
            best_dist2, best_id, best_bounds = selected_all_cells[0]
            step = max(1.0, float(getattr(self, "_current_zone_size", 1.0)))
            max_dist2 = (step * 0.75) ** 2
            if best_dist2 <= max_dist2:
                return best_id, best_bounds
            return None

        if candidates:
            candidates.sort(key=lambda item: item[0])
            _, best_id, best_bounds = candidates[0]
            return best_id, best_bounds

        if all_cells:
            all_cells.sort(key=lambda item: item[0])
            best_dist2, best_id, best_bounds = all_cells[0]
            step = max(1.0, float(getattr(self, "_current_zone_size", 1.0)))
            max_dist2 = step * step
            if best_dist2 <= max_dist2:
                return best_id, best_bounds
            return None

        return None
