"""YAML binding file generator.

Writes ScannedModule instances as .binding.yaml files compatible with
apcore.BindingLoader.
"""

from __future__ import annotations

import logging
import re
from datetime import UTC, datetime
from pathlib import Path
from typing import TYPE_CHECKING, Any

import yaml

if TYPE_CHECKING:
    from django_apcore.scanners.base import ScannedModule

logger = logging.getLogger("django_apcore")


class YAMLWriter:
    """Generates .binding.yaml files from ScannedModule instances."""

    def write(
        self,
        modules: list[ScannedModule],
        output_dir: str,
        dry_run: bool = False,
    ) -> list[dict[str, Any]]:
        """Write YAML binding files for each ScannedModule.

        Args:
            modules: List of ScannedModule instances to write.
            output_dir: Directory path to write files to.
            dry_run: If True, return content without writing to disk.

        Returns:
            List of dicts representing the YAML content for each module.
        """
        if not modules:
            return []

        output_path = Path(output_dir).resolve()
        if not dry_run:
            output_path.mkdir(parents=True, exist_ok=True)

        results: list[dict[str, Any]] = []
        timestamp = datetime.now(UTC).isoformat()

        for module in modules:
            binding_data = self._build_binding(module)
            results.append(binding_data)

            if not dry_run:
                # Sanitize module_id for safe filename construction
                safe_id = re.sub(r"[^a-zA-Z0-9._-]", "_", module.module_id)
                filename = f"{safe_id}.binding.yaml"
                file_path = (output_path / filename).resolve()

                # Path traversal protection
                if not str(file_path).startswith(str(output_path)):
                    logger.warning(
                        "Skipping file outside output directory: %s",
                        file_path,
                    )
                    continue

                if file_path.exists():
                    logger.warning("Overwriting existing file: %s", file_path)

                header = (
                    f"# Auto-generated by django-apcore scanner\n"
                    f"# Generated: {timestamp}\n"
                    "# Do not edit manually unless you intend"
                    " to customize schemas.\n\n"
                )
                yaml_content = yaml.dump(
                    binding_data, default_flow_style=False, sort_keys=False
                )
                file_path.write_text(header + yaml_content, encoding="utf-8")
                logger.debug("Written: %s", file_path)

        return results

    def _build_binding(self, module: ScannedModule) -> dict[str, Any]:
        """Build the YAML-serializable dict for a ScannedModule."""
        return {
            "bindings": [
                {
                    "module_id": module.module_id,
                    "target": module.target,
                    "description": module.description,
                    "tags": module.tags,
                    "version": module.version,
                    "input_schema": module.input_schema,
                    "output_schema": module.output_schema,
                }
            ]
        }
