#!/usr/bin/env python3
"""
Uni-Wizard Router v2 — Intelligent delegation across the three houses

Routes tasks to the appropriate house based on task characteristics:
- READ/ARCHIVE tasks → Ezra (archivist)
- BUILD/TEST tasks → Bezalel (artificer)  
- JUDGE/REVIEW tasks → Timmy (sovereign)

Usage:
    router = HouseRouter()
    result = router.route("read_and_summarize", {"repo": "timmy-home"})
"""

import json
from typing import Dict, Any, Optional, List
from pathlib import Path
from dataclasses import dataclass
from enum import Enum

from harness import UniWizardHarness, House, ExecutionResult


class TaskType(Enum):
    """Categories of work for routing decisions"""
    READ = "read"           # Read, analyze, summarize
    ARCHIVE = "archive"     # Store, catalog, preserve
    SYNTHESIZE = "synthesize"  # Combine, reconcile, interpret
    BUILD = "build"         # Implement, create, construct
    TEST = "test"           # Verify, validate, benchmark
    OPTIMIZE = "optimize"   # Tune, improve, harden
    JUDGE = "judge"         # Review, decide, approve
    ROUTE = "route"         # Delegate, coordinate, dispatch


@dataclass
class RoutingDecision:
    """Record of why a task was routed to a house"""
    task_type: str
    primary_house: str
    confidence: float
    reasoning: str
    fallback_houses: List[str]


class HouseRouter:
    """
    Routes tasks to the appropriate wizard house.
    
    The router understands the canon:
    - Ezra reads and orders the pattern
    - Bezalel builds and unfolds the pattern
    - Timmy judges and preserves sovereignty
    """
    
    # Task → House mapping
    ROUTING_TABLE = {
        # Read/Archive tasks → Ezra
        TaskType.READ: {
            "house": House.EZRA,
            "confidence": 0.95,
            "reasoning": "Archivist house: reading is Ezra's domain"
        },
        TaskType.ARCHIVE: {
            "house": House.EZRA,
            "confidence": 0.95,
            "reasoning": "Archivist house: preservation is Ezra's domain"
        },
        TaskType.SYNTHESIZE: {
            "house": House.EZRA,
            "confidence": 0.85,
            "reasoning": "Archivist house: synthesis requires reading first"
        },
        
        # Build/Test tasks → Bezalel
        TaskType.BUILD: {
            "house": House.BEZALEL,
            "confidence": 0.95,
            "reasoning": "Artificer house: building is Bezalel's domain"
        },
        TaskType.TEST: {
            "house": House.BEZALEL,
            "confidence": 0.95,
            "reasoning": "Artificer house: verification is Bezalel's domain"
        },
        TaskType.OPTIMIZE: {
            "house": House.BEZALEL,
            "confidence": 0.90,
            "reasoning": "Artificer house: optimization is Bezalel's domain"
        },
        
        # Judge/Route tasks → Timmy
        TaskType.JUDGE: {
            "house": House.TIMMY,
            "confidence": 1.0,
            "reasoning": "Sovereign house: judgment is Timmy's domain"
        },
        TaskType.ROUTE: {
            "house": House.TIMMY,
            "confidence": 0.95,
            "reasoning": "Sovereign house: routing is Timmy's domain"
        },
    }
    
    # Tool → TaskType mapping
    TOOL_TASK_MAP = {
        # System tools
        "system_info": TaskType.READ,
        "process_list": TaskType.READ,
        "service_status": TaskType.READ,
        "service_control": TaskType.BUILD,
        "health_check": TaskType.TEST,
        "disk_usage": TaskType.READ,
        
        # Git tools
        "git_status": TaskType.READ,
        "git_log": TaskType.ARCHIVE,
        "git_pull": TaskType.BUILD,
        "git_commit": TaskType.ARCHIVE,
        "git_push": TaskType.BUILD,
        "git_checkout": TaskType.BUILD,
        "git_branch_list": TaskType.READ,
        
        # Network tools
        "http_get": TaskType.READ,
        "http_post": TaskType.BUILD,
        "gitea_list_issues": TaskType.READ,
        "gitea_get_issue": TaskType.READ,
        "gitea_create_issue": TaskType.BUILD,
        "gitea_comment": TaskType.BUILD,
    }
    
    def __init__(self):
        self.harnesses: Dict[House, UniWizardHarness] = {
            House.TIMMY: UniWizardHarness("timmy"),
            House.EZRA: UniWizardHarness("ezra"),
            House.BEZALEL: UniWizardHarness("bezalel")
        }
        self.decision_log: List[RoutingDecision] = []
    
    def classify_task(self, tool_name: str, params: Dict) -> TaskType:
        """Classify a task based on tool and parameters"""
        # Direct tool mapping
        if tool_name in self.TOOL_TASK_MAP:
            return self.TOOL_TASK_MAP[tool_name]
        
        # Heuristic classification
        if any(kw in tool_name for kw in ["read", "get", "list", "status", "info", "log"]):
            return TaskType.READ
        if any(kw in tool_name for kw in ["write", "create", "commit", "push", "post"]):
            return TaskType.BUILD
        if any(kw in tool_name for kw in ["test", "check", "verify", "validate"]):
            return TaskType.TEST
        
        # Default to Timmy for safety
        return TaskType.ROUTE
    
    def route(self, tool_name: str, **params) -> ExecutionResult:
        """
        Route a task to the appropriate house and execute.
        
        Returns execution result with routing metadata attached.
        """
        # Classify the task
        task_type = self.classify_task(tool_name, params)
        
        # Get routing decision
        routing = self.ROUTING_TABLE.get(task_type, {
            "house": House.TIMMY,
            "confidence": 0.5,
            "reasoning": "Default to sovereign house"
        })
        
        house = routing["house"]
        
        # Record decision
        decision = RoutingDecision(
            task_type=task_type.value,
            primary_house=house.value,
            confidence=routing["confidence"],
            reasoning=routing["reasoning"],
            fallback_houses=[h.value for h in [House.TIMMY] if h != house]
        )
        self.decision_log.append(decision)
        
        # Execute via the chosen harness
        harness = self.harnesses[house]
        result = harness.execute(tool_name, **params)
        
        # Attach routing metadata
        result.data = {
            "result": result.data,
            "routing": {
                "task_type": task_type.value,
                "house": house.value,
                "confidence": routing["confidence"],
                "reasoning": routing["reasoning"]
            }
        }
        
        return result
    
    def execute_multi_house_plan(
        self,
        plan: List[Dict],
        require_timmy_approval: bool = False
    ) -> Dict[str, Any]:
        """
        Execute a plan that may span multiple houses.
        
        Example plan:
            [
                {"tool": "git_status", "params": {}, "house": "ezra"},
                {"tool": "git_commit", "params": {"message": "Update"}, "house": "ezra"},
                {"tool": "git_push", "params": {}, "house": "bezalel"}
            ]
        """
        results = {}
        ezra_review = None
        bezalel_proof = None
        
        for step in plan:
            tool_name = step.get("tool")
            params = step.get("params", {})
            specified_house = step.get("house")
            
            # Use specified house or auto-route
            if specified_house:
                harness = self.harnesses[House(specified_house)]
                result = harness.execute(tool_name, **params)
            else:
                result = self.route(tool_name, **params)
            
            results[tool_name] = result
            
            # Collect review/proof for Timmy
            if specified_house == "ezra":
                ezra_review = result
            elif specified_house == "bezalel":
                bezalel_proof = result
        
        # If required, get Timmy's approval
        if require_timmy_approval:
            timmy_harness = self.harnesses[House.TIMMY]
            
            # Build review package
            review_input = {
                "ezra_work": {
                    "success": ezra_review.success if ezra_review else None,
                    "evidence_level": ezra_review.provenance.evidence_level if ezra_review else None,
                    "sources": ezra_review.provenance.sources_read if ezra_review else []
                },
                "bezalel_work": {
                    "success": bezalel_proof.success if bezalel_proof else None,
                    "proof_verified": bezalel_proof.success if bezalel_proof else None
                } if bezalel_proof else None
            }
            
            # Timmy judges
            timmy_result = timmy_harness.execute(
                "review_proposal",
                proposal=json.dumps(review_input)
            )
            
            results["timmy_judgment"] = timmy_result
        
        return results
    
    def get_routing_stats(self) -> Dict:
        """Get statistics on routing decisions"""
        if not self.decision_log:
            return {"total": 0}
        
        by_house = {}
        by_task = {}
        total_confidence = 0
        
        for d in self.decision_log:
            by_house[d.primary_house] = by_house.get(d.primary_house, 0) + 1
            by_task[d.task_type] = by_task.get(d.task_type, 0) + 1
            total_confidence += d.confidence
        
        return {
            "total": len(self.decision_log),
            "by_house": by_house,
            "by_task_type": by_task,
            "avg_confidence": round(total_confidence / len(self.decision_log), 2)
        }


class CrossHouseWorkflow:
    """
    Pre-defined workflows that coordinate across houses.
    
    Implements the canonical flow:
    1. Ezra reads and shapes
    2. Bezalel builds and proves
    3. Timmy reviews and approves
    """
    
    def __init__(self):
        self.router = HouseRouter()
    
    def issue_to_pr_workflow(self, issue_number: int, repo: str) -> Dict:
        """
        Full workflow: Issue → Ezra analysis → Bezalel implementation → Timmy review
        """
        workflow_id = f"issue_{issue_number}"
        
        # Phase 1: Ezra reads and shapes the issue
        ezra_harness = self.router.harnesses[House.EZRA]
        issue_data = ezra_harness.execute("gitea_get_issue", repo=repo, number=issue_number)
        
        if not issue_data.success:
            return {
                "workflow_id": workflow_id,
                "phase": "ezra_read",
                "status": "failed",
                "error": issue_data.error
            }
        
        # Phase 2: Ezra synthesizes approach
        # (Would call LLM here in real implementation)
        approach = {
            "files_to_modify": ["file1.py", "file2.py"],
            "tests_needed": True
        }
        
        # Phase 3: Bezalel implements
        bezalel_harness = self.router.harnesses[House.BEZALEL]
        # Execute implementation plan
        
        # Phase 4: Bezalel proves with tests
        test_result = bezalel_harness.execute("run_tests", repo_path=repo)
        
        # Phase 5: Timmy reviews
        timmy_harness = self.router.harnesses[House.TIMMY]
        review = timmy_harness.review_for_timmy({
            "ezra_analysis": issue_data,
            "bezalel_implementation": test_result
        })
        
        return {
            "workflow_id": workflow_id,
            "status": "complete",
            "phases": {
                "ezra_read": issue_data.success,
                "bezalel_implement": test_result.success,
                "timmy_review": review
            },
            "recommendation": review.get("recommendation", "PENDING")
        }


if __name__ == "__main__":
    print("=" * 60)
    print("HOUSE ROUTER — Three-House Delegation Demo")
    print("=" * 60)
    
    router = HouseRouter()
    
    # Demo routing decisions
    demo_tasks = [
        ("git_status", {"repo_path": "/tmp/timmy-home"}),
        ("git_commit", {"repo_path": "/tmp/timmy-home", "message": "Test"}),
        ("system_info", {}),
        ("health_check", {}),
    ]
    
    print("\n📋 Task Routing Decisions:")
    print("-" * 60)
    
    for tool, params in demo_tasks:
        task_type = router.classify_task(tool, params)
        routing = router.ROUTING_TABLE.get(task_type, {})
        
        print(f"\n  Tool: {tool}")
        print(f"  Task Type: {task_type.value}")
        print(f"  Routed To: {routing.get('house', House.TIMMY).value}")
        print(f"  Confidence: {routing.get('confidence', 0.5)}")
        print(f"  Reasoning: {routing.get('reasoning', 'Default')}")
    
    print("\n" + "=" * 60)
    print("Routing complete.")
