"""Generated GraphQL models.

All fields are Optional for maximum flexibility in test automation.
The GraphQL API will validate required fields at runtime.

IMPORTANT: Call ensure_models_rebuilt() before using models with forward references.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from pydantic import BaseModel
{%- if types or interfaces %}
from pydantic import ConfigDict
from pydantic import Field
{%- endif %}

from ..enums import *
from ..scalars import *

{#- Collect modules needed for inheritance (runtime imports) #}
{%- set runtime_imports = {} %}
{%- for type in types %}
{%- for iface in type.full_interfaces if '.' in iface %}
{%- set module = iface.split('.')[0] %}
{%- if module not in runtime_imports %}
{%- set _ = runtime_imports.update({module: true}) %}
{%- endif %}
{%- endfor %}
{%- endfor %}

{#- Runtime imports only for inheritance (base classes, sorted for I001) #}
{%- if runtime_imports %}
{%- for module in runtime_imports.keys() | sort %}
from . import {{ module }}
{%- endfor %}
{%- endif %}

if TYPE_CHECKING:
{#- Type-checking imports for forward references (sorted for I001) #}
{%- set type_check_imports = {} %}
{%- for dep_file, dep_types in external_imports.items() if dep_file not in runtime_imports %}
{%- set _ = type_check_imports.update({dep_file: dep_types}) %}
{%- endfor %}
{%- if type_check_imports %}
{%- for dep_file in type_check_imports.keys() | sort %}
    from . import {{ dep_file }}
{%- endfor %}
{%- else %}
    pass
{%- endif -%}
{#- Macros for field handling - no output -#}
{%- set PYTHON_RESERVED = [
    'False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',
    'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',
    'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',
    'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try',
    'while', 'with', 'yield', 'to',
    'bool', 'str', 'int', 'float', 'list', 'dict', 'set', 'tuple',
    'type', 'object', 'hash', 'len', 'range', 'print', 'input',
    'open', 'file', 'bytes', 'bytearray', 'map', 'filter', 'zip',
    'enumerate', 'sorted', 'reversed', 'min', 'max', 'sum', 'abs',
    'all', 'any', 'next', 'iter', 'repr', 'format', 'vars', 'dir',
    'getattr', 'setattr', 'hasattr', 'delattr', 'callable', 'isinstance',
    'issubclass', 'super', 'property', 'staticmethod', 'classmethod'
] -%}
{%- macro field_name(field) -%}
{{ field.name }}{% if field.name in PYTHON_RESERVED or field.name == field.type_name %}_{% endif %}
{%- endmacro -%}
{#- Macro for Python type from GraphQL type - uses direct types for scalars -#}
{%- macro python_type(type_name) -%}
{%- if type_name == 'String' %}str
{%- elif type_name == 'Int' %}int
{%- elif type_name == 'Float' %}float
{%- elif type_name == 'Boolean' %}bool
{%- elif type_name == 'ID' %}str
{%- else %}{{ type_name }}
{%- endif %}
{%- endmacro -%}
{#- Macro for field type annotation - ALL fields are Optional for automation -#}
{#- With `from __future__ import annotations`, no quotes are needed (PEP 563) -#}
{%- macro field_type(field) -%}
{%- set py_type = python_type(field.full_type_name) -%}
{%- if field.is_list -%}
list[{{ py_type }}] | None
{%- else -%}
{{ py_type }} | None
{%- endif -%}
{%- endmacro -%}
{#- Macro for field default value -#}
{%- macro field_default(field) -%}
{% if field.is_list %}default_factory=list{% else %}None{% endif %}
{%- endmacro -%}
{#- Generate interfaces first as base classes -#}
{%- for interface in interfaces %}
{% set _dummy = '' %}

class {{ interface.name }}(BaseModel):
    """{{ (interface.description or interface.name)|safe_docstring }}"""

    model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)
{%- for field in interface.fields %}
    {{ field_name(field) }}: {{ field_type(field) }} = Field({{ field_default(field) }}, description={{ (field.description or '')|repr }}, alias="{{ field.name }}")
{%- endfor %}
{%- endfor -%}
{#- Generate types with interface inheritance -#}
{%- for type in types %}
{% set base_classes = type.full_interfaces if type.full_interfaces else ['BaseModel'] %}

class {{ type.name }}({{ base_classes | join(', ') }}):
    """{{ (type.description or type.name)|safe_docstring }}"""

    model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)
{%- for field in type.fields %}
    {#- Skip fields inherited from interfaces -#}
    {%- set inherited_fields = [] -%}
    {%- for iface_name in type.interfaces -%}
        {%- if iface_name in interface_fields -%}
            {%- for ifield in interface_fields[iface_name] -%}
                {%- set _ = inherited_fields.append(ifield) -%}
            {%- endfor -%}
        {%- endif -%}
    {%- endfor -%}
    {%- if field.name not in inherited_fields %}
    {{ field_name(field) }}: {{ field_type(field) }} = Field({{ field_default(field) }}, description={{ (field.description or '')|repr }}, alias="{{ field.name }}")
    {%- endif -%}
{%- endfor %}
{%- endfor %}


# Rebuild models to resolve forward references within this module
def _rebuild_module_models():
    """Rebuild all models in this module to resolve forward references."""
    import sys
    current_module = sys.modules[__name__]

    # Build namespace with all types from this module plus imported modules
    rebuild_namespace = {}

    # Add all runtime-imported modules (for cross-module references like "base.CountryRefInput")
{%- for module in runtime_imports.keys() %}
    rebuild_namespace['{{ module }}'] = {{ module }}
{%- endfor %}

    # Add all types from this module
    for name in dir(current_module):
        obj = getattr(current_module, name, None)
        if isinstance(obj, type) and issubclass(obj, BaseModel):
            rebuild_namespace[name] = obj

    # Rebuild all models
    for name in dir(current_module):
        obj = getattr(current_module, name, None)
        if isinstance(obj, type) and issubclass(obj, BaseModel) and obj is not BaseModel:
            if not getattr(obj, '__pydantic_complete__', True):
                try:
                    obj.model_rebuild(_types_namespace=rebuild_namespace)
                except Exception:
                    pass


_rebuild_module_models()
