"""
Workflow Generator — Phase 23.6

Converts an Experience into a reusable WorkflowTemplate.

A WorkflowTemplate is an actionable, structured guide:
    "Next time you encounter trigger X in scene Y,
     execute steps [A, B, C] using tools [tool1, tool2]."

Generation pipeline:
  1. Parse steps from Experience
  2. Detect tools used in each step
  3. Add conditions / guards where applicable
  4. Assign trigger description
  5. Return WorkflowTemplate (caller saves via ExperienceRegistry)
"""

import logging
import re
from typing import Dict, List, Optional

from openmemo.experience.models import Experience, WorkflowTemplate

logger = logging.getLogger("openmemo.experience.workflow_gen")

KNOWN_TOOLS = {
    "docker", "kubectl", "helm", "terraform", "ansible",
    "git", "npm", "pip", "cargo", "make", "bash", "curl",
    "psql", "mysql", "redis", "kafka", "nginx", "systemctl",
    "pytest", "jest", "gradle", "mvn", "python", "node",
    "aws", "gcloud", "az",
}


class WorkflowGenerator:
    """
    Converts Experiences into executable WorkflowTemplates.

    Args:
        llm_fn — Optional LLM callable for smarter step refinement
    """

    def __init__(self, llm_fn=None):
        self._llm_fn = llm_fn

    def generate(self, experience: Experience) -> WorkflowTemplate:
        """
        Generate a WorkflowTemplate from an Experience.

        Returns:
            WorkflowTemplate ready to persist
        """
        if self._llm_fn and experience.steps:
            return self._generate_with_llm(experience)
        return self._generate_rule_based(experience)

    def generate_batch(self, experiences: List[Experience]) -> List[WorkflowTemplate]:
        """Generate WorkflowTemplates for a list of Experiences."""
        workflows = []
        for exp in experiences:
            if exp.type in ("workflow", "pattern"):
                wf = self.generate(exp)
                workflows.append(wf)
        return workflows

    # ─── Rule-based generation ─────────────────────────────────────

    def _generate_rule_based(self, experience: Experience) -> WorkflowTemplate:
        structured_steps = self._structure_steps(experience.steps, experience)
        trigger = self._build_trigger(experience)
        name = self._build_name(experience)

        return WorkflowTemplate(
            name=name,
            trigger=trigger,
            steps=structured_steps,
            experience_id=experience.id,
            scene=experience.scene,
            agent_id=experience.agent_id,
            metadata={
                "source_experience_type": experience.type,
                "extracted_from_nodes": len(experience.source_node_ids),
                "outcome": experience.outcome,
            },
        )

    def _structure_steps(self, steps: List[str],
                          experience: Experience) -> List[Dict]:
        """
        Convert raw step strings into structured step dicts:
        {step, tool, input_template, condition}
        """
        if not steps:
            return self._steps_from_facts(experience)

        structured = []
        for i, step_text in enumerate(steps):
            tool = self._detect_tool(step_text)
            condition = ""
            if i == 0:
                condition = f"Start when: {experience.conditions.get('trigger', 'task begins')}"
            elif i == len(steps) - 1:
                condition = "Execute last — verify outcome"

            structured.append({
                "step": step_text[:200],
                "tool": tool,
                "input_template": self._make_input_template(step_text, tool),
                "condition": condition,
                "order": i + 1,
            })
        return structured

    def _steps_from_facts(self, experience: Experience) -> List[Dict]:
        """Fallback: generate steps from key_facts if steps list is empty."""
        structured = []
        for i, fact in enumerate(experience.key_facts[:5]):
            structured.append({
                "step": fact,
                "tool": "",
                "input_template": "",
                "condition": "",
                "order": i + 1,
            })
        if not structured:
            structured.append({
                "step": f"Apply {experience.title}",
                "tool": "",
                "input_template": "",
                "condition": "",
                "order": 1,
            })
        return structured

    def _detect_tool(self, text: str) -> str:
        """Detect tool name from step text."""
        lower = text.lower()
        for tool in KNOWN_TOOLS:
            if tool in lower:
                return tool
        pattern = r"tool=(\w+)"
        match = re.search(pattern, lower)
        if match:
            return match.group(1)
        return ""

    def _make_input_template(self, text: str, tool: str) -> str:
        """Generate a simple input template for the step."""
        action_match = re.search(r"action=([^\s|]+)", text.lower())
        if action_match:
            return action_match.group(1)
        if tool:
            return f"{tool} <args>"
        return ""

    def _build_trigger(self, experience: Experience) -> str:
        """Build the trigger description."""
        conditions = experience.conditions
        trigger = conditions.get("trigger", "")
        scene = experience.scene or conditions.get("scene", "")

        parts = []
        if scene:
            parts.append(f"In {scene} context")
        if trigger:
            parts.append(f"when task involves: {trigger}")
        elif experience.type == "workflow":
            parts.append("when executing a multi-step process")
        elif experience.type == "lesson":
            parts.append("when similar failure conditions are detected")
        elif experience.type == "pattern":
            parts.append("when this behavioral pattern is detected")

        if not parts:
            parts.append(f"when {experience.title.lower()}")

        return " ".join(parts)

    def _build_name(self, experience: Experience) -> str:
        """Build workflow name from experience."""
        scene = experience.scene
        outcome = experience.outcome
        if scene and outcome:
            return f"{scene.title()} workflow → {outcome}"
        if experience.title:
            return f"Workflow: {experience.title[:60]}"
        return f"Auto-workflow from {experience.type}"

    # ─── LLM-assisted generation ───────────────────────────────────

    def _generate_with_llm(self, experience: Experience) -> WorkflowTemplate:
        """LLM-assisted workflow generation."""
        prompt = (
            f"Convert this experience into a reusable workflow.\n\n"
            f"Experience Title: {experience.title}\n"
            f"Type: {experience.type}\n"
            f"Steps observed: {experience.steps[:6]}\n"
            f"Outcome: {experience.outcome}\n"
            f"Key facts: {experience.key_facts}\n"
            f"Scene: {experience.scene}\n\n"
            "Generate a JSON workflow with:\n"
            "  name (str): workflow name\n"
            "  trigger (str): when to use this workflow\n"
            "  steps (list): [{step, tool, input_template, condition}]\n\n"
            "Return ONLY valid JSON."
        )
        try:
            import json
            response = self._llm_fn(prompt).strip()
            if response.startswith("```"):
                response = response.split("```")[1]
                if response.startswith("json"):
                    response = response[4:]
            data = json.loads(response)
            return WorkflowTemplate(
                name=data.get("name", self._build_name(experience)),
                trigger=data.get("trigger", self._build_trigger(experience)),
                steps=data.get("steps", self._structure_steps(
                    experience.steps, experience)),
                experience_id=experience.id,
                scene=experience.scene,
                agent_id=experience.agent_id,
                metadata={"llm_generated": True,
                          "source_experience_type": experience.type},
            )
        except Exception as e:
            logger.warning("[workflow_gen] LLM generation failed: %s — falling back", e)
            return self._generate_rule_based(experience)
