"""Pydantic models for Whisper Scribe."""

from pydantic import BaseModel
from enum import Enum
from typing import Optional, List, Dict
from datetime import datetime


class JobStatus(str, Enum):
    """Status of a transcription job."""
    PENDING = "pending"
    FETCHING_INFO = "fetching_info"
    DOWNLOADING = "downloading"
    CONVERTING = "converting"
    TRANSCRIBING = "transcribing"
    SAVING = "saving"
    COMPLETE = "complete"
    ERROR = "error"


class ExportFormat(str, Enum):
    """Available export formats."""
    TXT = "txt"
    SRT = "srt"
    VTT = "vtt"
    PDF = "pdf"
    MD = "md"


# Request/Response Models
class VideoPreviewRequest(BaseModel):
    url: str


class VideoPreview(BaseModel):
    url: str
    video_id: str
    title: str
    thumbnail: str
    duration: str
    channel: str


class TranscribeRequest(BaseModel):
    url: str


class QueueRequest(BaseModel):
    urls: List[str]


class TranscribeResponse(BaseModel):
    job_id: str
    status: JobStatus


class StatusResponse(BaseModel):
    status: JobStatus
    progress: int = 0
    message: Optional[str] = None
    stage: Optional[str] = None


class ResultResponse(BaseModel):
    text: str
    title: str
    file_path: Optional[str] = None
    language: Optional[str] = None
    text_direction: Optional[str] = None  # "rtl" or "ltr"


class CostEntry(BaseModel):
    """Single cost entry for an operation."""
    operation: str  # "transcription", "analysis", "qa", "resources"
    provider: str
    model: str
    cost_usd: float
    timestamp: str
    # Optional fields depending on operation type
    duration_seconds: Optional[float] = None  # For transcription
    input_tokens: Optional[int] = None  # For chat
    output_tokens: Optional[int] = None  # For chat
    total_tokens: Optional[int] = None  # For chat


class ItemCosts(BaseModel):
    """All costs associated with a history item."""
    entries: List[CostEntry] = []
    total_cost: float = 0.0


class QAEntry(BaseModel):
    """Single Q&A exchange."""
    question: str
    answer: str
    timestamp: str
    cost_info: Optional[CostEntry] = None
    references: Optional[dict] = None


class ProviderAnalysis(BaseModel):
    """Analysis result from a specific provider."""
    content: dict  # The analysis content (analysis text, topics, etc.)
    provider: str  # Provider name (openai, anthropic, google, etc.)
    timestamp: str  # When this analysis was performed
    cost_info: Optional[CostEntry] = None


class AnalysisCollection(BaseModel):
    """Collection of analyses from different providers."""
    analyses: Dict[str, ProviderAnalysis] = {}  # Keyed by provider name
    primary_provider: Optional[str] = None  # Which provider's analysis to show by default


class HistoryItem(BaseModel):
    id: str
    title: str
    url: str
    created_at: str
    file_path: str
    duration: Optional[str] = None
    thumbnail: Optional[str] = None
    language: Optional[str] = None
    text_direction: Optional[str] = None  # "rtl" or "ltr"


class FullHistoryItem(BaseModel):
    """Extended history item with all persisted data."""
    id: str
    title: str
    url: str
    created_at: str
    file_path: str
    duration: Optional[str] = None
    thumbnail: Optional[str] = None
    language: Optional[str] = None
    text_direction: Optional[str] = None  # "rtl" or "ltr"
    # Persisted data
    transcription: Optional[str] = None
    analysis: Optional[dict] = None
    qa_history: List[QAEntry] = []
    resources: Optional[dict] = None
    costs: ItemCosts = ItemCosts()
    topics: List[str] = []


class HistoryResponse(BaseModel):
    items: List[HistoryItem]
    total: int


class ExportRequest(BaseModel):
    format: ExportFormat


class QueueStatusResponse(BaseModel):
    queue: List[dict]
    current_job: Optional[str] = None
    total: int
    completed: int


class SettingsRequest(BaseModel):
    # API Keys
    openai_api_key: Optional[str] = None
    perplexity_api_key: Optional[str] = None
    anthropic_api_key: Optional[str] = None
    eden_api_key: Optional[str] = None
    # Provider selection
    transcription_provider: Optional[str] = None  # openai, eden
    analysis_provider: Optional[str] = None  # openai, anthropic, eden
    critique_provider: Optional[str] = None  # anthropic, openai, eden
    resources_provider: Optional[str] = None  # perplexity, eden
    # Output
    output_directory: Optional[str] = None


class SettingsResponse(BaseModel):
    # API Keys status
    openai_api_key_set: bool
    perplexity_api_key_set: bool
    anthropic_api_key_set: bool = False
    eden_api_key_set: bool = False
    # Provider selection
    transcription_provider: str = "openai"
    analysis_provider: str = "openai"
    critique_provider: str = "anthropic"
    resources_provider: str = "perplexity"
    # Output
    output_directory: str


class ValidateKeyResponse(BaseModel):
    valid: bool
    message: str


class UploadResponse(BaseModel):
    job_id: str
    status: JobStatus
    filename: str


class PlaylistVideo(BaseModel):
    video_id: str
    title: str
    thumbnail: Optional[str] = None
    duration: str
    url: str


class PlaylistPreview(BaseModel):
    playlist_id: str
    title: str
    channel: str
    video_count: int
    videos: List[PlaylistVideo]


class PlaylistRequest(BaseModel):
    url: str


class QARequest(BaseModel):
    question: str
    find_references: bool = True


class QAResponse(BaseModel):
    question: str
    transcription_answer: Optional[dict] = None
    references: Optional[dict] = None
    combined_analysis: Optional[str] = None
    references_error: Optional[str] = None


class CustomPromptAnalysisRequest(BaseModel):
    prompt_id: Optional[str] = None
    prompt_text: Optional[str] = None


class BookReferencesRequest(BaseModel):
    topic: str


# =============================================================================
# Project/Knowledge Repository Models (v3)
# =============================================================================

class EntityModel(BaseModel):
    """Entity extracted from transcription."""
    id: str
    name: str
    type: str  # person, organization, technology, product, place, concept
    description: str = ""
    mentions: List[dict] = []  # [{timestamp, context}]
    wikipedia_url: Optional[str] = None
    confidence: float = 1.0


class ExtractedEntitiesModel(BaseModel):
    """Collection of extracted entities by type."""
    people: List[EntityModel] = []
    organizations: List[EntityModel] = []
    technologies: List[EntityModel] = []
    products: List[EntityModel] = []
    places: List[EntityModel] = []
    concepts: List[EntityModel] = []


class InsightModel(BaseModel):
    """Extracted insight or key takeaway."""
    id: str
    content: str
    category: str  # takeaway, aha, wisdom, action, warning, definition
    confidence: float = 1.0
    source_timestamp: Optional[float] = None


class QuoteModel(BaseModel):
    """Notable quote from video."""
    id: str
    text: str
    speaker: Optional[str] = None
    timestamp: float = 0.0
    context: str = ""


class FactModel(BaseModel):
    """Extracted fact or statistic."""
    id: str
    statement: str
    category: str  # statistic, definition, claim, date, comparison
    confidence: float = 1.0
    source_timestamp: float = 0.0
    source: Optional[str] = None


class SemanticSectionModel(BaseModel):
    """Semantic section of transcription."""
    id: str
    title: str
    content: str
    start_time: float
    end_time: float
    topics: List[str] = []
    summary: str = ""


class PersonalNoteModel(BaseModel):
    """Personal note from user."""
    id: str
    content: str
    timestamp: Optional[float] = None
    created_at: str
    updated_at: str
    tags: List[str] = []


class VideoConnectionModel(BaseModel):
    """Connection to another video."""
    video_id: str
    title: str
    similarity_score: float = 0.0
    shared_topics: List[str] = []
    shared_entities: List[str] = []


class ProjectDataModel(BaseModel):
    """Complete project data for a video (v3 format)."""
    # Core identification
    video_id: str
    title: str
    url: str
    channel: str = ""
    duration: int = 0
    thumbnail: str = ""
    file_path: str = ""

    # Transcription
    transcription: str = ""
    language: str = ""
    text_direction: str = "ltr"

    # Semantic sections
    sections: List[SemanticSectionModel] = []

    # Extracted data
    entities: ExtractedEntitiesModel = ExtractedEntitiesModel()
    insights: List[InsightModel] = []
    quotes: List[QuoteModel] = []
    facts: List[FactModel] = []

    # AI Analysis
    analyses: Dict[str, dict] = {}
    primary_analysis_provider: Optional[str] = None

    # Personal data
    notes: List[PersonalNoteModel] = []
    is_starred: bool = False
    tags: List[str] = []

    # Connections
    connections: List[VideoConnectionModel] = []
    shared_topics: List[str] = []

    # Q&A history
    qa_history: List[QAEntry] = []

    # Resources
    resources: Optional[dict] = None

    # Costs
    costs: ItemCosts = ItemCosts()

    # Metadata
    created_at: str = ""
    processed_at: str = ""
    last_accessed: str = ""
    extraction_status: str = "pending"


class ProjectSummaryModel(BaseModel):
    """Summary of a project for list views."""
    video_id: str
    title: str
    url: str
    channel: str = ""
    duration: int = 0
    thumbnail: str = ""
    is_starred: bool = False
    tags: List[str] = []
    created_at: str = ""
    extraction_status: str = "pending"
    insight_count: int = 0
    entity_count: int = 0
    note_count: int = 0


class ProjectListResponse(BaseModel):
    """Response for project list."""
    projects: List[ProjectSummaryModel]
    total: int


class DashboardStatsModel(BaseModel):
    """Dashboard statistics."""
    total_videos: int = 0
    total_insights: int = 0
    total_entities: int = 0
    total_notes: int = 0
    total_quotes: int = 0
    total_facts: int = 0
    total_topics: int = 0
    total_watch_time_seconds: int = 0
    total_watch_time_formatted: str = "0m"
    # Extraction status
    extracted_count: int = 0
    processing_count: int = 0
    pending_count: int = 0
    # Content metrics
    starred_count: int = 0
    total_connections: int = 0
    # Duration breakdown
    short_videos: int = 0      # < 5 min
    medium_videos: int = 0     # 5-15 min
    long_videos: int = 0       # 15-60 min
    very_long_videos: int = 0  # 60+ min


class ActivityModel(BaseModel):
    """Activity item for activity feed."""
    type: str  # video_added, note_added, extraction_complete, etc.
    video_id: str
    title: str
    timestamp: str
    details: dict = {}


class ActivityFeedResponse(BaseModel):
    """Response for activity feed."""
    activities: List[ActivityModel]


class AddNoteRequest(BaseModel):
    """Request to add a note."""
    content: str
    timestamp: Optional[float] = None
    tags: List[str] = []


class UpdateNoteRequest(BaseModel):
    """Request to update a note."""
    content: str
    tags: Optional[List[str]] = None


class UpdateTagsRequest(BaseModel):
    """Request to update project tags."""
    tags: List[str]


class ExtractRequest(BaseModel):
    """Request to run extraction pipeline."""
    extract_entities: bool = True
    extract_insights: bool = True
    extract_quotes: bool = True
    extract_facts: bool = True
    extract_sections: bool = True


class SearchRequest(BaseModel):
    """Request for AI-powered search."""
    query: str
    limit: int = 10


class SearchResultModel(BaseModel):
    """Single search result."""
    video_id: str
    title: str
    relevance_score: float
    matched_sections: List[dict] = []  # [{section_id, title, content_preview, timestamp}]
    matched_insights: List[str] = []


class SearchResponse(BaseModel):
    """Response for AI search."""
    query: str
    answer: Optional[str] = None  # AI-generated answer
    results: List[SearchResultModel] = []
    total_results: int = 0


# Knowledge Graph Models
class GraphNodeModel(BaseModel):
    """Node in knowledge graph."""
    id: str
    type: str  # video, topic, entity, person
    label: str
    metadata: dict = {}


class GraphEdgeModel(BaseModel):
    """Edge in knowledge graph."""
    source: str
    target: str
    type: str  # mentions, related_to, part_of
    weight: float = 1.0


class KnowledgeGraphModel(BaseModel):
    """Complete knowledge graph."""
    nodes: List[GraphNodeModel] = []
    edges: List[GraphEdgeModel] = []


class TopicModel(BaseModel):
    """Topic with associated videos."""
    name: str
    video_count: int = 0
    insight_count: int = 0
    entity_count: int = 0
    videos: List[str] = []  # video_ids


class TopicsResponse(BaseModel):
    """Response for topics list."""
    topics: List[TopicModel]
    total: int


class JournalEntryModel(BaseModel):
    """Entry in learning journal."""
    date: str
    entries: List[ActivityModel] = []


class JournalResponse(BaseModel):
    """Response for learning journal."""
    entries: List[JournalEntryModel]
