from __future__ import annotations

from dataclasses import dataclass
from enum import Enum
from enum import StrEnum
from typing import Any
from typing import Literal
from typing import NamedTuple
from typing import NotRequired

from amsdal_models.classes.model import Model
from amsdal_utils.models.enums import ModuleType
from amsdal_utils.models.enums import TransactionType
from typing_extensions import TypedDict


@dataclass
class ModelInfo:
    model: type[Model]
    scope: ModuleType


ModelRegistry = dict[str, ModelInfo]


class CrudOperation(str, Enum):
    CREATE = 'create'
    READ = 'read'
    UPDATE = 'update'
    DELETE = 'delete'


class CrudResponse(TypedDict):
    operation: str
    model: str
    data: Any


class CrudAnalysisResponse(TypedDict):
    operation: str
    model: str
    analysis: dict[str, Any]
    requires_confirmation: bool


class ModelSummaryView(TypedDict):
    model_name: str
    fields: list[str]


class ModelSchemaView(TypedDict):
    model: str
    schema: dict[str, Any]
    properties: dict[str, str]


class FieldValuesResponse(TypedDict):
    model: str
    field: str
    values: list[dict[str, Any]]


class RelationshipInfo(TypedDict):
    field: str
    references_model: str
    type: str
    required: bool


class ReferencedByRelationshipInfo(TypedDict):
    model: str
    field: str
    type: str


class ModelRelationshipsResponse(TypedDict):
    model: str
    relationships: list[RelationshipInfo]
    referenced_by: list[ReferencedByRelationshipInfo]


class TransactionScope(str, Enum):
    ALL = 'all'
    USER = 'user'
    CONTRIB = 'contrib'


class TransactionParameterKind(StrEnum):
    PRIMITIVE = 'primitive'
    MODEL = 'model'
    DICT = 'dict'
    UNKNOWN = 'unknown'


class TransactionArgumentMode(StrEnum):
    LITERAL = 'literal'
    EXISTING_REF = 'existing_ref'
    NEW_OBJECT = 'new_object'
    EXPLICIT_ID = 'explicit_id'


class TransactionParameterView(TypedDict):
    name: str
    annotation: str
    kind: TransactionParameterKind
    model_name: str | None
    nullable: NotRequired[bool]


class TransactionView(TypedDict):
    name: str
    description: str
    scope: Literal[TransactionType.USER, TransactionType.CONTRIB]
    parameters: list[TransactionParameterView]


class TransactionCatalogResponse(TypedDict):
    transactions: list[TransactionView]


class TransactionAnalysisResponse(TypedDict):
    transaction_name: str
    analysis: dict[str, Any]
    requires_confirmation: bool


class TransactionExecutionResponse(TypedDict):
    transaction_name: str
    result: Any


class AnnotationTypeName(StrEnum):
    STR = 'str'
    INT = 'int'
    FLOAT = 'float'
    BOOL = 'bool'
    ANY = 'Any'
    OPTIONAL = 'Optional'


class AnnotationMeta(NamedTuple):
    kind: TransactionParameterKind
    model_name: str | None
    nullable: bool


ParameterMeta = tuple[str, AnnotationMeta]


TransactionParameterMetaByName = dict[str, ParameterMeta]


LiteralScalar = str | int | float | bool | None


LiteralValue = LiteralScalar | list[LiteralScalar] | dict[str, LiteralScalar]
