#  Copyright © 2025 Bentley Systems, Incorporated
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#      http://www.apache.org/licenses/LICENSE-2.0
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

# generated by datamodel-codegen:
#   filename:  spec.yaml

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import Annotated
from uuid import UUID

from pydantic import Field, RootModel, StrictBool, StrictFloat, StrictInt, StrictStr

from .._model_config import CustomBaseModel


class CoordinateItem(RootModel[list[StrictFloat]]):
    root: Annotated[list[StrictFloat], Field(max_length=2, min_length=2, title="GeoJSON Point")]
    """
    A WGS84 coordinate pair [longitude, latitude]. The longitude must come before the latitude, in order to be considered a valid GeoJSON Point
    """


class Coordinate(RootModel[list[CoordinateItem]]):
    root: Annotated[
        list[CoordinateItem],
        Field(max_length=5, min_length=5, title="GeoJSON LinearRing"),
    ]
    """
    A list of GeoJSON points defining a closed linear ring. In order for the ring to be closed, the last point must be the same as the first point. Only a rectangle is supported, so the ring must be defined by 5 points.
    """


class DataDownloadUrl(CustomBaseModel):
    download_url: Annotated[StrictStr | None, Field(title="Download Url")] = None
    id: Annotated[UUID, Field(title="Id")]
    name: Annotated[StrictStr, Field(title="Name")]


class DataUploadRequestBody(CustomBaseModel):
    name: Annotated[StrictStr, Field(title="Name")]
    """
    SHA256 or UUID "name" for the data blob. SHA256 is preferred as it allows other clients to deduplicate data.
    """


class DataUploadResponseBody(CustomBaseModel):
    exists: Annotated[StrictBool, Field(title="Exists")]
    id: Annotated[UUID, Field(title="Id")]
    """
    Server-generated unique identifier for the data
    """
    name: Annotated[StrictStr, Field(title="Name")]
    """
    client-provided name for the data (SHA256 or UUID)
    """
    upload_url: Annotated[StrictStr | None, Field(title="Upload Url")] = None


class GeoJSONType(Enum):
    Polygon = "Polygon"


class GeoscienceObject(CustomBaseModel):
    """
    The geoscience object with the additional required schema properties.

    This object is largely defined by the schemas in the geoscience-object-schemas repository.
    There are some default, required values listed here explicitly.
    """

    name: Annotated[StrictStr, Field(title="Name")]
    """
    The name of the geoscience object.
    """
    schema_: Annotated[StrictStr, Field(alias="schema", title="Schema")]
    """
    The geoscience object schema.
    """
    uuid: Annotated[UUID | None, Field(title="Uuid")] = None
    """
    Unique object UUID.
    """


class LatestObjectVersionIdResponse(CustomBaseModel):
    object_id: Annotated[StrictStr, Field(title="Object Id")]
    version_id: Annotated[StrictStr | None, Field(title="Version Id")] = None


class ListObjectsResponseLinks(CustomBaseModel):
    next: Annotated[StrictStr | None, Field(title="Next")] = None
    prev: Annotated[StrictStr | None, Field(title="Prev")] = None


class ListedObjectLinks(CustomBaseModel):
    download: Annotated[StrictStr, Field(title="Download")]


class MetadataUpdateBody(CustomBaseModel):
    stage_id: Annotated[UUID | None, Field(title="Stage Id")] = None


class ObjectResponseLinks(CustomBaseModel):
    data: Annotated[list[DataDownloadUrl], Field(title="Data")]
    download: Annotated[StrictStr, Field(title="Download")]


class ObjectVersionResponseLinks(CustomBaseModel):
    download: Annotated[StrictStr, Field(title="Download")]


class RoleEnum(Enum):
    owner = "owner"
    editor = "editor"
    viewer = "viewer"


class StageListItem(CustomBaseModel):
    name: Annotated[StrictStr, Field(title="Name")]
    stage_id: Annotated[UUID, Field(title="Stage Id")]


class StageResponse(CustomBaseModel):
    name: Annotated[StrictStr, Field(title="Name")]
    stage_id: Annotated[UUID, Field(title="Stage Id")]


class UpdateGeoscienceObject(CustomBaseModel):
    """
    The geoscience object with the additional required schema properties.

    The uuid field must be set when updating a geoscience object.
    This object is largely defined by the schemas in the geoscience-object-schemas repository.
    There are some default, required values listed here explicitly.
    """

    name: Annotated[StrictStr, Field(title="Name")]
    """
    The name of the geoscience object.
    """
    schema_: Annotated[StrictStr, Field(alias="schema", title="Schema")]
    """
    The geoscience object schema.
    """
    uuid: Annotated[UUID, Field(title="Uuid")]
    """
    Unique object UUID.
    """


class User(CustomBaseModel):
    """
    User details.
    """

    email: Annotated[StrictStr | None, Field(title="Email")] = None
    id: Annotated[UUID, Field(title="Id")]
    name: Annotated[StrictStr | None, Field(title="Name")] = None


class BoundingBox(CustomBaseModel):
    """
    The bounding box for a geoscience object, represented by a GeoJSON polygon.
    """

    coordinates: Annotated[
        list[Coordinate],
        Field(max_length=1, min_length=1, title="GeoJSON Polygon Coordinates"),
    ]
    """
    A list containing one exterior ring of a GeoJSON polygon
    """
    type: GeoJSONType = "Polygon"


class GeoscienceObjectVersion(CustomBaseModel):
    """
    Geoscience object version.
    """

    created_at: Annotated[datetime, Field(title="Created At")]
    created_by: User | None = None
    etag: Annotated[StrictStr, Field(title="Etag")]
    links: ObjectVersionResponseLinks
    stage: StageResponse | None = None
    version_id: Annotated[StrictStr, Field(title="Version Id")]


class GetObjectResponse(CustomBaseModel):
    created_at: Annotated[datetime, Field(title="Created At")]
    created_by: User | None = None
    deleted_at: Annotated[datetime | None, Field(title="Deleted At")] = None
    deleted_by: User | None = None
    etag: Annotated[StrictStr, Field(title="Etag")]
    geojson_bounding_box: BoundingBox | None = None
    links: ObjectResponseLinks
    modified_at: Annotated[datetime, Field(title="Modified At")]
    modified_by: User | None = None
    object: GeoscienceObject
    object_id: Annotated[UUID, Field(title="Object Id")]
    object_path: Annotated[StrictStr | None, Field(title="Object Path")] = None
    stage: StageResponse | None = None
    version_id: Annotated[StrictStr, Field(title="Version Id")]
    versions: Annotated[list[GeoscienceObjectVersion] | None, Field(title="Versions")] = None


class ListStagesResponse(CustomBaseModel):
    stages: Annotated[list[StageListItem], Field(title="Stages")]


class ListedObject(CustomBaseModel):
    created_at: Annotated[datetime, Field(title="Created At")]
    created_by: User | None = None
    deleted_at: Annotated[datetime | None, Field(title="Deleted At")] = None
    deleted_by: User | None = None
    etag: Annotated[StrictStr, Field(title="Etag")]
    geojson_bounding_box: BoundingBox | None = None
    links: ListedObjectLinks
    modified_at: Annotated[datetime, Field(title="Modified At")]
    modified_by: User | None = None
    name: Annotated[StrictStr, Field(title="Name")]
    object_id: Annotated[UUID, Field(title="Object Id")]
    path: Annotated[StrictStr, Field(title="Path")]
    schema_: Annotated[StrictStr, Field(alias="schema", title="Schema")]
    """
    The geoscience object schema.
    """
    stage: StageResponse | None = None
    version_id: Annotated[StrictStr, Field(title="Version Id")]


class OrgListedObject(CustomBaseModel):
    created_at: Annotated[datetime, Field(title="Created At")]
    created_by: User | None = None
    deleted_at: Annotated[datetime | None, Field(title="Deleted At")] = None
    deleted_by: User | None = None
    geojson_bounding_box: BoundingBox | None = None
    modified_at: Annotated[datetime, Field(title="Modified At")]
    modified_by: User | None = None
    name: Annotated[StrictStr, Field(title="Name")]
    object_id: Annotated[UUID, Field(title="Object Id")]
    schema_: Annotated[StrictStr, Field(alias="schema", title="Schema")]
    stage: StageResponse | None = None
    workspace_access: RoleEnum | None = None
    workspace_id: Annotated[UUID, Field(title="Workspace Id")]
    workspace_name: Annotated[StrictStr | None, Field(title="Workspace Name")] = None


class PostObjectResponse(CustomBaseModel):
    created_at: Annotated[datetime, Field(title="Created At")]
    created_by: User | None = None
    deleted_at: Annotated[datetime | None, Field(title="Deleted At")] = None
    deleted_by: User | None = None
    etag: Annotated[StrictStr, Field(title="Etag")]
    geojson_bounding_box: BoundingBox | None = None
    links: ObjectResponseLinks
    modified_at: Annotated[datetime, Field(title="Modified At")]
    modified_by: User | None = None
    object: GeoscienceObject
    object_id: Annotated[UUID | None, Field(title="Object Id")] = None
    object_path: Annotated[StrictStr | None, Field(title="Object Path")] = None
    stage: StageResponse | None = None
    version_id: Annotated[StrictStr, Field(title="Version Id")]


class ListObjectsResponse(CustomBaseModel):
    count: Annotated[StrictInt, Field(title="Count")] = 0
    limit: Annotated[StrictInt, Field(title="Limit")] = 0
    links: ListObjectsResponseLinks
    objects: Annotated[list[ListedObject], Field(title="Objects")]
    offset: Annotated[StrictInt, Field(title="Offset")] = 0
    total: Annotated[StrictInt, Field(title="Total")] = 0


class ListOrgObjectsResponse(CustomBaseModel):
    count: Annotated[StrictInt, Field(title="Count")] = 0
    limit: Annotated[StrictInt, Field(title="Limit")] = 0
    links: ListObjectsResponseLinks
    objects: Annotated[list[OrgListedObject], Field(title="Objects")]
    offset: Annotated[StrictInt, Field(title="Offset")] = 0
    total: Annotated[StrictInt, Field(title="Total")] = 0
