"""Plain Python (no framework) code generator."""

import re

from agent_blueprint.exceptions import GeneratorError
from agent_blueprint.generators.base import BaseGenerator
from agent_blueprint.ir.compiler import AgentGraph


def _safe_id(value: str) -> str:
    return re.sub(r"[^a-zA-Z0-9_]", "_", value)


class PlainPythonGenerator(BaseGenerator):
    """Generates a plain Python agent script (openai SDK, no framework)."""

    def generate(self, ir: AgentGraph) -> dict[str, str]:
        files: dict[str, str] = {}
        files["agent.py"] = self._generate_agent(ir)
        files["requirements.txt"] = "openai>=1.0\nhttpx>=0.27\npython-dotenv>=1.0\n"
        files[".env.example"] = "OPENAI_API_KEY=\n"
        return files

    def _generate_agent(self, ir: AgentGraph) -> str:
        lines = [
            f'"""Agent: {ir.name} (v{ir.version})"""',
            "# Generated by agent-blueprint - plain Python target",
            "",
            "import os",
            "from openai import OpenAI",
            "",
            "client = OpenAI()",
            "",
        ]

        for node in ir.nodes:
            if not node.agent:
                continue
            fn_name = f"run_{_safe_id(node.id)}"
            system_prompt = (node.agent.system_prompt or "You are a helpful assistant.").replace('"""', '\\"\\"\\"')
            lines += [
                f"def {fn_name}(messages: list[dict]) -> str:",
                f'    """Node: {node.description}"""',
                f'    system = """',
                f'{system_prompt.rstrip()}',
                f'"""',
                f"    full_messages = [{{\"role\": \"system\", \"content\": system}}] + messages",
                f"    response = client.chat.completions.create(",
                f'        model="{node.agent.model}",',
                f"        messages=full_messages,",
                f"    )",
                f"    return response.choices[0].message.content or \"\"",
                "",
            ]

        # Simple sequential runner for entry point node
        entry_node = ir.get_node(ir.entry_point)
        if entry_node:
            entry_fn = f"run_{_safe_id(ir.entry_point)}"
            lines += [
                "def main(user_input: str) -> str:",
                f"    messages = [{{\"role\": \"user\", \"content\": user_input}}]",
                f"    return {entry_fn}(messages)",
                "",
                'if __name__ == "__main__":',
                "    import sys",
                "    prompt = \" \".join(sys.argv[1:]) if len(sys.argv) > 1 else input(\"Message: \")",
                "    print(main(prompt))",
            ]

        return "\n".join(lines) + "\n"
