import geopandas

from opendvp.utils import logger


def segmask_to_qupath(
        path_to_mask : str,
        simplify_value : float = 1,
        export_path : str | None = None,
        return_gdf : bool = True,
    ) -> geopandas.GeoDataFrame | None:
    """Convert a segmentation mask (TIFF) to QuPath-compatible detections as a GeoDataFrame or GeoJSON file.

    This function loads a 2D segmentation mask image, converts it to polygons using spatialdata,
    and prepares the result for QuPath detection import. Optionally, it can simplify the geometry,
    export the detections as a GeoJSON file, and/or return the resulting GeoDataFrame.

    Parameters
    ----------
    path_to_mask : str
        Path to the segmentation mask image (must be a .tif file).
    simplify_value : float, default 1
        Tolerance for geometry simplification. Set to None to disable simplification.
    export_path : str, optional
        If provided, writes the detections to this path as a GeoJSON file.
    return_gdf : bool, default False
        If True, returns the resulting GeoDataFrame. If False, returns None.

    Returns
    -------
    geopandas.GeoDataFrame or None
        The resulting GeoDataFrame if `return_gdf` is True, otherwise None.

    Raises
    ------
    ImportError
        If required packages (dask, dask_image, spatialdata) are not installed.
    ValueError
        If input types or file extensions are incorrect.

    Notes
    -----
    - Requires the 'dask', 'dask_image', and 'spatialdata' packages.
    - The exported GeoJSON is compatible with QuPath for detection import and visualization.
    """
    try:
        import dask.array as da
        import dask_image
        import spatialdata
    except ImportError as e:
        raise ImportError("The 'spatialdata' package is required. Use 'pip install opendvp[spatialdata]'.") from e

    # checks
    if not isinstance(path_to_mask, str):
        raise ValueError("path_to_mask must be a string")
    if not path_to_mask.endswith('.tif'):
        raise ValueError("path_to_mask must end with .tif")

    #create empty sdata
    sdata = spatialdata.SpatialData()
    # load image
    mask = dask_image.imread.imread(path_to_mask)
    mask = da.squeeze(mask)
    sdata['mask'] = spatialdata.models.Labels2DModel.parse(mask)
    # convert to polygons
    sdata['mask_polygons'] = spatialdata.to_polygons(sdata['mask'])
    gdf = sdata['mask_polygons']
    gdf['objectType'] = "detection"
    #simplify the geometry
    if simplify_value is not None:
        logger.info(f"Simplifying the geometry with tolerance {simplify_value}")
        gdf['geometry'] = gdf['geometry'].simplify(simplify_value, preserve_topology=True)
    #remove label column
    gdf = gdf.drop(columns='label')
    if export_path:
        gdf.to_file(export_path, driver='GeoJSON')
        logger.success(f"Exported detections to {export_path}")
    if return_gdf:
        return gdf
    return None