# generated by datamodel-codegen:
#   filename:  core/catchment.json
#   timestamp: 2026-02-28T17:39:50+00:00

from __future__ import annotations

from enum import Enum
from typing import Annotated, Any

from adcp.types.base import AdCPBaseModel
from pydantic import ConfigDict, Field, RootModel

from ..enums import distance_unit
from ..enums import transport_mode as transport_mode_1
from . import ext as ext_1


class Type(Enum):
    Polygon = 'Polygon'
    MultiPolygon = 'MultiPolygon'


class Geometry(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    coordinates: Annotated[
        list[Any],
        Field(
            description='GeoJSON coordinates array. For Polygon: array of linear rings. For MultiPolygon: array of polygons.'
        ),
    ]
    type: Annotated[Type, Field(description='GeoJSON geometry type.')]


class Unit(Enum):
    min = 'min'
    hr = 'hr'


class TravelTime(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    unit: Annotated[Unit, Field(description='Time unit.')]
    value: Annotated[float, Field(description='Travel time limit.', ge=1.0)]


class Geometry1(Geometry):
    pass


class TravelTime1(TravelTime):
    pass


class Geometry2(Geometry):
    pass


class TravelTime2(TravelTime):
    pass


class Radius(AdCPBaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    unit: Annotated[distance_unit.DistanceUnit, Field(description='Distance unit.')]
    value: Annotated[float, Field(description='Radius distance.', gt=0.0)]


class Catchment1(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    catchment_id: Annotated[
        str,
        Field(
            description="Identifier for this catchment, used to reference specific catchment areas in targeting (e.g., 'walk', 'drive', 'primary')."
        ),
    ]
    ext: ext_1.ExtensionObject | None = None
    geometry: Annotated[
        Geometry | None,
        Field(
            description='Pre-computed GeoJSON geometry defining the catchment boundary. Use this when the buyer has already calculated isochrones (via TravelTime, Mapbox, etc.) or has custom trade area boundaries. Supports Polygon and MultiPolygon types.'
        ),
    ] = None
    label: Annotated[
        str | None,
        Field(
            description="Human-readable label for this catchment (e.g., '15-min drive', '1km walking radius')."
        ),
    ] = None
    radius: Annotated[
        Radius | None,
        Field(
            description="Simple radius from the store location. The platform draws a circle of this distance around the store's coordinates."
        ),
    ] = None
    transport_mode: Annotated[
        transport_mode_1.TransportMode,
        Field(
            description='Transportation mode for isochrone calculation. Required when travel_time is provided.'
        ),
    ]
    travel_time: Annotated[
        TravelTime,
        Field(
            description='Travel time limit for isochrone calculation. The platform resolves this to a geographic boundary based on actual transportation networks, accounting for road connectivity, transit schedules, and terrain.'
        ),
    ]


class Catchment2(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    catchment_id: Annotated[
        str,
        Field(
            description="Identifier for this catchment, used to reference specific catchment areas in targeting (e.g., 'walk', 'drive', 'primary')."
        ),
    ]
    ext: ext_1.ExtensionObject | None = None
    geometry: Annotated[
        Geometry1 | None,
        Field(
            description='Pre-computed GeoJSON geometry defining the catchment boundary. Use this when the buyer has already calculated isochrones (via TravelTime, Mapbox, etc.) or has custom trade area boundaries. Supports Polygon and MultiPolygon types.'
        ),
    ] = None
    label: Annotated[
        str | None,
        Field(
            description="Human-readable label for this catchment (e.g., '15-min drive', '1km walking radius')."
        ),
    ] = None
    radius: Annotated[
        Radius,
        Field(
            description="Simple radius from the store location. The platform draws a circle of this distance around the store's coordinates."
        ),
    ]
    transport_mode: Annotated[
        transport_mode_1.TransportMode | None,
        Field(
            description='Transportation mode for isochrone calculation. Required when travel_time is provided.'
        ),
    ] = None
    travel_time: Annotated[
        TravelTime1 | None,
        Field(
            description='Travel time limit for isochrone calculation. The platform resolves this to a geographic boundary based on actual transportation networks, accounting for road connectivity, transit schedules, and terrain.'
        ),
    ] = None


class Catchment3(AdCPBaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    catchment_id: Annotated[
        str,
        Field(
            description="Identifier for this catchment, used to reference specific catchment areas in targeting (e.g., 'walk', 'drive', 'primary')."
        ),
    ]
    ext: ext_1.ExtensionObject | None = None
    geometry: Annotated[
        Geometry2,
        Field(
            description='Pre-computed GeoJSON geometry defining the catchment boundary. Use this when the buyer has already calculated isochrones (via TravelTime, Mapbox, etc.) or has custom trade area boundaries. Supports Polygon and MultiPolygon types.'
        ),
    ]
    label: Annotated[
        str | None,
        Field(
            description="Human-readable label for this catchment (e.g., '15-min drive', '1km walking radius')."
        ),
    ] = None
    radius: Annotated[
        Radius | None,
        Field(
            description="Simple radius from the store location. The platform draws a circle of this distance around the store's coordinates."
        ),
    ] = None
    transport_mode: Annotated[
        transport_mode_1.TransportMode | None,
        Field(
            description='Transportation mode for isochrone calculation. Required when travel_time is provided.'
        ),
    ] = None
    travel_time: Annotated[
        TravelTime2 | None,
        Field(
            description='Travel time limit for isochrone calculation. The platform resolves this to a geographic boundary based on actual transportation networks, accounting for road connectivity, transit schedules, and terrain.'
        ),
    ] = None


class Catchment(RootModel[Catchment1 | Catchment2 | Catchment3]):
    root: Annotated[
        Catchment1 | Catchment2 | Catchment3,
        Field(
            description='A catchment area definition for a store or location. Defines the geographic area from which a store draws customers. Three methods are supported: isochrone inputs (travel time + transport mode, platform resolves the shape), simple radius (distance from location), or pre-computed GeoJSON geometry (buyer provides the exact boundary). Provide exactly one method per catchment.',
            examples=[
                {
                    'data': {
                        'catchment_id': 'drive',
                        'label': '15-min drive',
                        'transport_mode': 'driving',
                        'travel_time': {'unit': 'min', 'value': 15},
                    },
                    'description': 'Isochrone: 15-minute drive',
                },
                {
                    'data': {
                        'catchment_id': 'walk',
                        'label': '10-min walk',
                        'transport_mode': 'walking',
                        'travel_time': {'unit': 'min', 'value': 10},
                    },
                    'description': 'Isochrone: 10-minute walk',
                },
                {
                    'data': {
                        'catchment_id': 'local',
                        'label': '5km radius',
                        'radius': {'unit': 'km', 'value': 5},
                    },
                    'description': 'Simple 5km radius',
                },
                {
                    'data': {
                        'catchment_id': 'trade-area',
                        'geometry': {
                            'coordinates': [
                                [
                                    [4.85, 52.35],
                                    [4.95, 52.35],
                                    [4.95, 52.4],
                                    [4.85, 52.4],
                                    [4.85, 52.35],
                                ]
                            ],
                            'type': 'Polygon',
                        },
                        'label': 'Primary trade area',
                    },
                    'description': 'Pre-computed GeoJSON boundary',
                },
            ],
            title='Catchment',
        ),
    ]
