"""Builder workspace - response schemas for hydrate endpoint."""
from __future__ import annotations
from datetime import datetime
from typing import Any, Optional
from uuid import UUID

from pydantic import BaseModel, ConfigDict


class ProjectSummary(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: UUID
    workspace_id: UUID
    name: str
    slug: str
    type: str
    status: str
    created_at: datetime
    project_ref: Optional[str] = None
    live_url: Optional[str] = None
    preview_url: Optional[str] = None
    active_revision_id: Optional[UUID] = None
    active_preview_id: Optional[UUID] = None
    latest_deploy_id: Optional[UUID] = None
    publish_status_summary: Optional[str] = None
    setup_stage: Optional[str] = None
    discovery_status: Optional[str] = None


class PromptMessageSummary(BaseModel):
    id: UUID
    sender_label: str | None = None
    content: str
    context: Optional[dict] = None
    response: Optional[str] = None
    created_at: datetime
    run_id: Optional[UUID] = None
    # Unified run chat (assistant clarifications, etc.) — omitted for legacy prompt-only rows
    role: Optional[str] = None
    message_type: Optional[str] = None
    payload: Optional[dict[str, Any]] = None
    prompt_id: Optional[UUID] = None


class SessionPromptSummary(BaseModel):
    active_session_id: Optional[UUID] = None
    current_prompt_slice: list[PromptMessageSummary]
    last_assistant_response_summary: Optional[str] = None
    linked_run_ids: list[UUID]


class RunSummary(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    selected_run_id: Optional[UUID] = None
    latest_run_id: Optional[UUID] = None
    latest_run_status: Optional[str] = None
    is_terminal: bool = False  # True when status is completed/failed — frontend stops polling
    run_type: Optional[str] = None
    duration_seconds: Optional[float] = None
    error_message: Optional[str] = None
    # When the run blocks on user action (same fields as GET …/runs/{id})
    pending_user_inputs: Optional[dict[str, Any]] = None
    interruption_payload: Optional[dict[str, Any]] = None
    continuation_required: bool = False  # plan approval, clarification, or manifest inputs


class TimelineEventSummary(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: UUID
    event_type: str
    phase: Optional[str] = None
    title: Optional[str] = None
    detail_text: Optional[str] = None
    sequence_no: int
    created_at: datetime


class TimelineSummary(BaseModel):
    latest_events: list[TimelineEventSummary]
    current_phase: Optional[str] = None
    current_activity_label: Optional[str] = None


class ChangedFileSummary(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: UUID
    file_path: str
    change_type: str
    summary: Optional[str] = None
    lines_added: Optional[int] = None
    lines_removed: Optional[int] = None


class ChangesSummary(BaseModel):
    changed_files_count: int
    top_changed_files: list[ChangedFileSummary]
    lines_added: int = 0
    lines_removed: int = 0


class PreviewSummary(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    active_preview_id: Optional[UUID] = None
    preview_status: Optional[str] = None
    # Populated when preview_phase == "ready" (includes "stopped" rows that still resolve)
    preview_url: Optional[str] = None
    preview_source_revision_id: Optional[UUID] = None
    last_refreshed_at: Optional[datetime] = None
    # Drives the frontend UI state machine:
    #   "empty"      – no prompt and no hosted site yet, show onboarding CTA
    #   "generating" – AI codegen in progress, show code animation, hide iframe
    #   "building"   – codegen done or initial hosting still deploying
    #   "ready"      – preview (or bootstrap production URL) live, iframe preview_url
    #   "failed"     – run or preview failed, show error
    preview_phase: str = "empty"


class RouteEntry(BaseModel):
    path: str
    label: str
    type: str = "page"
    is_default: bool = False


class RoutesSummary(BaseModel):
    route_manifest_id: Optional[UUID] = None
    routes: list[RouteEntry]
    default_route: Optional[str] = None


class PublishSummary(BaseModel):
    latest_deploy_id: Optional[UUID] = None
    deploy_status: Optional[str] = None
    live_domain: Optional[str] = None
    generated_domain: Optional[str] = None
    custom_domain_status: Optional[str] = None
    published_revision_id: Optional[UUID] = None
    publish_blockers: list[str] = []  # e.g. "no_deploy", "domain_not_verified"


class CapabilitySummary(BaseModel):
    """One CapabilityProvisioner's status() result (src/domain/capabilities/lifecycle.py)."""

    status: str  # declared | planned | applying | ready | drifted | blocked | shadow | enabled
    reason: Optional[str] = None


class WorkspaceResponse(BaseModel):
    """Full builder workspace hydrate response."""

    project: ProjectSummary
    session_prompt: SessionPromptSummary
    run: RunSummary
    timeline: TimelineSummary
    changes: ChangesSummary
    preview: PreviewSummary
    routes: RoutesSummary
    publish: PublishSummary
    capabilities: dict[str, CapabilitySummary] = {}
    selected_route: Optional[str] = None  # Echo of hydrate query param for client state
    # True when no further async updates are expected — frontend should stop polling workspace
    polling_complete: bool = False
