
import traceback
import numbers
from typing import List, Tuple

from qgis.core import *
from qgis.core import Qgis
from qgis.core import QgsMessageLog

from geogst.core.utils.inspections.errors import *
from geogst.core.utils.inspections.functions import *


def extract_geometry_type_of_vector_layer(
        layer: QgsMapLayer.LayerType.VectorLayer
) -> Optional[str]:

    if layer.geometryType() == QgsWkbTypes.GeometryType.PointGeometry:
        return "point"
    elif layer.geometryType() == QgsWkbTypes.GeometryType.LineGeometry:
        return "line"
    elif layer.geometryType() == QgsWkbTypes.GeometryType.PolygonGeometry:
        return "polygon"
    else:
        return None


def try_geoms_attrs(
        layer: QgsVectorLayer,
        field_indices: Optional[List[numbers.Integral]] = None
) -> Tuple[bool, Union[str, List[Tuple[QgsGeometry, Tuple]]]]:
    """
    Returns geometry (unchanged) and attributes of (selected) layer records.
    """

    try:

        if not isinstance(layer, QgsVectorLayer):
            return False, f"Invalid layer type: expected QgsVectorLayer, got {type(layer)}"

        if not layer.isValid():
            return False, f"Layer '{layer.name()}' is not valid"

        if field_indices is None:
            field_indices = []

        # Validate field indices are within range
        fields = layer.fields()
        valid_field_indices = []
        for field_ndx in field_indices:
            if 0 <= field_ndx < fields.count():
                valid_field_indices.append(field_ndx)
            else:
                QgsMessageLog.logMessage(
                    f"Invalid field index {field_ndx} for layer '{layer.name()}' (field count: {fields.count()})",
                    "qgSurf",
                    Qgis.MessageLevel.Warning
                )

        records = []

        if layer.selectedFeatureCount() > 0:
            features = layer.selectedFeatures()
        else:
            features = layer.getFeatures()

        for feature in features:

            geom = feature.geometry()

            # Use direct attribute access with index instead of attrs[field_ndx].name()
            rec_data = tuple([feature.attribute(field_ndx) for field_ndx in valid_field_indices])

            records.append((geom, rec_data))

        return True, records

    except Exception as e:

        return False, f"{e!r}"


def extract_selected_geometries(
    layer: QgsVectorLayer,
) -> Union[None, List[QgsGeometry]]:
    """
    Returns geometry (unchanged) of (selected) layer records.
    """

    try:

        if not isinstance(layer, QgsVectorLayer):
            warn_qgis(
                "qgSurf",
                f"Invalid layer type: expected QgsVectorLayer, got {type(layer)}"
            )
            return None

        if not layer.isValid():
            warn_qgis(
                "qgSurf",
                f"Layer '{layer.name()}' is not valid"
            )
            return None

        geometries = []

        if layer.selectedFeatureCount() > 0:
            features = layer.selectedFeatures()
        else:
            features = layer.getFeatures()

        for feature in features:

            geometries.append(feature.geometry())

        return geometries

    except Exception as e:

        err = Error(
            True,
            caller_name(),
            e,
            traceback.format_exc()
        )

        warn_qgis(
            "qgSurf",
            f"Line layer not read: {err!r} "
        )

        return None

