"""
StrEnum generator for Django TextChoices fields.

Generates enums.py per app containing StrEnum classes
that mirror Django TextChoices definitions.
"""

from ..base import BaseGenerator
from ...ir.models import GeneratedFile, ParsedModel, ParsedField


class EnumsGenerator(BaseGenerator):
    """
    Generates enums.py files with StrEnum classes from Django TextChoices.

    For each app that has CharField/IntegerField with choices backed by
    a TextChoices class, generates:

        class LLMProviderType(StrEnum):
            OPENROUTER = "openrouter"
            ANTHROPIC = "anthropic"
            ...
    """

    def generate(self) -> list[GeneratedFile]:
        files: list[GeneratedFile] = []

        for app_label, models in self.context.group_models_by_app().items():
            enums = self._collect_enums(models)
            if not enums:
                continue

            content = self._generate_enums_file(app_label, enums)
            files.append(self.create_file(f"{app_label}/enums.py", content))

            # Store enum class names per app so SQLModelGenerator can pick them up
            # (used by _generate_init_file patch below)
            self._app_enums[app_label] = list(enums.keys())

        return files

    # Map of app_label -> list of enum class names, populated during generate()
    # Used by SQLModelGenerator to update __init__.py
    _app_enums: dict[str, list[str]] = {}

    def _collect_enums(
        self, models: list[ParsedModel]
    ) -> dict[str, list[tuple[str, str]]]:
        """
        Collect all unique TextChoices enums from all fields in all models.

        Returns:
            dict of {ClassName: [(VALUE, "value"), ...]}
        """
        enums: dict[str, list[tuple[str, str]]] = {}

        for model in models:
            for field in model.fields:
                if not field.choices_class or not field.choices:
                    continue
                class_name = field.choices_class
                if class_name in enums:
                    continue
                # choices is list of (value, label) tuples
                members: list[tuple[str, str]] = []
                for value, _label in field.choices:
                    if not isinstance(value, str):
                        continue
                    # Derive UPPER_CASE member name from value
                    member_name = value.upper().replace("-", "_").replace(".", "_").replace(" ", "_")
                    members.append((member_name, value))
                if members:
                    enums[class_name] = members

        return enums

    def _generate_enums_file(
        self, app_label: str, enums: dict[str, list[tuple[str, str]]]
    ) -> str:
        lines = [
            '"""',
            f"StrEnum classes for {app_label}.",
            "",
            "Auto-generated by django-cfg FastAPI ORM Generator.",
            "Do not edit manually - changes will be overwritten.",
            '"""',
            "",
            "from enum import StrEnum",
            "",
        ]

        for class_name, members in enums.items():
            lines.append(f"class {class_name}(StrEnum):")
            for member_name, value in members:
                lines.append(f'    {member_name} = "{value}"')
            lines.append("")
            lines.append("")

        return "\n".join(lines)
