from typing import Optional, List, Dict, Any
from datetime import datetime
import uuid
from sqlmodel import SQLModel, Field, Relationship, Column, JSON

# We use TEXT for JSON fields in SQLite because SQLite doesn't have a native JSON type
# but SQLAlchemy can handle the serialization if we assume it's JSON.
# However, SQLModel with Pydantic v2 usually handles Dict/List fields automatically by validating them.
# storage, we can use sa_column=Column(JSON) which maps to TEXT in SQLite.


def _iso_timestamp(unix_timestamp: float) -> str:
    """Convert Unix timestamp to ISO 8601 format string"""
    return datetime.fromtimestamp(unix_timestamp).isoformat() + "Z"


class TimestampMixin:
    """Mixin for ISO timestamp conversion"""
    created_at: float
    updated_at: float

    @property
    def created_at_iso(self) -> str:
        """返回 ISO 8601 格式的创建时间"""
        return _iso_timestamp(self.created_at)

    @property
    def updated_at_iso(self) -> str:
        """返回 ISO 8601 格式的更新时间"""
        return _iso_timestamp(self.updated_at)

class ProjectDB(SQLModel, table=True):
    __tablename__ = "projects"

    id: str = Field(default_factory=lambda: str(uuid.uuid4()), primary_key=True)
    name: str
    description: Optional[str] = None
    type: str = "canvas"
    status: str = "active"
    created_at: float = Field(default_factory=lambda: datetime.now().timestamp())
    updated_at: float = Field(default_factory=lambda: datetime.now().timestamp())
    deleted_at: Optional[float] = None  # Soft delete support

    # User association
    user_id: Optional[str] = Field(default=None, foreign_key="users.id", index=True, description="项目所有者ID")

    # Specific fields
    resolution: Optional[str] = None
    ratio: Optional[str] = None
    style_id: Optional[str] = None
    style_params: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))

    # Wizard state preservation
    chapters: Optional[List[Dict[str, Any]]] = Field(default=None, sa_column=Column(JSON))

    # Initialization progress tracking
    progress: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    error: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))

    # Relationships
    owner: Optional["UserDB"] = Relationship(back_populates="projects")
    assets: List["AssetDB"] = Relationship(back_populates="project", sa_relationship_kwargs={"cascade": "all, delete-orphan"})
    episodes: List["EpisodeDB"] = Relationship(back_populates="project", sa_relationship_kwargs={"cascade": "all, delete-orphan"})
    storyboards: List["StoryboardDB"] = Relationship(back_populates="project", sa_relationship_kwargs={"cascade": "all, delete-orphan"})
    canvas_metadata: List["CanvasMetadataDB"] = Relationship(back_populates="project", sa_relationship_kwargs={"cascade": "all, delete-orphan"})


class AssetDB(SQLModel, table=True):
    __tablename__ = "assets"

    id: str = Field(default_factory=lambda: str(uuid.uuid4()), primary_key=True)
    project_id: str = Field(foreign_key="projects.id", index=True)
    type: str  # character, scene, prop, etc.
    
    # We store the full Pydantic model dump in 'data' for flexibility, 
    # matching the previous implementation's logic, but we can also extract common fields.
    # To keep migration simple and support various Asset types, we'll store the core fields
    # and put everything else in a JSON blob if needed, OR we can try to map fields.
    # Given the Pydantic models in apps/models.py have name, desc, tags, imageUrl, etc.
    
    name: str
    desc: str = ""
    tags: List[str] = Field(default=[], sa_column=Column(JSON))
    image_url: Optional[str] = None
    image_urls: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    video_urls: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    deleted_at: Optional[float] = None  # Soft delete support
    
    # Image generation prompt
    image_prompt: Optional[str] = None
    
    # Store other specific attributes (age, role, etc.) in a generic JSON field
    # to avoid creating separate tables for Character, Scene, etc. for now.
    extra_data: Dict[str, Any] = Field(default={}, sa_column=Column(JSON))
    
    # Store generations history
    generations: List[Dict[str, Any]] = Field(default=[], sa_column=Column(JSON))

    project: ProjectDB = Relationship(back_populates="assets")


class EpisodeDB(SQLModel, table=True):
    __tablename__ = "episodes"

    id: str = Field(default_factory=lambda: str(uuid.uuid4()), primary_key=True)
    project_id: str = Field(foreign_key="projects.id", index=True)
    order_index: int = Field(alias="order") # 'order' is a reserved keyword in SQL usually, but valid as column name. Using order_index to be safe.
    
    title: str
    desc: Optional[str] = None
    content: Optional[str] = None
    status: str = "draft"
    deleted_at: Optional[float] = None  # Soft delete support
    
    project: ProjectDB = Relationship(back_populates="episodes")
    storyboards: List["StoryboardDB"] = Relationship(back_populates="episode", sa_relationship_kwargs={"cascade": "all, delete-orphan"})


class StoryboardDB(SQLModel, table=True):
    __tablename__ = "storyboards"

    id: str = Field(default_factory=lambda: str(uuid.uuid4()), primary_key=True)
    project_id: str = Field(foreign_key="projects.id", index=True)
    episode_id: str = Field(foreign_key="episodes.id", index=True)
    order_index: int
    
    shot: str
    desc: str
    duration: str
    type: str = "image"
    
    scene_id: Optional[str] = None
    character_ids: List[str] = Field(default=[], sa_column=Column(JSON))
    prop_ids: List[str] = Field(default=[], sa_column=Column(JSON))
    
    # 生产环境 details
    voiceover: Optional[str] = None
    audio_desc: Optional[str] = None
    audio_url: Optional[str] = None
    camera_movement: Optional[str] = None
    transition: Optional[str] = None

    # Cinematic control fields
    camera_angle: Optional[str] = None
    lens: Optional[str] = None
    focus: Optional[str] = None
    lighting: Optional[str] = None
    color_style: Optional[str] = None

    # Context
    location: Optional[str] = None
    time: Optional[str] = None
    
    # Original text and prompts
    original_text: Optional[str] = None
    merge_image_prompt: Optional[str] = None
    video_prompt: Optional[str] = None
    
    image_urls: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    video_urls: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    generations: List[Dict[str, Any]] = Field(default=[], sa_column=Column(JSON))
    deleted_at: Optional[float] = None  # Soft delete support

    project: ProjectDB = Relationship(back_populates="storyboards")
    episode: EpisodeDB = Relationship(back_populates="storyboards")


class TaskDB(SQLModel, table=True):
    __tablename__ = "tasks"

    id: str = Field(default_factory=lambda: str(uuid.uuid4()), primary_key=True)
    type: str = Field(index=True)  # image, video, script
    status: str = Field(index=True)  # pending, processing, success, failed, timeout, retrying
    created_at: float = Field(default_factory=lambda: datetime.now().timestamp(), index=True)
    updated_at: float = Field(default_factory=lambda: datetime.now().timestamp())
    model: Optional[str] = None
    provider: Optional[str] = Field(default=None, index=True)  # Provider name (e.g., dashscope, openai)
    params: Dict[str, Any] = Field(default={}, sa_column=Column(JSON))
    provider_task_id: Optional[str] = None
    result: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    error: Optional[str] = None
    
    # Retry configuration
    retry_count: int = Field(default=0)
    max_retries: int = Field(default=3)
    
    # Timestamps for task lifecycle
    started_at: Optional[float] = None
    completed_at: Optional[float] = None
    
    # User context
    user_id: Optional[str] = Field(default=None, index=True)
    project_id: Optional[str] = Field(default=None, index=True)
    
    # Soft delete support
    deleted_at: Optional[float] = None

class CanvasDB(SQLModel, table=True):
    __tablename__ = "canvases"

    id: str = Field(primary_key=True)
    project_id: Optional[str] = Field(default=None, index=True)
    
    # Canvas Content
    nodes: List[Dict[str, Any]] = Field(default=[], sa_column=Column(JSON))
    connections: List[Dict[str, Any]] = Field(default=[], sa_column=Column(JSON))
    groups: List[Dict[str, Any]] = Field(default=[], sa_column=Column(JSON))
    history: List[Dict[str, Any]] = Field(default=[], sa_column=Column(JSON))
    history_index: int = Field(default=-1, alias="historyIndex")
    
    updated_at: float = Field(default_factory=lambda: datetime.now().timestamp())


class CanvasMetadataDB(SQLModel, table=True):
    """画布元数据表 - 统一管理所有类型的画布"""
    __tablename__ = "canvas_metadata"
    
    # ===== 基础字段 =====
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()), 
        primary_key=True,
        description="画布唯一标识符"
    )
    project_id: str = Field(
        foreign_key="projects.id", 
        index=True,
        description="所属项目 ID"
    )
    
    # ===== 画布类型和关联 =====
    canvas_type: str = Field(
        index=True,
        description="画布类型: 'general' | 'asset' | 'storyboard'"
    )
    related_entity_type: Optional[str] = Field(
        default=None,
        description="关联实体类型: 'asset' | 'storyboard' | None"
    )
    related_entity_id: Optional[str] = Field(
        default=None, 
        index=True,
        description="关联实体 ID"
    )
    
    # ===== 元数据 =====
    name: str = Field(description="画布名称")
    description: Optional[str] = Field(default=None, description="画布描述")
    
    # ===== 显示和组织 =====
    order_index: int = Field(default=0, description="显示顺序（仅通用画布使用）")
    is_pinned: bool = Field(default=False, description="是否置顶")
    tags: List[str] = Field(default=[], sa_column=Column(JSON), description="标签")
    
    # ===== 统计信息 =====
    node_count: int = Field(default=0, description="节点数量")
    last_accessed_at: Optional[float] = Field(default=None, description="最后访问时间")
    access_count: int = Field(default=0, description="访问次数")
    
    # ===== 时间戳 =====
    created_at: float = Field(
        default_factory=lambda: datetime.now().timestamp(),
        description="创建时间"
    )
    updated_at: float = Field(
        default_factory=lambda: datetime.now().timestamp(),
        description="更新时间"
    )
    deleted_at: Optional[float] = Field(default=None, description="软删除时间")
    
    # ===== 关系 =====
    project: ProjectDB = Relationship(back_populates="canvas_metadata")


class UserDB(SQLModel, table=True):
    """用户表 - 存储用户认证信息"""
    __tablename__ = "users"

    id: str = Field(default_factory=lambda: str(uuid.uuid4()), primary_key=True)
    username: str = Field(index=True, unique=True, description="用户名")
    email: Optional[str] = Field(default=None, index=True, unique=True, description="邮箱")

    # 密码哈希（bcrypt）
    password_hash: str = Field(description="密码哈希")

    # 用户状态
    is_active: bool = Field(default=True, description="是否激活")
    is_superuser: bool = Field(default=False, description="是否超级用户")

    # 权限和角色（JSON 数组）
    permissions: List[str] = Field(default=[], sa_column=Column(JSON), description="权限列表")
    roles: List[str] = Field(default=[], sa_column=Column(JSON), description="角色列表")

    # 用户头像
    avatar_url: Optional[str] = Field(default=None, description="头像URL")

    # 时间戳
    created_at: float = Field(default_factory=lambda: datetime.now().timestamp(), description="创建时间")
    updated_at: float = Field(default_factory=lambda: datetime.now().timestamp(), description="更新时间")
    last_login: Optional[float] = Field(default=None, description="最后登录时间")

    # 关系：用户的 API keys
    api_keys: List["UserApiKeyDB"] = Relationship(
        back_populates="user",
        sa_relationship_kwargs={"cascade": "all, delete-orphan"}
    )

    # 关系：用户的项目
    projects: List["ProjectDB"] = Relationship(
        back_populates="owner",
        sa_relationship_kwargs={"cascade": "all, delete-orphan"}
    )


class UserApiKeyDB(SQLModel, table=True):
    """用户 API Key 表 - 存储用户的模型 API Key"""
    __tablename__ = "user_api_keys"

    id: str = Field(default_factory=lambda: str(uuid.uuid4()), primary_key=True)

    # 外键关联
    user_id: str = Field(foreign_key="users.id", index=True, description="用户ID")

    # Provider 类型
    provider: str = Field(index=True, description="提供商: openai, dashscope, midjourney 等")

    # 加密的 API key
    encrypted_key: str = Field(description="加密的API Key")

    # 用户自定义名称（如"我的工作Key"）
    name: Optional[str] = Field(default=None, description="自定义名称")

    # 是否启用
    is_active: bool = Field(default=True, description="是否启用")

    # 使用统计
    created_at: float = Field(default_factory=lambda: datetime.now().timestamp(), description="创建时间")
    updated_at: float = Field(default_factory=lambda: datetime.now().timestamp(), description="更新时间")
    last_used_at: Optional[float] = Field(default=None, description="最后使用时间")
    usage_count: int = Field(default=0, description="使用次数")

    # 额外配置（如 base_url, 组织ID等）
    extra_config: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON), description="额外配置")

    # 关系
    user: UserDB = Relationship(back_populates="api_keys")
