"""
数据模型定义模块
定义AI换脸换装系统的所有数据表结构
用户表：存储用户信息（用户ID，用户名, 密码哈希，是否激活，是否管理员，创建时间，更新时间，最后登录时间）
图片记录表：存储图片信息（图片ID，用户ID，图片类型，原始文件名，存储路径，文件大小，图片哈希，是否已删除，创建时间，更新时间）
处理记录表：存储处理记录信息（处理记录ID，用户ID，人脸图片ID，服装图片ID，生成结果图片ID, AI生成的文案内容，完成时间）
系统配置表：存储系统配置信息（配置ID，配置键，配置值，配置类型，配置描述，是否公开配置，创建时间，更新时间）
数据库版本表：存储数据库版本信息（版本ID，版本号，版本描述，应用时间，迁移文件名）
"""


from datetime import datetime
from typing import Optional, List
from sqlalchemy import (
    Column, Integer, String, Text, DateTime, Boolean, 
    Float, ForeignKey, Index, UniqueConstraint, CheckConstraint
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, Mapped
from sqlalchemy.sql import func

# 定义数据库模型
Base = declarative_base()

class User(Base):
    """用户表"""
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, autoincrement=True, comment="用户ID")
    username = Column(String(50), unique=True, nullable=False, comment="用户名")
    password_hash = Column(String(255), nullable=False, comment="密码哈希")
    is_active = Column(Boolean, default=True, comment="是否激活")
    is_admin = Column(Boolean, default=False, comment="是否管理员")
    created_at = Column(DateTime, default=func.now(), comment="创建时间")
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间")
    last_login = Column(DateTime, nullable=True, comment="最后登录时间")

    # 关联关系: 用户与图片记录、处理记录一对多关系（一个用户可以有多张图片和多个处理记录）
    image_records: Mapped[List["ImageRecord"]] = relationship("ImageRecord", back_populates="user")
    process_records: Mapped[List["ProcessRecord"]] = relationship("ProcessRecord", back_populates="user")
    text_records: Mapped[List["TextRecord"]] = relationship("TextRecord", back_populates="user")
    
    __table_args__ = (
        Index('idx_username', 'username'),
    )


class ImageRecord(Base):
    """图片记录表"""
    __tablename__ = "image_records"

    id = Column(Integer, primary_key=True, autoincrement=True, comment="图片记录ID")
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False, comment="用户ID")
    image_type = Column(String(20), nullable=False, comment="图片类型(face/cloth/result/original)")
    original_filename = Column(String(255), nullable=False, comment="原始文件名")
    stored_path = Column(String(500), nullable=False, comment="存储路径")
    file_size = Column(Integer, nullable=True, comment="文件大小(字节)")
    image_hash = Column(String(64), nullable=True, comment="图片哈希值")
    is_deleted = Column(Boolean, default=False, comment="是否已删除")
    created_at = Column(DateTime, default=func.now(), comment="创建时间")
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间")

    # 关联关系：图片记录与用户、处理记录多对一关系；一个人脸图片可以有多个处理记录
    user: Mapped["User"] = relationship("User", back_populates="image_records")
    face_processes: Mapped[List["ProcessRecord"]] = relationship(
        "ProcessRecord",
        foreign_keys="ProcessRecord.face_image_id",
        back_populates="face_image"
    )
    cloth_processes: Mapped[List["ProcessRecord"]] = relationship(
        "ProcessRecord", 
        foreign_keys="ProcessRecord.cloth_image_id",
        back_populates="cloth_image"
    )
    result_processes: Mapped[List["ProcessRecord"]] = relationship(
        "ProcessRecord",
        foreign_keys="ProcessRecord.result_image_id",
        back_populates="result_image"
    )

    __table_args__ = (
        Index('idx_image_user_id', 'user_id'),
        Index('idx_image_type', 'image_type'),
        Index('idx_image_created_at', 'created_at'),
        CheckConstraint("image_type IN ('face', 'cloth', 'result', 'original')", name="ck_image_type"),
    )


class TextRecord(Base):
    """文本模板记录表"""
    __tablename__ = "text_records"

    id = Column(Integer, primary_key=True, autoincrement=True, comment="文本模板记录ID")
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False, comment="用户ID")
    text_type = Column(String(20), nullable=False, comment="文本模型类型(prompt/copywrite)")
    text_name = Column(String(20), nullable=False, comment="文本名称")
    text_label = Column(String(20), nullable=False, comment="文本模板标签")
    text_content = Column(Text, nullable=False, comment="文本模板内容")
    created_at = Column(DateTime, default=func.now(), comment="创建时间")
    
    # 关联关系：文本模型与用户多对一关系
    user: Mapped["User"] = relationship("User", back_populates="text_records")

    __table_args__ = (
        Index('idx_text_user_id', 'user_id'),
        Index('idx_text_type', 'text_type'),
        Index('idx_text_name', 'text_name'),
        Index('idx_text_label', 'text_label'),
        CheckConstraint("text_type IN ('prompt', 'copywrite')", name="ck_text_type"),
    )


class ProcessRecord(Base):
    """AI换脸换装处理记录表"""
    __tablename__ = "process_records"

    id = Column(Integer, primary_key=True, autoincrement=True, comment="处理记录ID")
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False, comment="用户ID")

    # 输入图片信息
    face_image_id = Column(Integer, ForeignKey("image_records.id"), nullable=False, comment="人脸图片ID")
    cloth_image_id = Column(Integer, ForeignKey("image_records.id"), nullable=False, comment="服装图片ID")

    # 输出图片信息
    result_image_id = Column(Integer, ForeignKey("image_records.id"), nullable=True, comment="生成结果图片ID")

    # 文案信息
    generated_text = Column(Text, nullable=True, comment="AI生成的文案内容")

    # 状态信息
    status = Column(String(20), nullable=False, default="待审核", comment="处理记录状态")

    # 完成时间
    completed_at = Column(DateTime, nullable=True, onupdate=func.now(), comment="完成时间")

    # 任务类型
    task_type = Column(String(40), nullable=False, comment="任务类型")

    # 提示词
    prompt = Column(Text, nullable=False, comment="提示词")


    # 关联关系：处理记录与用户、图片记录多对一关系
    user: Mapped["User"] = relationship("User", back_populates="process_records")
    face_image: Mapped["ImageRecord"] = relationship(
        "ImageRecord",
        foreign_keys=[face_image_id],
        back_populates="face_processes"
    )
    cloth_image: Mapped["ImageRecord"] = relationship(
        "ImageRecord",
        foreign_keys=[cloth_image_id],
        back_populates="cloth_processes"
    )
    result_image: Mapped[Optional["ImageRecord"]] = relationship(
        "ImageRecord",
        foreign_keys=[result_image_id],
        back_populates="result_processes"
    )

    __table_args__ = (
        Index('idx_process_user_id', 'user_id'),
        Index('idx_face_image_id', 'face_image_id'),
        Index('idx_cloth_image_id', 'cloth_image_id'),
        Index('idx_result_image_id', 'result_image_id'),
        Index('idx_completed_at', 'completed_at'),
        Index('idx_status', 'status'),
        CheckConstraint(
            "status IN ('已审核', '已发布', '待审核', '待发布', '已拒绝')",
            name="ck_process_status"
        ),
        CheckConstraint(
            "task_type IN ('swap_face', 'swap_cloth', 'swap_bg', 'swap_all')",
            name="ck_process_task_type"
        )
    )
    
class SystemConfig(Base):
    """系统配置表"""
    __tablename__ = "system_configs"

    id = Column(Integer, primary_key=True, autoincrement=True, comment="配置ID")
    config_key = Column(String(100), nullable=False, comment="配置键")
    config_value = Column(Text, nullable=False, comment="配置值")
    config_type = Column(String(20), nullable=False, comment="配置类型(string/int/float/bool/json)")
    config_description = Column(Text, nullable=True, comment="配置描述")
    is_public = Column(Boolean, default=False, comment="是否公开配置")
    created_at = Column(DateTime, default=func.now(), comment="创建时间")
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间")
    
    __table_args__ = (
        Index('idx_config_key', 'config_key'),
        Index('idx_is_public', 'is_public'),
        CheckConstraint("config_type IN ('string', 'int', 'float', 'bool', 'json')", name="ck_config_type"),
    )

class DatabaseVersion(Base):
    """数据库版本表"""
    __tablename__ = "database_versions"

    id = Column(Integer, primary_key=True, autoincrement=True, comment="版本ID")
    version = Column(String(20), unique=True, nullable=False, comment="版本号")
    description = Column(Text, nullable=True, comment="版本描述")
    applied_at = Column(DateTime, default=func.now(), comment="应用时间")
    migration_file = Column(String(255), nullable=True, comment="迁移文件名")

    __table_args__ = (
        Index('idx_version', 'version'),
        Index('idx_applied_at', 'applied_at'),
    )
