from typing import Literal

from pydantic import BaseModel, Field


class ChatRequest(BaseModel):
    question: str = Field(..., min_length=1, max_length=2000)
    session_id: str | None = None


class Citation(BaseModel):
    record_id: str
    data_category: str
    source_dataset: str
    excerpt: str = ""
    page: int | str | None = None
    confidence: int | None = None
    reason: str | None = None


class InsightMetric(BaseModel):
    label: str
    value: str
    hint: str | None = None
    tone: Literal["neutral", "accent", "danger", "success"] = "neutral"


class InsightTransaction(BaseModel):
    date: str | None = None
    description: str
    amount: str
    direction: Literal["in", "out"] | None = None


class InsightTable(BaseModel):
    headers: list[str]
    rows: list[list[str]]


class StructuredInsight(BaseModel):
    intent: str
    intent_label: str = ""
    headline: str
    summary: str
    metrics: list[InsightMetric] = []
    highlights: list[str] = []
    transactions: list[InsightTransaction] = []
    table: InsightTable | None = None
    footnotes: list[str] = []
    suggestions: list[str] = []


class ChatResponse(BaseModel):
    answer: str
    citations: list[Citation]
    session_id: str | None = None
    log_id: int | None = None
    mode: Literal["conversational", "rag", "pdf", "pdf_overview", "calculator"] = "rag"
    pdf_job_id: str | None = None
    pdf_summary: str | None = None
    finance_intent: str | None = None
    insight: StructuredInsight | None = None
    # empty | no_relevant | found — UI uses this for upload CTA / messaging
    knowledge_state: Literal["empty", "no_relevant", "found"] | None = None
    show_upload_cta: bool = False
    suggestions: list[str] = []
    # general | document | statement — UI badge for answer source
    response_source: Literal["general", "document", "statement"] | None = None


class HealthResponse(BaseModel):
    status: str
    ollama_reachable: bool
    ollama_model: str
    vector_store_ready: bool
    document_count: int | None = None


# ── Feedback ──────────────────────────────────────────────────────────────────

class FeedbackRequest(BaseModel):
    log_id: int | None = None
    session_id: str | None = None
    question: str = Field(..., min_length=1, max_length=4000)
    answer: str = Field(..., min_length=1)
    rating: Literal["up", "down"]
    correction: str | None = Field(default=None, max_length=4000)
    message_id: str | None = Field(default=None, max_length=80)
    mode: str | None = Field(default=None, max_length=40)


class FeedbackResponse(BaseModel):
    feedback_id: int
    message: str
    rating: Literal["up", "down"] | None = None


# ── Admin ─────────────────────────────────────────────────────────────────────

class FeedbackItem(BaseModel):
    id: int
    log_id: int | None = None
    session_id: str | None = None
    question: str
    answer: str
    rating: str
    correction: str | None = None
    reviewed: int = 0
    created_at: str
    org_id: str | None = None
    agent_id: str | None = None
    user_id: str | None = None
    message_id: str | None = None
    mode: str | None = None
    model_name: str | None = None
    updated_at: str | None = None


class AuditItem(BaseModel):
    id: int
    session_id: str | None
    question: str
    answer: str
    citations: str | None
    duration_ms: int | None
    created_at: str


class ConversationSummary(BaseModel):
    id: str
    title: str
    created_at: str | None = None
    last_seen: str | None = None
    message_count: int = 0
    turn_count: int = 0


class ConversationMessage(BaseModel):
    id: int
    question: str
    answer: str
    created_at: str
    duration_ms: int | None = None


class ConversationDetail(BaseModel):
    id: str
    title: str
    messages: list[ConversationMessage]


class ReviewRequest(BaseModel):
    reviewed: Literal[0, 1, 2]  # 0=pending, 1=approved, 2=dismissed


# ── PDF calculation ───────────────────────────────────────────────────────────

class PdfRow(BaseModel):
    description: str = ""
    debit: float | None = None
    credit: float | None = None
    amount: float | None = None
    date: str | None = None
    account: str | None = None
    raw: str = ""


class PdfConfirmRequest(BaseModel):
    rows: list[PdfRow]


class PdfJobResponse(BaseModel):
    job_id: str
    filename: str
    source_type: str
    trusted: bool
    needs_confirm: bool
    confirmed: bool = False
    status: str
    rows: list[PdfRow]
    text_preview: str = ""
    warnings: list[str] = []
    validation: dict = {}
    ocr_used: bool = False
    calculation: dict | None = None
    message: str = ""
