"""Docker generator — reads ProjectSpec.docker to generate Docker config."""

from __future__ import annotations

from pathlib import Path

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


class DockerGenerator(GeneratorBase):
    """Generate Docker configuration from ProjectSpec.docker."""

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

        docker = project_spec.docker

        from prisme.docker import ComposeConfig, ComposeGenerator

        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

        config = ComposeConfig(
            project_name=project_spec.name.replace("-", "_"),
            backend_path=backend_path_relative,
            frontend_path=frontend_path_relative,
            backend_module=backend_module,
            use_redis=docker.include_redis,
            use_mcp=docker.include_mcp,
            mcp_path=gen_config.mcp_path,
        )

        # Use the existing ComposeGenerator to render content (without writing)
        generator = ComposeGenerator(project_dir)

        files: list[GeneratedFile] = []

        files.append(
            GeneratedFile(
                path=Path("docker-compose.dev.yml"),
                content=generator._render_compose_template(config),
                strategy=FileStrategy.GENERATE_ONCE,
                description="Docker Compose dev config",
            )
        )
        files.append(
            GeneratedFile(
                path=Path("Dockerfile.backend"),
                content=generator._render_backend_dockerfile(config),
                strategy=FileStrategy.ALWAYS_OVERWRITE,
                description="Backend Dockerfile",
            )
        )
        files.append(
            GeneratedFile(
                path=Path("Dockerfile.frontend"),
                content=generator._render_frontend_dockerfile(config),
                strategy=FileStrategy.ALWAYS_OVERWRITE,
                description="Frontend Dockerfile",
            )
        )
        files.append(
            GeneratedFile(
                path=Path(".dockerignore"),
                content=generator._render_dockerignore(),
                strategy=FileStrategy.GENERATE_ONCE,
                description="Docker ignore file",
            )
        )

        # Generate production config if domain or non-default replicas are set
        prod = docker.production
        if prod.domain or prod.replicas != 2:
            from prisme.docker import ProductionComposeGenerator, ProductionConfig

            prod_config = ProductionConfig(
                project_name=project_spec.name,
                use_redis=docker.include_redis,
                domain=prod.domain,
                backend_replicas=prod.replicas,
                backend_path=backend_path_relative,
                frontend_path=frontend_path_relative,
                backend_module=backend_module,
            )

            prod_gen = ProductionComposeGenerator(project_dir)

            # Render production Dockerfiles
            prod_env = prod_gen.env

            template = prod_env.get_template("docker/Dockerfile.backend.prod.jinja2")
            content = template.render(
                project_name=prod_config.project_name,
                backend_path=prod_config.backend_path,
                backend_module=prod_config.backend_module,
            )
            files.append(
                GeneratedFile(
                    path=Path("Dockerfile.backend.prod"),
                    content=content,
                    strategy=FileStrategy.GENERATE_ONCE,
                    description="Production backend Dockerfile",
                )
            )

            template = prod_env.get_template("docker/Dockerfile.frontend.prod.jinja2")
            content = template.render(
                project_name=prod_config.project_name,
                frontend_path=prod_config.frontend_path,
            )
            files.append(
                GeneratedFile(
                    path=Path("Dockerfile.frontend.prod"),
                    content=content,
                    strategy=FileStrategy.GENERATE_ONCE,
                    description="Production frontend Dockerfile",
                )
            )

            template = prod_env.get_template("docker/docker-compose.prod.yml.jinja2")
            content = template.render(
                PROJECT_NAME=prod_config.project_name,
                use_redis=prod_config.use_redis,
                backend_replicas=prod_config.backend_replicas,
                backend_path=prod_config.backend_path,
                frontend_path=prod_config.frontend_path,
                backend_module=prod_config.backend_module,
            )
            files.append(
                GeneratedFile(
                    path=Path("docker-compose.prod.yml"),
                    content=content,
                    strategy=FileStrategy.GENERATE_ONCE,
                    description="Production Docker Compose config",
                )
            )

            # .env.prod.example
            env_example = f"""# Production Environment Variables

# Project
PROJECT_NAME={prod_config.project_name}

# Database
DB_USER=postgres
DB_PASSWORD=CHANGE_ME_IN_PRODUCTION
POSTGRES_PASSWORD=CHANGE_ME_IN_PRODUCTION

# Backend
SECRET_KEY=GENERATE_RANDOM_SECRET_KEY_HERE
ALLOWED_HOSTS={prod_config.domain + "," if prod_config.domain else ""}localhost,127.0.0.1
ENVIRONMENT=production

# Redis (if used)
{"REDIS_URL=redis://redis:6379/0" if prod_config.use_redis else "# REDIS_URL=redis://redis:6379/0"}
"""
            files.append(
                GeneratedFile(
                    path=Path(".env.prod.example"),
                    content=env_example,
                    strategy=FileStrategy.GENERATE_ONCE,
                    description="Production env example",
                )
            )

        return files
