"""Pydantic schemas for FlowPilot AI sessions."""
from __future__ import annotations

from typing import Optional, Any
from uuid import UUID
from datetime import datetime

from pydantic import BaseModel, Field


# ── Intake ──

class AISessionCreateRequest(BaseModel):
    """Start a new FlowPilot or chat session."""
    session_type: str = Field(
        "guided",
        pattern="^(guided|chat)$",
        description="Session type: guided (FlowPilot) or chat (assistant)",
    )
    intake_type: str = Field(
        "free_text",
        pattern="^(free_text|psa_ticket|screenshot|log_paste|combined)$",
    )
    intake_content: dict[str, Any] = Field(
        ...,
        description=(
            "Intake payload. Shape depends on intake_type: "
            "{text: str} for free_text, "
            "{text?: str, image_urls?: list[str]} for screenshot, "
            "{text?: str, log_content?: str} for log_paste, "
            "{ticket_id: str, psa_connection_id: str} for psa_ticket, "
            "any combination for combined."
        ),
    )
    psa_ticket_id: Optional[str] = None
    psa_connection_id: Optional[UUID] = None


class AISessionCreateResponse(BaseModel):
    """Response after starting a session — includes the first FlowPilot step."""
    session_id: UUID
    status: str
    confidence_tier: str
    problem_summary: str | None = None
    problem_domain: str | None = None
    matched_flow_id: UUID | None = None
    matched_flow_name: str | None = None
    match_score: float | None = None
    first_step: AISessionStepResponse
    psa_context_status: str | None = None  # loaded | unavailable | None (no PSA)


# ── Step interaction ──

class StepOptionSchema(BaseModel):
    """A selectable option presented to the engineer."""
    label: str
    value: str
    followup_hint: str | None = None


class AISessionStepResponse(BaseModel):
    """A FlowPilot step rendered in the session UI."""
    step_id: UUID
    step_order: int
    step_type: str
    content: dict[str, Any]
    context_message: str | None = None
    options: list[StepOptionSchema] = []
    allow_free_text: bool = True
    allow_skip: bool = True
    confidence_tier: str
    confidence_score: float

    model_config = {"from_attributes": True}


class StepResponseRequest(BaseModel):
    """Engineer's response to a FlowPilot step."""
    selected_option: str | None = None
    free_text_input: str | None = None
    was_skipped: bool = False
    action_result: dict[str, Any] | None = None


class StepResponseResponse(BaseModel):
    """FlowPilot's next step after processing the engineer's response."""
    session_id: UUID
    status: str
    confidence_tier: str
    confidence_score: float
    next_step: AISessionStepResponse | None = None
    resolution_suggested: bool = False
    resolution_summary: str | None = None


# ── Resolution / Escalation ──

class ResolveSessionRequest(BaseModel):
    """Close a session as resolved."""
    resolution_summary: str = Field(..., min_length=5, max_length=2000)
    resolution_action: str | None = None
    session_rating: int | None = Field(None, ge=1, le=5)
    session_feedback: str | None = None


class EscalateSessionRequest(BaseModel):
    """Escalate a session to another engineer."""
    escalation_reason: str = Field(..., min_length=5, max_length=2000)
    escalated_to_id: UUID | None = None


class DocumentationStep(BaseModel):
    """A step in the documentation trail."""
    step_number: int
    step_type: str
    description: str
    engineer_response: str | None = None
    outcome: str | None = None


class SessionDocumentation(BaseModel):
    """Auto-generated session documentation."""
    problem_summary: str
    problem_domain: str | None = None
    intake_summary: str
    diagnostic_steps: list[DocumentationStep]
    resolution_summary: str | None = None
    escalation_reason: str | None = None
    follow_up_recommendations: list[str] = []
    total_steps: int
    duration_display: str | None = None
    generated_at: datetime


class SessionCloseResponse(BaseModel):
    """Response after resolving or escalating."""
    session_id: UUID
    status: str
    documentation: SessionDocumentation | None = None
    psa_push_status: str = "no_psa"  # sent | pending_retry | no_psa | failed
    psa_push_error: str | None = None
    member_mapping_warning: str | None = None


class StatusUpdateRequest(BaseModel):
    """Generate a mid-session or post-session status update."""
    audience: str = Field(
        ...,
        pattern="^(ticket_notes|client_update|email_draft|request_info)$",
        description="Who is this update for?",
    )
    length: str = Field(
        "detailed",
        pattern="^(quick|detailed)$",
        description="Quick (1-2 sentences) or detailed breakdown",
    )
    context: str = Field(
        "status",
        pattern="^(status|resolution|escalation)$",
        description="What type of communication: mid-session status, resolution close-out, or escalation handoff",
    )


class StatusUpdateResponse(BaseModel):
    """Generated status update content."""
    content: str
    audience: str
    length: str
    context: str
    session_status: str
    steps_completed: int
    time_spent_display: str | None = None
    client_name: str | None = None
    generated_at: datetime


class RateSessionRequest(BaseModel):
    """Submit post-session rating."""
    rating: int = Field(..., ge=1, le=5)
    feedback: str | None = None


class PickupSessionRequest(BaseModel):
    """Pick up an escalated session as a new engineer."""
    resume_mode: str = Field("continue", pattern="^(continue|fresh)$")
    additional_context: str | None = None


class LinkTicketRequest(BaseModel):
    """Link a PSA ticket to an in-progress session."""
    psa_ticket_id: str
    psa_connection_id: UUID


# ── List / Detail ──

class AISessionSummary(BaseModel):
    """Compact session for list views."""
    id: UUID
    session_type: str = "guided"
    title: str | None = None
    status: str
    intake_type: str
    problem_summary: str | None = None
    problem_domain: str | None = None
    confidence_tier: str
    step_count: int
    session_rating: int | None = None
    psa_ticket_id: str | None = None
    escalation_reason: str | None = None
    created_at: datetime
    resolved_at: datetime | None = None

    model_config = {"from_attributes": True}


class AISessionDetail(AISessionSummary):
    """Full session detail with steps (guided) or messages (chat)."""
    intake_content: dict[str, Any]
    matched_flow_id: UUID | None = None
    match_score: float | None = None
    resolution_summary: str | None = None
    resolution_action: str | None = None
    escalation_reason: str | None = None
    session_feedback: str | None = None
    psa_ticket_id: str | None = None
    psa_connection_id: UUID | None = None
    ticket_data: dict[str, Any] | None = None
    steps: list[AISessionStepResponse] = []
    conversation_messages: list[dict[str, Any]] = []  # Chat sessions store messages here
    pending_task_lane: dict[str, Any] | None = None
    is_branching: bool = False
    active_branch_id: str | None = None

    model_config = {"from_attributes": True}


# ── Chat session ──

class ChatSessionCreateResponse(BaseModel):
    """Response after creating a chat session on ai_sessions."""
    session_id: UUID
    session_type: str = "chat"
    title: str
    status: str = "active"


class ChatMessageRequest(BaseModel):
    """Send a message in a chat session."""
    message: str = Field(..., min_length=1, max_length=8000)
    upload_ids: list[UUID] = Field(default_factory=list, max_length=10)


class ForkBranchInfo(BaseModel):
    """Branch info returned when a fork is created."""
    branch_id: str
    label: str


class ForkMetadata(BaseModel):
    """Metadata returned when the AI suggests a diagnostic fork."""
    fork_point_id: str
    fork_reason: str
    branches: list[ForkBranchInfo]
    active_branch_id: str


class ActionItem(BaseModel):
    """A single action item for the engineer."""
    label: str
    command: str | None = None
    description: str = ""


class QuestionItem(BaseModel):
    """A question the AI needs answered by the engineer."""
    text: str
    context: str = ""


class ChatMessageResponse(BaseModel):
    """AI response to a chat message."""
    content: str
    suggested_flows: list[dict[str, Any]] = []
    fork: ForkMetadata | None = None
    actions: list[ActionItem] | None = None
    questions: list[QuestionItem] | None = None


class SaveTaskLaneRequest(BaseModel):
    """Save the full task lane state (AI items + user responses)."""
    questions: list[QuestionItem] = Field(default_factory=list, max_length=50)
    actions: list[ActionItem] = Field(default_factory=list, max_length=50)
    responses: list[dict[str, Any]] = Field(
        default_factory=list,
        max_length=100,
        description="User's in-progress task responses with state/value",
    )


class AISessionSearchResult(BaseModel):
    """Lightweight session result for Command Palette / autocomplete."""
    id: UUID
    problem_summary: str | None = None
    problem_domain: str | None = None
    status: str
    created_at: datetime

    model_config = {"from_attributes": True}
