from infrahub.core.constants import (
    BranchSupportType,
    GeneratorInstanceStatus,
    InfrahubKind,
)
from infrahub.core.constants import RelationshipCardinality as Cardinality
from infrahub.core.constants import RelationshipKind as RelKind

from ...attribute_schema import AttributeSchema as Attr
from ...node_schema import NodeSchema
from ...relationship_schema import (
    RelationshipSchema as Rel,
)

core_generator_definition = NodeSchema(
    name="GeneratorDefinition",
    namespace="Core",
    description="Defines a generator that creates or updates objects based on a GraphQL query",
    include_in_menu=False,
    icon="mdi:state-machine",
    label="Generator Definition",
    default_filter="name__value",
    order_by=["name__value"],
    display_labels=["name__value"],
    branch=BranchSupportType.AWARE,
    uniqueness_constraints=[["name__value"]],
    generate_profile=False,
    inherit_from=[InfrahubKind.TASKTARGET],
    documentation="/topics/generator",
    attributes=[
        Attr(name="name", kind="Text", unique=True),
        Attr(name="description", kind="Text", optional=True),
        Attr(name="parameters", kind="JSON", description="GraphQL query parameters for the generator"),
        Attr(name="file_path", kind="Text", description="Path to the Python file containing the generator class"),
        Attr(name="class_name", kind="Text", description="Name of the Python class implementing the generator"),
        Attr(
            name="convert_query_response",
            kind="Boolean",
            description="Whether to convert the GraphQL response to SDK objects",
            optional=True,
            default_value=False,
        ),
        Attr(
            name="execute_in_proposed_change",
            kind="Boolean",
            description="Whether to run this generator in proposed changes",
            optional=True,
            default_value=True,
        ),
        Attr(
            name="execute_after_merge",
            kind="Boolean",
            description="Whether to run this generator after a merge",
            optional=True,
            default_value=True,
        ),
    ],
    relationships=[
        Rel(
            name="query",
            peer=InfrahubKind.GRAPHQLQUERY,
            identifier="generator_definition__graphql_query",
            kind=RelKind.ATTRIBUTE,
            cardinality=Cardinality.ONE,
            optional=False,
        ),
        Rel(
            name="repository",
            peer=InfrahubKind.GENERICREPOSITORY,
            kind=RelKind.ATTRIBUTE,
            cardinality=Cardinality.ONE,
            identifier="generator_definition__repository",
            optional=False,
        ),
        Rel(
            name="targets",
            peer=InfrahubKind.GENERICGROUP,
            kind=RelKind.ATTRIBUTE,
            identifier="generator_definition___group",
            cardinality=Cardinality.ONE,
            optional=False,
        ),
    ],
)

core_generator_instance = NodeSchema(
    name="GeneratorInstance",
    namespace="Core",
    description="An instance of a generator execution for a specific object",
    label="Generator Instance",
    include_in_menu=False,
    icon="mdi:file-document-outline",
    default_filter="name__value",
    order_by=["name__value"],
    display_labels=["name__value"],
    branch=BranchSupportType.LOCAL,
    generate_profile=False,
    inherit_from=[InfrahubKind.TASKTARGET],
    documentation="/topics/generator",
    attributes=[
        Attr(name="name", kind="Text"),
        Attr(name="status", kind="Text", enum=GeneratorInstanceStatus.available_types()),
    ],
    relationships=[
        Rel(
            name="object",
            peer=InfrahubKind.NODE,
            kind=RelKind.ATTRIBUTE,
            identifier="generator__node",
            cardinality=Cardinality.ONE,
            optional=False,
        ),
        Rel(
            name="definition",
            peer=InfrahubKind.GENERATORDEFINITION,
            kind=RelKind.ATTRIBUTE,
            identifier="generator__generator_definition",
            cardinality=Cardinality.ONE,
            optional=False,
        ),
    ],
)
