from sqlalchemy import Column, String, Integer, Float, Date, DateTime, Text, Boolean, JSON, ForeignKey, UniqueConstraint
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
from .database import Base
from datetime import datetime


class AuditLog(Base):
    __tablename__ = "audit_logs"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    user_id = Column(Integer, nullable=True, index=True)
    username = Column(String, nullable=False)
    action = Column(String, nullable=False, index=True)
    resource_type = Column(String, nullable=True, index=True)
    resource_id = Column(String, nullable=True)
    details = Column(JSON, default=dict, nullable=True)
    ip_address = Column(String, nullable=True)
    user_agent = Column(String, nullable=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())

    def to_dict(self):
        return {
            "id": self.id,
            "user_id": self.user_id,
            "username": self.username,
            "action": self.action,
            "resource_type": self.resource_type,
            "resource_id": self.resource_id,
            "details": self.details or {},
            "ip_address": self.ip_address,
            "user_agent": self.user_agent,
            "created_at": self.created_at.isoformat() if self.created_at else None
        }


class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    username = Column(String, unique=True, nullable=False, index=True)
    password_hash = Column(String, nullable=False)
    role = Column(String, default="user", nullable=False)
    last_login = Column(DateTime(timezone=True), nullable=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())

    def to_dict(self):
        return {
            "id": self.id,
            "username": self.username,
            "role": self.role,
            "last_login": self.last_login.isoformat() if self.last_login else None,
            "created_at": self.created_at.isoformat() if self.created_at else None
        }


class TopicField(Base):
    __tablename__ = "topic_fields"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    name = Column(String, nullable=False)
    icon = Column(String, nullable=True)
    color = Column(String, nullable=True)
    description = Column(Text, nullable=True)
    parent_id = Column(Integer, ForeignKey("topic_fields.id"), nullable=True)
    sort_order = Column(Integer, default=0)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())

    parent = relationship("TopicField", remote_side=[id], backref="children")
    scoring_fields = relationship("TopicConfigField", back_populates="field", cascade="all, delete-orphan")

    def to_dict(self):
        return {
            "id": self.id,
            "name": self.name,
            "icon": self.icon,
            "color": self.color,
            "description": self.description,
            "parent_id": self.parent_id,
            "sort_order": self.sort_order,
            "is_active": self.is_active,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }


class TopicConfigField(Base):
    __tablename__ = "topic_config_fields"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    field_id = Column(Integer, ForeignKey("topic_fields.id"), nullable=False)
    name = Column(String, nullable=False)
    key = Column(String, nullable=False)
    field_type = Column(String, default="number")  # number/select/multi_select/text
    weight = Column(Float, default=1.0)
    options = Column(JSON, default=list)  # for select/multi_select
    min_value = Column(Float, nullable=True)
    max_value = Column(Float, nullable=True)
    is_required = Column(Boolean, default=False)
    sort_order = Column(Integer, default=0)
    created_at = Column(DateTime(timezone=True), server_default=func.now())

    field = relationship("TopicField", back_populates="scoring_fields")

    def to_dict(self):
        return {
            "id": self.id,
            "field_id": self.field_id,
            "name": self.name,
            "key": self.key,
            "field_type": self.field_type,
            "weight": self.weight,
            "options": self.options or [],
            "min_value": self.min_value,
            "max_value": self.max_value,
            "is_required": self.is_required,
            "sort_order": self.sort_order,
            "created_at": self.created_at.isoformat() if self.created_at else None,
        }


class TopicStatusConfig(Base):
    __tablename__ = "topic_status_configs"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    status = Column(String, unique=True, nullable=False)
    label = Column(String, nullable=False)
    color = Column(String, nullable=True)
    icon = Column(String, nullable=True)
    sort_order = Column(Integer, default=0)
    is_default = Column(Boolean, default=False)
    created_at = Column(DateTime(timezone=True), server_default=func.now())

    def to_dict(self):
        return {
            "id": self.id,
            "status": self.status,
            "label": self.label,
            "color": self.color,
            "icon": self.icon,
            "sort_order": self.sort_order,
            "is_default": self.is_default,
            "created_at": self.created_at.isoformat() if self.created_at else None,
        }


class Topic(Base):
    __tablename__ = "topics"

    id = Column(String, primary_key=True, index=True)
    field_id = Column(Integer, ForeignKey("topic_fields.id"), nullable=True)
    field_name = Column(String, nullable=True)
    title = Column(String, nullable=False)
    format = Column(String)
    core_concept = Column(Text)
    audience_pain = Column(Text)
    unique_angle = Column(Text)
    priority = Column(String)
    priority_score = Column(Integer, default=0)
    total_score = Column(Float)
    status = Column(String, default="pending")
    cases = Column(JSON, default=list)
    source_file = Column(String)
    tags = Column(JSON, default=list)
    custom_data = Column(JSON, default=dict)
    scoring_data = Column(JSON, default=dict)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())
    generated_at = Column(DateTime(timezone=True), nullable=True)
    ready_at = Column(Date)
    published_at = Column(Date)
    compliance_score = Column(Integer)
    platform_urls = Column(JSON, default=dict)
    lock_by = Column(String, nullable=True)
    lock_at = Column(DateTime, nullable=True)

    field = relationship("TopicField", backref="topics")

    @property
    def field_info(self):
        if self.field:
            return self.field.to_dict()
        return None


class Article(Base):
    __tablename__ = "articles"

    id = Column(String, primary_key=True)
    topic_id = Column(String, ForeignKey("topics.id"), nullable=False)
    platform = Column(String, nullable=False)
    file_path = Column(String, nullable=False)
    status = Column(String, default="draft")
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    compliance_score = Column(Integer)
    html_content = Column(Text)
    word_count = Column(Integer, nullable=True)
    outline = Column(Text, nullable=True)


class PublishRecord(Base):
    __tablename__ = "publish_records"

    id = Column(Integer, primary_key=True, index=True)
    topic_id = Column(String, ForeignKey("topics.id"), nullable=False)
    platform = Column(String, nullable=False)
    action = Column(String, nullable=False)
    status = Column(String, nullable=False)
    operator = Column(String, nullable=True)
    description = Column(Text, nullable=True)
    suggestion = Column(Text, nullable=True)
    url = Column(String, nullable=True)
    error_msg = Column(Text, nullable=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())

    topic = relationship("Topic")


class ContentCalendar(Base):
    __tablename__ = "content_calendar"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    topic_id = Column(String, ForeignKey("topics.id"), nullable=True)
    field_id = Column(Integer, ForeignKey("topic_fields.id"), nullable=True)
    title = Column(String, nullable=False)
    planned_date = Column(Date, nullable=False, index=True)
    published_date = Column(Date, nullable=True)
    platform = Column(String, nullable=True)
    status = Column(String, default="planned")  # planned/published/delayed/cancelled
    reminder_time = Column(DateTime, nullable=True)
    notes = Column(Text, nullable=True)
    created_by = Column(String, nullable=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())

    topic = relationship("Topic")

    def to_dict(self):
        return {
            "id": self.id,
            "topic_id": self.topic_id,
            "field_id": self.field_id,
            "title": self.title,
            "planned_date": self.planned_date.isoformat() if self.planned_date else None,
            "published_date": self.published_date.isoformat() if self.published_date else None,
            "platform": self.platform,
            "status": self.status,
            "reminder_time": self.reminder_time.isoformat() if self.reminder_time else None,
            "notes": self.notes,
            "created_by": self.created_by,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }


class ContentMetrics(Base):
    __tablename__ = "content_metrics"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    topic_id = Column(String, ForeignKey("topics.id"), nullable=False, index=True)
    platform = Column(String, nullable=False)
    publish_url = Column(String, nullable=True)
    views = Column(Integer, default=0)
    likes = Column(Integer, default=0)
    favorites = Column(Integer, default=0)
    comments = Column(Integer, default=0)
    shares = Column(Integer, default=0)
    last_fetched = Column(DateTime(timezone=True), nullable=True)
    data_snapshot = Column(JSON, default=dict)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())

    topic = relationship("Topic")

    @property
    def engagement_rate(self):
        total = self.views or 0
        if total == 0:
            return 0
        return round((self.likes or 0) / total * 100, 2)

    def to_dict(self):
        return {
            "id": self.id,
            "topic_id": self.topic_id,
            "platform": self.platform,
            "publish_url": self.publish_url,
            "views": self.views,
            "likes": self.likes,
            "favorites": self.favorites,
            "comments": self.comments,
            "shares": self.shares,
            "engagement_rate": self.engagement_rate,
            "last_fetched": self.last_fetched.isoformat() if self.last_fetched else None,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }


class MediaAsset(Base):
    __tablename__ = "media_assets"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    filename = Column(String, nullable=False)
    file_path = Column(String, nullable=False)
    file_url = Column(String, nullable=True)
    file_type = Column(String, nullable=False)  # image/video/document
    mime_type = Column(String, nullable=True)
    size = Column(Integer, nullable=True)
    width = Column(Integer, nullable=True)
    height = Column(Integer, nullable=True)
    thumbnail_path = Column(String, nullable=True)
    alt_text = Column(String, nullable=True)
    tags = Column(JSON, default=list)
    topic_ids = Column(JSON, default=list)
    usage_count = Column(Integer, default=0)
    uploaded_by = Column(String, nullable=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())

    def to_dict(self):
        return {
            "id": self.id,
            "filename": self.filename,
            "file_path": self.file_path,
            "file_url": self.file_url,
            "file_type": self.file_type,
            "mime_type": self.mime_type,
            "size": self.size,
            "width": self.width,
            "height": self.height,
            "thumbnail_path": self.thumbnail_path,
            "alt_text": self.alt_text,
            "tags": self.tags or [],
            "topic_ids": self.topic_ids or [],
            "usage_count": self.usage_count,
            "uploaded_by": self.uploaded_by,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }


class PlatformConfig(Base):
    __tablename__ = "platform_configs"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    platform = Column(String, unique=True, nullable=False)  # zhihu/wechat/xiaohongshu
    name = Column(String, nullable=False)
    icon = Column(String, nullable=True)
    api_endpoint = Column(String, nullable=True)
    auth_config = Column(JSON, default=dict)
    format_template = Column(JSON, default=dict)
    compliance_rules = Column(JSON, default=dict)
    default_format = Column(Text, nullable=True)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())

    def to_dict(self):
        return {
            "id": self.id,
            "platform": self.platform,
            "name": self.name,
            "icon": self.icon,
            "api_endpoint": self.api_endpoint,
            "format_template": self.format_template or {},
            "compliance_rules": self.compliance_rules or {},
            "default_format": self.default_format,
            "is_active": self.is_active,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }


class ContentTask(Base):
    __tablename__ = "content_tasks"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    topic_id = Column(String, ForeignKey("topics.id"), nullable=True, index=True)
    task_id = Column(String, unique=True, nullable=False)
    stage = Column(String, nullable=False)  # research/outline/writer/optimizer/format/publish
    status = Column(String, default="pending")  # pending/running/completed/failed/cancelled
    progress = Column(Integer, default=0)
    message = Column(Text, nullable=True)
    result_data = Column(JSON, default=dict)
    error_msg = Column(Text, nullable=True)
    started_at = Column(DateTime(timezone=True), nullable=True)
    finished_at = Column(DateTime(timezone=True), nullable=True)
    duration = Column(Integer, nullable=True)
    created_by = Column(String, nullable=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())

    topic = relationship("Topic")

    def to_dict(self):
        return {
            "id": self.id,
            "topic_id": self.topic_id,
            "task_id": self.task_id,
            "stage": self.stage,
            "status": self.status,
            "progress": self.progress,
            "message": self.message,
            "error_msg": self.error_msg,
            "started_at": self.started_at.isoformat() if self.started_at else None,
            "finished_at": self.finished_at.isoformat() if self.finished_at else None,
            "duration": self.duration,
            "created_by": self.created_by,
            "created_at": self.created_at.isoformat() if self.created_at else None,
        }


class Case(Base):
    __tablename__ = "cases"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    title = Column(String, nullable=False)
    field = Column(String, nullable=False)
    summary = Column(Text)
    key_metrics = Column(Text, nullable=True)
    date = Column(String, nullable=True)
    source = Column(String, nullable=True)
    credibility_rating = Column(String, nullable=True)
    china_applicability = Column(String, nullable=True)
    source_url = Column(String, nullable=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())

    def to_dict(self):
        return {
            "id": self.id,
            "title": self.title,
            "field": self.field,
            "summary": self.summary,
            "key_metrics": self.key_metrics,
            "date": self.date,
            "source": self.source,
            "credibility_rating": self.credibility_rating,
            "china_applicability": self.china_applicability,
            "source_url": self.source_url,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }


class TaskLog(Base):
    __tablename__ = "task_logs"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    task_name = Column(String, nullable=False)
    topic_id = Column(String, nullable=True)
    status = Column(String, nullable=False)
    message = Column(Text, nullable=True)
    started_at = Column(DateTime(timezone=True), server_default=func.now())
    finished_at = Column(DateTime(timezone=True), nullable=True)
    duration = Column(Integer, nullable=True)

    def to_dict(self):
        return {
            "id": self.id,
            "task_name": self.task_name,
            "topic_id": self.topic_id,
            "status": self.status,
            "message": self.message,
            "started_at": self.started_at.isoformat() if self.started_at else None,
            "finished_at": self.finished_at.isoformat() if self.finished_at else None,
            "duration": self.duration,
        }


class LLMConfig(Base):
    __tablename__ = "llm_configs"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    name = Column(String, unique=True, nullable=False)
    system_prompt = Column(Text, nullable=True)
    user_prompt_template = Column(Text, nullable=False)
    temperature = Column(Float, default=0.7)
    max_tokens = Column(Integer, default=2000)
    model = Column(String, nullable=True)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())

    def to_dict(self):
        return {
            "id": self.id,
            "name": self.name,
            "system_prompt": self.system_prompt,
            "user_prompt_template": self.user_prompt_template,
            "temperature": self.temperature,
            "max_tokens": self.max_tokens,
            "model": self.model,
            "is_active": self.is_active,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }


class SystemConfig(Base):
    __tablename__ = "system_configs"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    key = Column(String, unique=True, nullable=False)
    value = Column(Text, nullable=True)
    description = Column(String, nullable=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())

    def to_dict(self):
        import json
        return {
            "id": self.id,
            "key": self.key,
            "value": json.loads(self.value) if self.value else None,
            "description": self.description,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }