"""Pydantic models for Document validation."""

from typing import Any, Dict, List, Optional

from pydantic import Field, field_validator

from .base import ToothFairyModel
from .enums import DocumentType
from .validators import validate_top_k


class DocumentCreateModel(ToothFairyModel):
    user_id: str = Field(..., min_length=1)
    title: str = Field(..., min_length=1, max_length=500)
    doc_type: DocumentType = Field(default="readComprehensionFile")
    topics: List[str] = Field(default_factory=list)
    folder_id: str = Field(default="mrcRoot")
    external_path: str = ""
    source: str = ""
    status: str = Field(default="published")
    scope: Optional[str] = None

    @field_validator("external_path")
    @classmethod
    def validate_external_path(cls, v: str, info) -> str:
        doc_type = info.data.get("doc_type")
        if doc_type == "readComprehensionUrl" and v:
            if not v.startswith(("http://", "https://")):
                raise ValueError("external_path must be a valid URL for readComprehensionUrl type")
        return v

    def to_api_payload(self) -> Dict[str, Any]:
        payload: Dict[str, Any] = {
            "data": [
                {
                    "userid": self.user_id,
                    "title": self.title,
                    "type": self.doc_type,
                    "topics": self.topics,
                    "folderid": self.folder_id,
                    "external_path": self.external_path,
                    "source": self.source,
                    "status": self.status,
                }
            ]
        }
        if self.scope is not None:
            payload["data"][0]["scope"] = self.scope
        return payload


class DocumentUpdateModel(ToothFairyModel):
    user_id: str = Field(..., min_length=1)
    title: Optional[str] = Field(default=None, min_length=1, max_length=500)
    topics: Optional[List[str]] = None
    folder_id: Optional[str] = None
    status: Optional[str] = None
    scope: Optional[str] = None

    def to_api_payload(self, document_id: str) -> Dict[str, Any]:
        fields: Dict[str, Any] = {}
        if self.title is not None:
            fields["title"] = self.title
        if self.topics is not None:
            fields["topics"] = self.topics
        if self.folder_id is not None:
            fields["folderid"] = self.folder_id
        if self.status is not None:
            fields["status"] = self.status
        if self.scope is not None:
            fields["scope"] = self.scope

        return {
            "id": document_id,
            "userid": self.user_id,
            "fields": fields,
        }


class DocumentSearchModel(ToothFairyModel):
    text: str = Field(..., min_length=1)
    top_k: int = Field(default=10, ge=1, le=50)
    metadata: Optional[Dict[str, Any]] = None

    _validate_top_k = field_validator("top_k")(validate_top_k)

    def to_api_payload(self) -> Dict[str, Any]:
        payload: Dict[str, Any] = {
            "text": self.text,
            "topK": self.top_k,
        }
        if self.metadata is not None:
            payload["metadata"] = self.metadata
        return payload


class FileUploadModel(ToothFairyModel):
    file_path: str = Field(..., min_length=1)
    folder_id: str = Field(default="mrcRoot")

    @field_validator("file_path")
    @classmethod
    def validate_file_path(cls, v: str) -> str:
        import os
        if not os.path.exists(v):
            raise ValueError(f"File not found: {v}")
        return v

    def to_api_payload(self) -> Dict[str, Any]:
        return {
            "folder_id": self.folder_id,
        }


class Base64UploadModel(ToothFairyModel):
    base64_data: str = Field(..., min_length=1)
    filename: str = Field(..., min_length=1)
    content_type: str = Field(..., min_length=1)
    folder_id: str = Field(default="mrcRoot")

    @field_validator("base64_data")
    @classmethod
    def validate_base64(cls, v: str) -> str:
        import base64
        try:
            base64.b64decode(v)
        except Exception as e:
            raise ValueError(f"Invalid base64 data: {e}")
        return v

    @field_validator("content_type")
    @classmethod
    def validate_content_type(cls, v: str) -> str:
        valid_types = [
            "application/pdf",
            "text/plain",
            "text/html",
            "text/markdown",
            "application/json",
            "application/xml",
            "text/csv",
            "application/msword",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        ]
        if v and not any(v.startswith(t) for t in valid_types):
            pass
        return v

    def to_api_payload(self) -> Dict[str, Any]:
        return {
            "folder_id": self.folder_id,
        }