"""
Data models for GetBiji API responses.

All models use dataclasses for clean, type-safe representations of API data.
"""

from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional


@dataclass
class Tag:
    """Tag associated with a note."""

    id: str
    name: str
    type: str
    tag_type: str

    @classmethod
    def from_dict(cls, data: dict) -> "Tag":
        """Create Tag from API response dict."""
        return cls(
            id=data.get("id", ""),
            name=data.get("name", ""),
            type=data.get("type", ""),
            tag_type=data.get("tag_type", ""),
        )


@dataclass
class Attachment:
    """Attachment in a note (link, audio, video, etc.)."""

    type: str
    url: str
    title: Optional[str] = None
    duration: Optional[int] = None  # Duration in milliseconds for audio/video
    size: Optional[int] = None  # Size in bytes
    path: Optional[str] = None  # OSS path

    @classmethod
    def from_dict(cls, data: dict) -> "Attachment":
        """Create Attachment from API response dict."""
        return cls(
            type=data.get("type", ""),
            url=data.get("url", ""),
            title=data.get("title"),
            duration=data.get("duration"),
            size=data.get("size"),
            path=data.get("path"),
        )


@dataclass
class Note:
    """
    Note object representing a GetBiji note.

    Attributes:
        id: Note ID
        note_id: Alternative note ID field (some endpoints use this)
        title: Note title
        content: Plain text content
        body_text: Body summary (may contain HTML)
        json_content: Rich text content in JSON format
        note_type: Type of note - plain_text, link, local_audio
        entry_type: How note was created - manual, ai
        source: Source of note - web, knowledge
        tags: List of tags
        attachments: List of attachments
        is_ai_generated: Whether this was AI-generated
        share_id: Share ID for sharing
        is_in_topic: Whether note is in a knowledge base
        topics: List of knowledge bases this note belongs to
        created_at: Creation timestamp
        updated_at: Last update timestamp
    """

    id: str
    title: str
    content: str
    body_text: str = ""
    json_content: str = ""
    note_type: str = "plain_text"
    entry_type: str = "manual"
    source: str = "web"
    tags: List[Tag] = field(default_factory=list)
    attachments: List[Attachment] = field(default_factory=list)
    is_ai_generated: bool = False
    share_id: str = ""
    is_in_topic: bool = False
    topics: List[Dict[str, Any]] = field(default_factory=list)
    created_at: str = ""
    updated_at: str = ""
    version: int = 1
    display_status: int = 0
    prompt_template_id: str = ""
    is_author: bool = False
    edit_time: str = ""
    topic_id: str = ""
    has_ai_processed: bool = False
    status: int = 0

    @classmethod
    def from_dict(cls, data: dict) -> "Note":
        """Create Note from API response dict."""
        # Handle both 'id' and 'note_id' fields
        note_id = data.get("id") or data.get("note_id", "")

        # Parse tags
        tags = []
        for tag_data in data.get("tags", []):
            if isinstance(tag_data, dict):
                tags.append(
                    Tag(
                        id=tag_data.get("id", ""),
                        name=tag_data.get("name", ""),
                        type=tag_data.get("type", ""),
                        tag_type=tag_data.get("tag_type", ""),
                    )
                )

        # Parse attachments
        attachments = []
        for attach_data in data.get("attachments", []):
            if isinstance(attach_data, dict):
                attachments.append(Attachment.from_dict(attach_data))

        return cls(
            id=note_id,
            title=data.get("title", ""),
            content=data.get("content", ""),
            body_text=data.get("body_text", ""),
            json_content=data.get("json_content", ""),
            note_type=data.get("note_type", "plain_text"),
            entry_type=data.get("entry_type", "manual"),
            source=data.get("source", "web"),
            tags=tags,
            attachments=attachments,
            is_ai_generated=data.get("is_ai_generated", False),
            share_id=data.get("share_id", ""),
            is_in_topic=data.get("is_in_topic", False),
            topics=data.get("topics", []),
            created_at=data.get("created_at", ""),
            updated_at=data.get("updated_at", ""),
            version=data.get("version", 1),
            display_status=data.get("display_status", 0),
            prompt_template_id=data.get("prompt_template_id", ""),
            is_author=data.get("is_author", False),
            edit_time=data.get("edit_time", ""),
            topic_id=str(data.get("topic_id", "")),
            has_ai_processed=data.get("has_ai_processed", False),
            status=data.get("status", 0),
        )


@dataclass
class LinkNoteDetail:
    """Detailed content for a link-type note."""

    title: str  # AI generated title
    web_title: str  # Original web page title
    content: str  # Original web page HTML content
    url: str  # Original link URL
    has_content: bool  # Whether content was successfully retrieved

    @classmethod
    def from_dict(cls, data: dict) -> "LinkNoteDetail":
        """Create LinkNoteDetail from API response dict."""
        return cls(
            title=data.get("title", ""),
            web_title=data.get("web_title", ""),
            content=data.get("content", ""),
            url=data.get("url", ""),
            has_content=data.get("has_content", False),
        )


@dataclass
class NoteListResult:
    """Result of listing notes with pagination."""

    list: List[Note]
    total_items: int
    has_more: bool
    limit: int

    @classmethod
    def from_dict(cls, data: dict) -> "NoteListResult":
        """Create NoteListResult from API response dict."""
        notes = []
        for note_data in data.get("list", []):
            if isinstance(note_data, dict):
                notes.append(Note.from_dict(note_data))

        return cls(
            list=notes,
            total_items=data.get("total_items", 0),
            has_more=data.get("has_more", False),
            limit=data.get("limit", 10),
        )


@dataclass
class TokenInfo:
    """
    Token information for authentication.

    Attributes:
        token: Access token (JWT)
        refresh_token: Refresh token
        token_expire_at: Access token expiration timestamp (seconds)
        refresh_token_expire_at: Refresh token expiration timestamp (seconds)
        jti: JWT ID
    """

    token: str
    refresh_token: str
    token_expire_at: int
    refresh_token_expire_at: int
    jti: str = ""

    @classmethod
    def from_dict(cls, data: dict) -> "TokenInfo":
        """Create TokenInfo from API response dict."""
        return cls(
            token=data.get("token", ""),
            refresh_token=data.get("refresh_token", ""),
            token_expire_at=data.get("token_expire_at", 0),
            refresh_token_expire_at=data.get("refresh_token_expire_at", 0),
            jti=data.get("jti", ""),
        )


@dataclass
class VIPInfo:
    """VIP membership information."""

    is_vip: bool
    surplus_days: int  # Remaining VIP days


@dataclass
class RightsInfo:
    """User rights and permissions."""

    audio_duration_ms: int  # Audio duration limit in milliseconds


@dataclass
class QuotaInfo:
    """User quota information."""

    local_audio_quota: Dict[str, Any]

    def get_remained_duration(self) -> int:
        """Get remaining audio duration in milliseconds."""
        return self.local_audio_quota.get("remained_duration", 0)


@dataclass
class LabsInfo:
    """Labs feature availability."""

    can_create_topics: bool  # Whether user can create knowledge bases


@dataclass
class User:
    """
    User account information.

    Attributes:
        uid: User ID
        cellphone: Phone number
        nickname: Display nickname
        avatar: Avatar URL
        status: Account status
        app_id: App ID (3 = Web)
        is_vip: Whether user has VIP membership
        surplus_days: Remaining VIP days
        can_create_topics: Whether user can create knowledge bases
        audio_duration_ms: Audio duration limit in milliseconds
        remained_audio_duration: Remaining audio quota in milliseconds
        create_time: Account creation timestamp
    """

    uid: int
    cellphone: str
    nickname: str
    avatar: str
    status: int
    is_vip: bool
    surplus_days: int
    can_create_topics: bool
    audio_duration_ms: int
    remained_audio_duration: int
    create_time: int

    @classmethod
    def from_dict(cls, data: dict) -> "User":
        """Create User from API response dict."""
        vip_info = data.get("vip_info", {})
        rights_info = data.get("rights_info", {})
        quota_info = data.get("quota_info", {})
        labs = data.get("labs", {})

        return cls(
            uid=data.get("uid", 0),
            cellphone=data.get("cellphone", ""),
            nickname=data.get("nickname", ""),
            avatar=data.get("avatar", ""),
            status=data.get("status", 0),
            is_vip=vip_info.get("is_vip", False),
            surplus_days=vip_info.get("surplus_days", 0),
            can_create_topics=labs.get("can_create_topics", False),
            audio_duration_ms=rights_info.get("audio_duration_ms", 0),
            remained_audio_duration=quota_info.get("local_audio_quota", {}).get(
                "remained_duration", 0
            ),
            create_time=data.get("create_time", 0),
        )


@dataclass
class KnowledgeExtendData:
    """Extended data for knowledge base."""

    all_resource_count: int
    get_note_count: int
    subscribe_count: int


@dataclass
class KnowledgeShareInfo:
    """Share information for knowledge base."""

    share_mode: str  # OPEN, CLOSED
    share_link: str


@dataclass
class KnowledgeConfig:
    """Configuration for knowledge base."""

    supported_file_type: List[str]


@dataclass
class Knowledge:
    """
    Knowledge base information.

    Attributes:
        id: Knowledge base ID
        id_alias: Alias for sharing
        uid: Creator user ID
        name: Knowledge base name
        description: Description
        cover: Cover image URL
        avatar: Creator avatar URL
        creator: Creator nickname
        is_author: Whether current user is the creator (1=yes)
        is_added: Whether knowledge base is added (1=yes)
        scope: Scope - DEFAULT for private
        share_url: Share URL
        note_count: Number of notes in knowledge base
        subscribe_count: Number of subscribers
        all_resource_count: Total resources count
        root_dir_id: Root directory ID
        last_update_time_desc: Last update description
        create_time: Creation timestamp
        share_mode: Share mode (OPEN, CLOSED)
        is_selection: Whether featured (for subscribed)
        open_subscription: Whether open for subscription (for subscribed)
    """

    id: int
    id_alias: str
    uid: int
    name: str
    description: str
    creator: str
    is_author: bool
    share_url: str
    note_count: int
    subscribe_count: int
    all_resource_count: int
    root_dir_id: int
    cover: str = ""
    avatar: str = ""
    is_added: bool = False
    scope: str = "DEFAULT"
    last_update_time_desc: str = ""
    create_time: int = 0
    share_mode: str = "CLOSED"
    is_selection: bool = False
    open_subscription: bool = False
    supported_file_types: List[str] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> "Knowledge":
        """Create Knowledge from API response dict."""
        extend_data = data.get("extend_data", {}) or {}
        share_info = data.get("share_info", {}) or {}
        config = data.get("config") or {}

        return cls(
            id=data.get("id", 0),
            id_alias=data.get("id_alias", ""),
            uid=data.get("uid", 0),
            name=data.get("name", ""),
            description=data.get("description", ""),
            cover=data.get("cover", ""),
            avatar=data.get("avatar", ""),
            creator=data.get("creator", ""),
            is_author=data.get("is_author", 0) == 1,
            is_added=data.get("is_added", 0) == 1,
            scope=data.get("scope", "DEFAULT"),
            share_url=data.get("share_url", ""),
            note_count=extend_data.get("get_note_count", 0),
            subscribe_count=extend_data.get("subscribe_count", 0),
            all_resource_count=extend_data.get("all_resource_count", 0),
            root_dir_id=(data.get("root_dir") or {}).get("id", 0),
            last_update_time_desc=data.get("last_update_time_desc", ""),
            create_time=data.get("create_time", 0),
            share_mode=share_info.get("share_mode", "CLOSED"),
            is_selection=data.get("is_selection", 0) == 1,
            open_subscription=data.get("open_subscription", 0) == 1,
            supported_file_types=config.get("supported_file_type", []),
        )


@dataclass
class KnowledgeListResult:
    """Result of listing subscribed knowledge bases."""

    list: List[Knowledge]
    count: int
    has_more: bool

    @classmethod
    def from_dict(cls, data: dict) -> "KnowledgeListResult":
        """Create KnowledgeListResult from API response dict."""
        kbs = []
        for kb_data in data.get("list", []):
            if isinstance(kb_data, dict):
                kbs.append(Knowledge.from_dict(kb_data))

        return cls(
            list=kbs,
            count=data.get("count", 0),
            has_more=data.get("has_more", False),
        )


@dataclass
class OSSTokenInfo:
    """OSS upload token information."""

    object_key: str
    put_sign_url: str
    put_content_type: str
    put_md5: str
    get_url: str


@dataclass
class UploadTokenResult:
    """Result from getting upload token."""

    is_uploaded: bool  # True if file already exists (instant upload)
    file_id: str
    token_info: Optional[OSSTokenInfo]
    image_path: Optional[str] = None  # Set if is_uploaded is True

    @classmethod
    def from_dict(cls, data: dict) -> "UploadTokenResult":
        """Create UploadTokenResult from API response dict."""
        token_info_data = data.get("token_info")
        token_info = None
        if token_info_data:
            token_info = OSSTokenInfo(
                object_key=token_info_data.get("object_key", ""),
                put_sign_url=token_info_data.get("put_sign_url", ""),
                put_content_type=token_info_data.get("put_content_type", ""),
                put_md5=token_info_data.get("put_md5", ""),
                get_url=token_info_data.get("get_url", ""),
            )

        return cls(
            is_uploaded=data.get("is_uploaded", False),
            file_id=data.get("file_id", ""),
            token_info=token_info,
            image_path=data.get("image", {}).get("path") if data.get("is_uploaded") else None,
        )


@dataclass
class ProgressItem:
    """Progress item for streaming operations."""

    msg: str
    process_name: str
    process_status: str

    @classmethod
    def from_dict(cls, data: dict) -> "ProgressItem":
        """Create ProgressItem from dict."""
        return cls(
            msg=data.get("msg", ""),
            process_name=data.get("processName", ""),
            process_status=data.get("processStatus", ""),
        )


@dataclass
class AudioSectionInfo:
    """Chapter/section information for audio notes."""

    title: str
    description: str
    timestamp: str  # Format: "HH:MM:SS"
    milliseconds: int  # Timestamp in milliseconds

    @classmethod
    def from_dict(cls, data: dict) -> "AudioSectionInfo":
        """Create AudioSectionInfo from dict."""
        return cls(
            title=data.get("title", ""),
            description=data.get("description", ""),
            timestamp=data.get("timestamp", ""),
            milliseconds=data.get("milliseconds", 0),
        )


@dataclass
class Directory:
    """Knowledge base directory node."""

    id: int
    topic_id: int
    parent_id: int
    name: str
    type: str  # ROOT, DEFAULT
    resource_desc: str = ""
    create_time: int = 0
    update_time: int = 0

    @classmethod
    def from_dict(cls, data: dict) -> "Directory":
        """Create Directory from API response dict."""
        return cls(
            id=data.get("id", 0),
            topic_id=data.get("topic_id", 0),
            parent_id=data.get("parent_id", 0),
            name=data.get("name", ""),
            type=data.get("type", "DEFAULT"),
            resource_desc=data.get("resource_desc", ""),
            create_time=data.get("create_time", 0),
            update_time=data.get("update_time", 0),
        )


@dataclass
class FileMetaData:
    """File metadata for FILE type resources in knowledge bases."""

    name: str
    type: str  # PDF, DOC, DOCX, PPT, PPTX
    file_url: str
    source_file_url: str
    storage_size: int
    md5: str
    cover: str = ""
    source_type: str = ""

    @classmethod
    def from_dict(cls, data: dict) -> "FileMetaData":
        """Create FileMetaData from API response dict."""
        return cls(
            name=data.get("name", ""),
            type=data.get("type", ""),
            file_url=data.get("file_url", ""),
            source_file_url=data.get("source_file_url", ""),
            storage_size=data.get("storage_size", 0),
            md5=data.get("md5", ""),
            cover=data.get("cover", ""),
            source_type=data.get("source_type", ""),
        )


@dataclass
class Resource:
    """Resource item in a knowledge base (NOTE or FILE)."""

    id: int
    uid: int
    topic_id: int
    topic_id_alias: str
    directory_id: int
    resource_type: str  # NOTE, FILE
    resource_note_meta_data: Optional[Dict[str, Any]] = None
    resource_file_meta_data: Optional[FileMetaData] = None
    progress: str = ""
    platform: str = ""
    add_desc: str = ""
    create_time: int = 0
    update_time: int = 0

    @classmethod
    def from_dict(cls, data: dict) -> "Resource":
        """Create Resource from API response dict."""
        file_meta = data.get("resource_file_meta_data")
        file_meta_obj = FileMetaData.from_dict(file_meta) if file_meta else None

        return cls(
            id=data.get("id", 0),
            uid=data.get("uid", 0),
            topic_id=data.get("topic_id", 0),
            topic_id_alias=data.get("topic_id_alias", ""),
            directory_id=data.get("directory_id", 0),
            resource_type=data.get("resource_type", ""),
            resource_note_meta_data=data.get("resource_note_meta_data"),
            resource_file_meta_data=file_meta_obj,
            progress=data.get("progress", ""),
            platform=data.get("platform", ""),
            add_desc=data.get("add_desc", ""),
            create_time=data.get("create_time", 0),
            update_time=data.get("update_time", 0),
        )


@dataclass
class ResourceListResult:
    """Result of listing knowledge base resources."""

    has_next: bool
    current_directory: Optional[Directory]
    directories: List[Directory]
    resources: List[Resource]

    @classmethod
    def from_dict(cls, data: dict) -> "ResourceListResult":
        """Create ResourceListResult from API response dict."""
        current_dir_data = data.get("current_directory")
        current_dir = Directory.from_dict(current_dir_data) if current_dir_data else None

        directories = []
        for d in data.get("directories") or []:
            if isinstance(d, dict):
                directories.append(Directory.from_dict(d))

        resources = []
        for r in data.get("resources") or []:
            if isinstance(r, dict):
                resources.append(Resource.from_dict(r))

        return cls(
            has_next=data.get("has_next", 0) == 1,
            current_directory=current_dir,
            directories=directories,
            resources=resources,
        )


@dataclass
class FollowItem:
    """Follow item (live stream or blogger) in a knowledge base."""

    id: int
    uid: int
    topic_id: int
    type: int  # 1=blogger, 2=live stream
    name: str
    sub_title: str = ""
    description: str = ""
    icon: str = ""
    url: str = ""
    start_time: int = 0
    end_time: int = 0
    platform: str = ""
    status: int = 0
    ai_status: int = 0
    post_progress: str = ""
    followee_id: int = 0
    followee_id_str: str = ""
    create_time: int = 0
    extend_data: Optional[Dict[str, Any]] = None

    @classmethod
    def from_dict(cls, data: dict) -> "FollowItem":
        """Create FollowItem from API response dict."""
        return cls(
            id=data.get("id", 0),
            uid=data.get("uid", 0),
            topic_id=data.get("topic_id", 0),
            type=data.get("type", 0),
            name=data.get("name", ""),
            sub_title=data.get("sub_title", ""),
            description=data.get("description", ""),
            icon=data.get("icon", ""),
            url=data.get("url", ""),
            start_time=data.get("start_time", 0),
            end_time=data.get("end_time", 0),
            platform=data.get("platform", ""),
            status=data.get("status", 0),
            ai_status=data.get("ai_status", 0),
            post_progress=data.get("post_progress", ""),
            followee_id=data.get("followee_id", 0),
            followee_id_str=data.get("followee_id_str", ""),
            create_time=data.get("create_time", 0),
            extend_data=data.get("extend_data"),
        )


@dataclass
class FollowListResult:
    """Result of listing follow items (live streams / bloggers)."""

    has_next: bool
    list: List[FollowItem]

    @classmethod
    def from_dict(cls, data: dict) -> "FollowListResult":
        """Create FollowListResult from API response dict."""
        items = []
        for item in data.get("list") or []:
            if isinstance(item, dict):
                items.append(FollowItem.from_dict(item))

        return cls(
            has_next=data.get("has_next", False),
            list=items,
        )


@dataclass
class LiveStreamPost:
    """Live stream post detail (直播笔记详情)."""

    post_id: int
    post_id_str: str
    post_id_alias: str
    post_name: str
    post_type: int  # 4=live stream
    post_cover: str
    post_title: str
    post_summary: str  # AI-generated Markdown summary
    post_cleaned_summary: str
    post_url: str
    ai_status: int  # 2=completed
    post_media_text: str = ""
    post_create_time: int = 0
    post_update_time: int = 0
    post_publish_time: int = 0
    progress: str = ""
    hide_source_entrance: bool = False

    @classmethod
    def from_dict(cls, data: dict) -> "LiveStreamPost":
        """Create LiveStreamPost from API response dict."""
        return cls(
            post_id=data.get("post_id", 0),
            post_id_str=data.get("post_id_str", ""),
            post_id_alias=data.get("post_id_alias", ""),
            post_name=data.get("post_name", ""),
            post_type=data.get("post_type", 0),
            post_cover=data.get("post_cover", ""),
            post_title=data.get("post_title", ""),
            post_summary=data.get("post_summary", ""),
            post_cleaned_summary=data.get("post_cleaned_summary", ""),
            post_url=data.get("post_url", ""),
            ai_status=data.get("ai_status", 0),
            post_media_text=data.get("post_media_text", ""),
            post_create_time=data.get("post_create_time", 0),
            post_update_time=data.get("post_update_time", 0),
            post_publish_time=data.get("post_publish_time", 0),
            progress=data.get("progress", ""),
            hide_source_entrance=data.get("hide_source_entrance", False),
        )


@dataclass
class ChildrenCountResult:
    """Result of getting children count for a note."""

    total: int
    can_add_child_note: bool
    max_child_note_count: int

    @classmethod
    def from_dict(cls, data: dict) -> "ChildrenCountResult":
        """Create ChildrenCountResult from API response dict."""
        return cls(
            total=data.get("total", 0),
            can_add_child_note=data.get("can_add_child_note", False),
            max_child_note_count=data.get("max_child_note_count", 0),
        )
