"""Base generator utilities shared across all generators."""

from __future__ import annotations

from pathlib import Path
from typing import Any

from jinja2 import Environment, PackageLoader, select_autoescape
from ninja_core.schema.entity import EntitySchema

CODEGEN_HEADER = "# AUTO-GENERATED by ninja-codegen — DO NOT EDIT"

_env: Environment | None = None


def get_template_env() -> Environment:
    """Get the shared Jinja2 template environment."""
    global _env
    if _env is None:
        _env = Environment(
            loader=PackageLoader("ninja_codegen", "templates"),
            autoescape=select_autoescape([]),
            keep_trailing_newline=True,
            trim_blocks=True,
            lstrip_blocks=True,
        )
        _env.filters["repr"] = repr
    return _env


def write_generated_file(path: Path, content: str) -> bool:
    """Write generated content to a file, returning True if the file changed.

    Skips writing if the content is identical (idempotent).
    """
    path.parent.mkdir(parents=True, exist_ok=True)
    if path.exists() and path.read_text() == content:
        return False
    path.write_text(content)
    return True


# Mapping from FieldType enum values (lowercase) to Python type annotations
FIELD_TYPE_MAP: dict[str, str] = {
    "string": "str",
    "text": "str",
    "integer": "int",
    "float": "float",
    "boolean": "bool",
    "datetime": "datetime",
    "date": "date",
    "uuid": "UUID",
    "json": "dict[str, Any]",
    "array": "list[Any]",
    "binary": "bytes",
    "enum": "str",
}

# Mapping from FieldType enum values (lowercase) to Strawberry/GraphQL type annotations
GQL_TYPE_MAP: dict[str, str] = {
    "string": "str",
    "text": "str",
    "integer": "int",
    "float": "float",
    "boolean": "bool",
    "datetime": "str",
    "date": "str",
    "uuid": "str",
    "json": "strawberry.scalars.JSON",
    "array": "list[str]",
    "binary": "str",
    "enum": "str",
}


def build_fields_meta(entity: EntitySchema) -> list[dict[str, Any]]:
    """Build pre-processed field metadata for templates.

    Resolves enum values to Python/GQL type strings so templates
    don't need to do dict lookups on enum objects.
    """
    fields: list[dict[str, Any]] = []
    for f in entity.fields:
        ft_value = f.field_type.value
        fields.append(
            {
                "name": f.name,
                "python_type": FIELD_TYPE_MAP.get(ft_value, "Any"),
                "gql_type": GQL_TYPE_MAP.get(ft_value, "str"),
                "field_type_value": ft_value,
                "nullable": f.nullable,
                "primary_key": f.primary_key,
                "unique": f.unique,
                "indexed": f.indexed,
                "default": f.default,
                "description": f.description,
                "constraints": f.constraints,
            }
        )
    return fields
