from datetime import datetime
from typing import Optional, Any, Literal
from uuid import UUID
from pydantic import BaseModel, Field, validator

SessionOutcome = Literal["resolved", "escalated", "workaround", "unresolved"]


class CustomStepSchema(BaseModel):
    """Enhanced custom step with source tracking.

    Backward compatible: old sessions without new fields load with defaults.
    """
    type: str  # "decision" | "action" | "solution"
    content: str
    notes: Optional[str] = None

    # Source tracking (new fields, optional for backward compatibility)
    source: Literal["ad-hoc", "step-library", "forked-tree"] = "ad-hoc"
    source_step_id: Optional[UUID] = None
    inserted_at: Optional[datetime] = None
    inserted_after_node_id: Optional[str] = None


class DecisionRecord(BaseModel):
    node_id: str
    question: Optional[str] = None
    answer: Optional[str] = None
    action_performed: Optional[str] = None
    notes: Optional[str] = None
    command_output: Optional[str] = Field(None, max_length=10000)
    automation_used: Optional[bool] = False
    timestamp: datetime
    entered_at: Optional[datetime] = None
    exited_at: Optional[datetime] = None
    duration_seconds: Optional[int] = Field(None, ge=0)
    attachments: list[str] = Field(default_factory=list)


class SessionCreate(BaseModel):
    tree_id: UUID
    ticket_number: Optional[str] = Field(None, max_length=100)
    client_name: Optional[str] = Field(None, max_length=255)
    session_variables: Optional[dict[str, str]] = Field(None, description="Intake form values for procedural flows")


class SessionUpdate(BaseModel):
    path_taken: Optional[list[str]] = None
    decisions: Optional[list[DecisionRecord]] = None
    custom_steps: Optional[list[CustomStepSchema]] = None
    ticket_number: Optional[str] = Field(None, max_length=100)
    client_name: Optional[str] = Field(None, max_length=255)
    scratchpad: Optional[str] = None
    next_steps: Optional[str] = None
    session_variables: Optional[dict[str, str]] = None


class SessionResponse(BaseModel):
    id: UUID
    tree_id: UUID
    user_id: UUID
    tree_snapshot: dict[str, Any]
    path_taken: list[str]
    decisions: list[dict[str, Any]]
    custom_steps: list[dict[str, Any]] = Field(default_factory=list)
    started_at: datetime
    completed_at: Optional[datetime] = None
    outcome: Optional[SessionOutcome] = None
    outcome_notes: Optional[str] = None
    next_steps: str = ""
    ticket_number: Optional[str] = None
    client_name: Optional[str] = None
    exported: bool
    scratchpad: str = ""
    session_variables: dict[str, str] = Field(default_factory=dict)

    @validator('scratchpad', 'next_steps', pre=True, always=True)
    def normalize_text_fields(cls, v):
        return v or ""

    batch_id: Optional[UUID] = None
    target_label: Optional[str] = None

    class Config:
        from_attributes = True


class SessionExport(BaseModel):
    format: str = Field(default="markdown", pattern="^(text|markdown|html|psa)$")
    include_timestamps: bool = True
    include_tree_info: bool = True
    # Phase A
    include_outcome_notes: bool = True
    include_next_steps: bool = True
    max_step_index: Optional[int] = Field(None, ge=1, description="1-based inclusive step cutoff")
    # Phase B
    include_summary: bool = False
    detail_level: Literal["standard", "full"] = "standard"
    # Phase C
    redaction_mode: Literal["none", "mask"] = "none"


class SessionComplete(BaseModel):
    outcome: SessionOutcome
    outcome_notes: Optional[str] = None
    next_steps: Optional[str] = None


class ScratchpadUpdate(BaseModel):
    scratchpad: str


class SaveAsTreeRequest(BaseModel):
    """Request to save a session as a tree."""
    tree_name: Optional[str] = Field(None, max_length=255, description="Custom name for the saved tree (auto-generated if not provided)")
    description: Optional[str] = Field(None, description="Description for the saved tree")
    status: Literal["draft", "published"] = Field("draft", description="Status of the saved tree")


class SaveAsTreeResponse(BaseModel):
    """Response after saving a session as a tree."""
    tree_id: UUID
    tree_name: str
    message: str
