from __future__ import annotations

from enum import Enum
from typing import Any, Literal

from pydantic import BaseModel, ConfigDict, Field


class Scenario(str, Enum):
    EXPLAIN_PART = "explain_part"
    ANALYTICS_REVIEW = "analytics_review"
    DOCS_FROM_ANALYTICS = "docs_from_analytics"
    TARGETED_EDIT = "targeted_edit"
    GHERKIN_MODEL = "gherkin_model"
    GENERAL_QA = "general_qa"


class AttachmentRef(BaseModel):
    model_config = ConfigDict(extra="forbid")

    type: Literal["confluence_url", "http_url", "file_ref"]
    value: str


class FileRef(BaseModel):
    model_config = ConfigDict(extra="forbid")

    path: str
    content: str = ""
    content_hash: str = ""


class RoutingMeta(BaseModel):
    model_config = ConfigDict(extra="forbid")

    domain_id: str
    process_id: str
    confidence: float = Field(ge=0.0, le=1.0)
    reason: str = ""
    fallback_used: bool = False


class SourcePolicy(BaseModel):
    model_config = ConfigDict(extra="forbid")

    priority: list[Literal["requirements", "tech_docs", "code", "external_doc"]] = Field(
        default_factory=lambda: ["requirements", "tech_docs", "code"]
    )
    require_evidence: bool = True
    max_sources_per_step: int = 12


class TaskConstraints(BaseModel):
    model_config = ConfigDict(extra="forbid")

    allow_writes: bool = False
    max_steps: int = 20
    max_retries_per_step: int = 2
    step_timeout_sec: int = 120
    target_paths: list[str] = Field(default_factory=list)


class OutputSection(BaseModel):
    model_config = ConfigDict(extra="forbid")

    name: str
    format: Literal["markdown", "mermaid", "gherkin", "json", "changeset"]
    required: bool = True


class OutputContract(BaseModel):
    model_config = ConfigDict(extra="forbid")

    result_type: Literal["answer", "changeset", "review_report", "doc_bundle", "gherkin_bundle"]
    sections: list[OutputSection] = Field(default_factory=list)


class TaskSpec(BaseModel):
    model_config = ConfigDict(extra="forbid")

    task_id: str
    dialog_session_id: str
    rag_session_id: str
    mode: str = "auto"
    user_message: str
    scenario: Scenario
    routing: RoutingMeta
    attachments: list[AttachmentRef] = Field(default_factory=list)
    files: list[FileRef] = Field(default_factory=list)
    source_policy: SourcePolicy = Field(default_factory=SourcePolicy)
    constraints: TaskConstraints = Field(default_factory=TaskConstraints)
    output_contract: OutputContract
    metadata: dict[str, Any] = Field(default_factory=dict)
