"""Agent planning and execution models for the GuardianHub system.

This module contains Pydantic models for agent planning, mission execution,
and inter-agent communication within the GuardianHub ecosystem.
"""
import time
from typing import List, Dict, Any, Optional, Literal, Union
from uuid import uuid4
from ..registry.registry import register_model
from ...config.settings import settings


"""Agent planning and execution models for the GuardianHub system.

This module contains Pydantic models for agent planning, mission execution,
and inter-agent communication within the GuardianHub ecosystem.
"""
import time
from typing import List, Dict, Any, Optional, Literal
from uuid import uuid4
from pydantic import BaseModel, Field, ConfigDict,field_validator
from typing import List, Dict, Any, Optional
from datetime import datetime


# =============================================================================
# Core Planning Models
# =============================================================================

# =============================================================================
# Unified Workflow Spine
# =============================================================================
class SchemaKeyValuePair(BaseModel):
    """Gemini-safe way to handle dynamic arguments."""
    model_config = ConfigDict(extra='forbid')
    key: str
    value: str


@register_model
class SovereignStep(BaseModel):
    """
    THE ONE MODEL:
    The universal contract for Intent (Architect), Storage (DB), and Action (Muscle).
    """
    model_config = ConfigDict(
        populate_by_name=True,
        extra='ignore',
        arbitrary_types_allowed=True
    )

    # 1. Identity
    step_id: str = Field(default_factory=lambda: f"step_{uuid4().hex[:4]}")
    step_name: str = Field(..., description="Human name of the operation.")

    # 2. Dynamic Routing (Aliases ensure tool_name/action_name symmetry)
    tool_name: str = Field(..., alias="action_name", description="The tool or semantic blueprint ID.")

    # 3. Arguments (The Bridge: List[KV] for LLM -> Dict for Code)
    tool_args: Dict[str, Any] = Field(
        default_factory=dict,
        alias="action_input",
        description="Execution arguments."
    )

    # 4. Contextual Metadata
    dependencies: List[str] = Field(default_factory=list)
    status: str = "pending"
    session_id: Optional[str] = None
    agent_name: Optional[str] = None
    is_dry_run: bool = False

    @field_validator('tool_args', mode='before')
    @classmethod
    def dharma_normalization(cls, v: Any) -> Dict[str, Any]:
        """
        🚀 THE DHARMA GATE:
        If LLM sends [{'key': 'k', 'value': 'v'}], we flatten it.
        If it's already a Dict, we let it pass.
        """
        if isinstance(v, list):
            return {
                (item.get('key') if isinstance(item, dict) else item.key):
                    (item.get('value') if isinstance(item, dict) else item.value)
                for item in v
            }
        return v or {}

# =============================================================================
# Mission Wrappers
# =============================================================================



@register_model
class MacroPlan(BaseModel):
    # 🎯 FIX: Allow extra fields to prevent validation errors with step data

    model_config = ConfigDict(extra='allow')


    confidence_score: float = Field(default=0.0, description="Confidence score")
    # Fixed metadata fields instead of dynamic dict
    reflection: str = Field(default="", description="The Architect's reasoning for this plan")

    metadata: List[SchemaKeyValuePair] = Field(default_factory=list)
    steps: List[SovereignStep] = Field(default_factory=list)


class MacroPlanResponse(BaseModel):
    """Response model for the LLM's planning output."""
    plan: List[SovereignStep] = Field(
        default_factory=list,
        description="List of plan steps"
    )
    reflection: Optional[str] = Field(
        default="",
        description="Reasoning behind the plan"
    )


class MissionRequest(BaseModel):
    # 🎯 Data validation logic
    model_config = ConfigDict(populate_by_name=True, arbitrary_types_allowed=True)

    session_id: str
    trace_id: Optional[str] = None
    agent_name: str = "specialist"
    is_dry_run: bool = False
    template_id: str = "NO_TEMPLATE_ID"
    sub_objective: str = "NO_SUB_OBJECTIVE"
    assigned_mission_intent: str= "NO_MISSION_ASSIGNED"
    active_template_id: str = "NO_TEMPLATE_ID"
    mission_dna: str = "Audit Only"
    callback_url: str = settings.endpoints.SUTRAM_CALLBACK_URL
    history_limit: int = 5
    min_success_score: float = 0.7
    risk_threshold: float = 0.7

    # 🚀 The Core Fix: MacroPlan is now a proper model, not just a list
    macro_plan: MacroPlan

    metadata: Dict[str, Any] = Field(default_factory=dict)
    debug_mode: bool = True

    @field_validator('macro_plan')
    @classmethod
    def must_have_steps(cls, v: MacroPlan) -> MacroPlan:
        if not v.steps or len(v.steps) == 0:
            raise ValueError("Mission rejected: Sutram provided an empty MacroPlan.")
        return v

        # 🚀 ADD THIS PROPERTY HERE
    @property
    def technical_context(self) -> Dict[str, Any]:
        """Provides a unified bundle for activity arguments."""
        return {
            "session_id": self.session_id,
            "trace_id": self.trace_id,
            "template_id": self.active_template_id,
            "agent_name": self.agent_name,
            "is_dry_run": self.is_dry_run
        }

