"""Runner infrastructure generator.

Generates GitHub Actions workflows that provision ephemeral Hetzner Cloud
VMs as self-hosted runners for CI jobs. The generated workflows handle:

1. **setup-runner** job: Creates a Hetzner VM, installs the GitHub Actions
   runner agent, and registers it as an ephemeral self-hosted runner.
2. **CI jobs**: Run on ``self-hosted`` with Hetzner labels, using the
   provisioned VM.
3. **teardown-runner** job: Destroys the Hetzner VM after all jobs complete
   (runs even on failure via ``if: always()``).
"""

from __future__ import annotations

from pathlib import Path

from jinja2 import Environment, PackageLoader, select_autoescape

from prisme.generators.base import GeneratedFile, GeneratorBase
from prisme.spec.stack import FileStrategy


class RunnerGenerator(GeneratorBase):
    """Generate CI workflow with Hetzner ephemeral runner provisioning."""

    def generate_files(self) -> list[GeneratedFile]:
        project_spec = self.context.project_spec
        if project_spec is None or project_spec.ci is None:
            return []

        ci = project_spec.ci
        if ci.provider != "github" or ci.hetzner_runner is None:
            return []

        runner = ci.hetzner_runner

        gen_config = project_spec.generator
        backend_output = Path(gen_config.backend_output)
        frontend_output = Path(gen_config.frontend_output)
        project_dir = Path.cwd()

        backend_path_relative = str(backend_output.parent)
        frontend_path_relative = str(
            frontend_output.parent
            if (project_dir / frontend_output.parent / "package.json").exists()
            else frontend_output
        )
        backend_module = project_spec.backend.module_name or backend_output.name

        env = Environment(
            loader=PackageLoader("prisme", "templates/jinja2"),
            autoescape=select_autoescape(),
            trim_blocks=True,
            lstrip_blocks=True,
        )

        files: list[GeneratedFile] = []

        # CI workflow with self-hosted Hetzner runners
        template = env.get_template("ci/github/ci-hetzner.yml.jinja2")
        content = template.render(
            project_name=project_spec.name,
            project_name_snake=project_spec.name.replace("-", "_"),
            include_frontend=ci.include_frontend,
            use_redis=ci.use_redis,
            python_version="3.13",
            node_version="22",
            enable_codecov=ci.enable_codecov,
            backend_path=backend_path_relative,
            frontend_path=frontend_path_relative,
            backend_module=backend_module,
            runner_server_type=runner.server_type,
            runner_location=runner.location,
            runner_image=runner.image,
            runner_labels=runner.labels,
        )
        files.append(
            GeneratedFile(
                path=Path(".github/workflows/ci.yml"),
                content=content,
                strategy=FileStrategy.GENERATE_ONCE,
                description="CI workflow with Hetzner runners",
            )
        )

        # Cleanup workflow for stale runners
        template = env.get_template("ci/github/runner-cleanup.yml.jinja2")
        content = template.render(
            runner_labels=runner.labels,
        )
        files.append(
            GeneratedFile(
                path=Path(".github/workflows/runner-cleanup.yml"),
                content=content,
                strategy=FileStrategy.GENERATE_ONCE,
                description="Hetzner runner cleanup workflow",
            )
        )

        return files
