from typing import Dict, Union

from typing_extensions import Literal

from graph.ingestion.dataiku.data_types import NativeDataikuDataType

# Neo4j Data Types: https://neo4j.com/docs/cypher-manual/current/values-and-types/property-structural-constructed/

# Synonyms: https://neo4j.com/docs/cypher-manual/current/values-and-types/property-structural-constructed/#types-synonyms
IntAliases = Union[Literal["INTEGER"], Literal["INT"], Literal["SIGNED INTEGER"]]
BooleanAliases = Union[Literal["BOOLEAN"], Literal["BOOL"]]
StringAliases = Union[Literal["STRING"], Literal["VARCHAR"]]
LocalDateTimeAliases = Union[
    Literal["LOCAL DATETIME"], Literal["TIMESTAMP WITHOUT TIME ZONE"], Literal["TIMESTAMP WITHOUT TIMEZONE"]
]
ZonedDateTimeAliases = Union[
    Literal["ZONED DATETIME"], Literal["TIMESTAMP WITH TIME ZONE"], Literal["TIMESTAMP WITH TIMEZONE"]
]
LocalTimeAliases = Union[Literal["LOCAL TIME"], Literal["TIME WITHOUT TIME ZONE"], Literal["TIME WITHOUT TIMEZONE"]]
ZonedTimeAliases = Union[Literal["ZONED TIME"], Literal["TIME WITH TIME ZONE"], Literal["TIME WITH TIMEZONE"]]
NodeAliases = Union[Literal["NODE"], Literal["ANY NODE"], Literal["VERTEX"], Literal["ANY VERTEX"]]
EdgeAliases = Union[Literal["RELATIONSHIP"], Literal["ANY RELATIONSHIP"], Literal["EDGE"], Literal["ANY EDGE"]]
AnyAliases = Union[Literal["ANY"], Literal["ANY VALUE"]]

# Union of all valid property types
AnyPropertyValueAliases = Union[Literal["PROPERTY VALUE"], Literal["ANY PROPERTY VALUE"]]

Neo4jDataType = Union[
    IntAliases,
    Literal["FLOAT"],
    BooleanAliases,
    StringAliases,
    Literal["NOTHING"],
    Literal["NULL"],
    Literal["DATE"],
    LocalDateTimeAliases,
    ZonedDateTimeAliases,
    LocalTimeAliases,
    ZonedTimeAliases,
    Literal["DURATION"],
    Literal["LIST"],
    Literal["MAP"],
    NodeAliases,
    EdgeAliases,
    Literal["PATH"],
    Literal["POINT"],
    Literal["VECTOR"],
    AnyAliases,
    AnyPropertyValueAliases,
]

TYPE_MAP_DATAIKU_TO_NEO4J: Dict[NativeDataikuDataType, Neo4jDataType] = {
    "string": "STRING",
    "boolean": "BOOLEAN",
    "date": "ZONED DATETIME",
    "datetimenotz": "LOCAL DATETIME",
    "dateonly": "DATE",
    "tinyint": "INTEGER",
    "smallint": "INTEGER",
    "int": "INTEGER",
    "bigint": "INTEGER",
    "float": "FLOAT",
    "double": "FLOAT",
    "object": "STRING",
    "array": "STRING",
    "map": "STRING",
    # The following types are not supported.
    # "geometry"
    # "geopoint": candidate is POINT
}
