from __future__ import annotations

from datetime import datetime

from sqlalchemy import BigInteger, DateTime, ForeignKey, Integer, String, Text, UniqueConstraint, func
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.models.base import Base, TimestampMixin

PRIMARY_KEY_TYPE = BigInteger().with_variant(Integer, "sqlite")


class Knowledge(Base, TimestampMixin):
    __tablename__ = "sys_knowledge"
    __table_args__ = (UniqueConstraint("feishu_space_id", "feishu_node_id", name="uq_knowledge_feishu_node"),)

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    name: Mapped[str] = mapped_column(String(100), nullable=False)
    feishu_space_id: Mapped[str] = mapped_column(String(100), nullable=False)
    feishu_node_id: Mapped[str] = mapped_column(String(100), nullable=False)
    status: Mapped[int] = mapped_column(default=1, nullable=False)
    remark: Mapped[str | None] = mapped_column(String(255), nullable=True)
    source_title: Mapped[str | None] = mapped_column(String(255), nullable=True)
    knowledge_type: Mapped[str] = mapped_column(String(30), default="general", nullable=False)
    review_mode: Mapped[str] = mapped_column(String(30), default="automatic", nullable=False)
    lifecycle_status: Mapped[str] = mapped_column(String(30), default="active", nullable=False)
    source_status: Mapped[str] = mapped_column(String(30), default="normal", nullable=False)
    source_error: Mapped[str | None] = mapped_column(Text, nullable=True)
    manifest_confirmed: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    current_version_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    pending_version_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    last_synced_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
    last_published_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
    migration_status: Mapped[str] = mapped_column(String(30), default="pending", nullable=False)

    user_permissions: Mapped[list["UserKnowledgePermission"]] = relationship(
        "UserKnowledgePermission", back_populates="knowledge"
    )


class UserKnowledgePermission(Base, TimestampMixin):
    __tablename__ = "sys_user_kb"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("sys_user.id"), index=True, nullable=False)
    knowledge_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge.id"), index=True, nullable=False)
    effective_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
    expired_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
    created_by: Mapped[int | None] = mapped_column(BigInteger, nullable=True)

    user: Mapped["User"] = relationship("User", back_populates="knowledge_permissions")
    knowledge: Mapped[Knowledge] = relationship("Knowledge", back_populates="user_permissions")


class KnowledgeSourceSnapshot(Base):
    __tablename__ = "sys_knowledge_source_snapshot"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    knowledge_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge.id"), index=True, nullable=False)
    sync_job_id: Mapped[int | None] = mapped_column(BigInteger, index=True, nullable=True)
    source_title: Mapped[str] = mapped_column(String(255), nullable=False)
    source_content: Mapped[str] = mapped_column(Text, nullable=False)
    content_hash: Mapped[str] = mapped_column(String(64), index=True, nullable=False)
    source_identifier: Mapped[str] = mapped_column(String(255), nullable=False)
    fetched_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
    created_by: Mapped[int | None] = mapped_column(BigInteger, nullable=True)


class KnowledgeVersion(Base):
    __tablename__ = "sys_knowledge_version"
    __table_args__ = (UniqueConstraint("knowledge_id", "version_no", name="uq_kb_version_no"),)

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    knowledge_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge.id"), index=True, nullable=False)
    snapshot_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge_source_snapshot.id"), nullable=False)
    version_no: Mapped[int] = mapped_column(Integer, nullable=False)
    status: Mapped[str] = mapped_column(String(30), index=True, nullable=False)
    quality_status: Mapped[str] = mapped_column(String(30), default="pending", nullable=False)
    change_summary: Mapped[str | None] = mapped_column(Text, nullable=True)
    quality_report: Mapped[str | None] = mapped_column(Text, nullable=True)
    processing_rule_version: Mapped[str] = mapped_column(String(50), nullable=False)
    generation_model: Mapped[str | None] = mapped_column(String(100), nullable=True)
    created_by: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
    published_by: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    published_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)


class KnowledgeManifest(Base):
    __tablename__ = "sys_knowledge_manifest"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    knowledge_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge.id"), index=True, nullable=False)
    version_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge_version.id"), index=True, nullable=False)
    purpose: Mapped[str] = mapped_column(Text, nullable=False)
    applicable_questions: Mapped[str] = mapped_column(Text, nullable=False)
    inapplicable_questions: Mapped[str] = mapped_column(Text, nullable=False)
    core_topics: Mapped[str] = mapped_column(Text, nullable=False)
    entities: Mapped[str | None] = mapped_column(Text, nullable=True)
    boundaries: Mapped[str | None] = mapped_column(Text, nullable=True)
    content_hash: Mapped[str] = mapped_column(String(64), nullable=False)
    change_level: Mapped[str] = mapped_column(String(20), default="major", nullable=False)
    confirmed: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    confirmed_by: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    confirmed_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)


class KnowledgeSection(Base):
    __tablename__ = "sys_knowledge_section"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    knowledge_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge.id"), index=True, nullable=False)
    version_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge_version.id"), index=True, nullable=False)
    section_key: Mapped[str] = mapped_column(String(64), nullable=False)
    title: Mapped[str] = mapped_column(String(255), nullable=False)
    content: Mapped[str] = mapped_column(Text, nullable=False)
    source_start: Mapped[int] = mapped_column(Integer, nullable=False)
    source_end: Mapped[int] = mapped_column(Integer, nullable=False)
    sort_order: Mapped[int] = mapped_column(Integer, nullable=False)
    content_hash: Mapped[str] = mapped_column(String(64), nullable=False)


class KnowledgeChunk(Base):
    __tablename__ = "sys_knowledge_chunk"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    knowledge_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge.id"), index=True, nullable=False)
    version_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge_version.id"), index=True, nullable=False)
    section_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge_section.id"), index=True, nullable=False)
    title: Mapped[str] = mapped_column(String(255), nullable=False)
    content: Mapped[str] = mapped_column(Text, nullable=False)
    normalized_text: Mapped[str] = mapped_column(Text, nullable=False)
    keywords: Mapped[str | None] = mapped_column(Text, nullable=True)
    synonyms: Mapped[str | None] = mapped_column(Text, nullable=True)
    source_start: Mapped[int] = mapped_column(Integer, nullable=False)
    source_end: Mapped[int] = mapped_column(Integer, nullable=False)
    sort_order: Mapped[int] = mapped_column(Integer, nullable=False)
    content_hash: Mapped[str] = mapped_column(String(64), nullable=False)


class KnowledgeCard(Base):
    __tablename__ = "sys_knowledge_card"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    knowledge_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge.id"), index=True, nullable=False)
    version_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge_version.id"), index=True, nullable=False)
    section_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge_section.id"), index=True, nullable=False)
    title: Mapped[str] = mapped_column(String(255), nullable=False)
    summary: Mapped[str] = mapped_column(Text, nullable=False)
    core_conclusion: Mapped[str] = mapped_column(Text, nullable=False)
    applicable_questions: Mapped[str] = mapped_column(Text, nullable=False)
    inapplicable_questions: Mapped[str] = mapped_column(Text, nullable=False)
    keywords: Mapped[str] = mapped_column(Text, nullable=False)
    synonyms: Mapped[str | None] = mapped_column(Text, nullable=True)
    entities: Mapped[str | None] = mapped_column(Text, nullable=True)
    risk_level: Mapped[str] = mapped_column(String(20), default="normal", nullable=False)
    source_range: Mapped[str] = mapped_column(String(100), nullable=False)
    content_hash: Mapped[str] = mapped_column(String(64), nullable=False)
    generation_model: Mapped[str | None] = mapped_column(String(100), nullable=True)
    generation_rule_version: Mapped[str] = mapped_column(String(50), nullable=False)
    review_status: Mapped[str] = mapped_column(String(20), default="pending", nullable=False)


class KnowledgeSyncJob(Base):
    __tablename__ = "sys_knowledge_sync_job"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    knowledge_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge.id"), index=True, nullable=False)
    mode: Mapped[str] = mapped_column(String(30), nullable=False)
    status: Mapped[str] = mapped_column(String(30), index=True, nullable=False)
    stage: Mapped[str] = mapped_column(String(50), nullable=False)
    progress: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    source_error: Mapped[str | None] = mapped_column(Text, nullable=True)
    result_summary: Mapped[str | None] = mapped_column(Text, nullable=True)
    requested_by: Mapped[int] = mapped_column(BigInteger, nullable=False)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
    started_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
    finished_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)


class KnowledgeReviewRecord(Base):
    __tablename__ = "sys_knowledge_review_record"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    knowledge_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge.id"), index=True, nullable=False)
    version_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge_version.id"), index=True, nullable=False)
    card_id: Mapped[int | None] = mapped_column(ForeignKey("sys_knowledge_card.id"), nullable=True)
    action: Mapped[str] = mapped_column(String(30), nullable=False)
    reason: Mapped[str | None] = mapped_column(Text, nullable=True)
    reviewed_by: Mapped[int] = mapped_column(BigInteger, nullable=False)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)


class KnowledgePublishLog(Base):
    __tablename__ = "sys_knowledge_publish_log"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    knowledge_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge.id"), index=True, nullable=False)
    from_version_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    to_version_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    action: Mapped[str] = mapped_column(String(30), nullable=False)
    keep_open: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    detail_json: Mapped[str | None] = mapped_column(Text, nullable=True)
    operated_by: Mapped[int] = mapped_column(BigInteger, nullable=False)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)


class KnowledgeRetrievalLog(Base):
    __tablename__ = "sys_knowledge_retrieval_log"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    session_id: Mapped[int | None] = mapped_column(BigInteger, index=True, nullable=True)
    message_id: Mapped[int | None] = mapped_column(BigInteger, index=True, nullable=True)
    user_id: Mapped[int | None] = mapped_column(BigInteger, index=True, nullable=True)
    question: Mapped[str] = mapped_column(Text, nullable=False)
    catalog_snapshot: Mapped[str] = mapped_column(Text, nullable=False)
    catalog_hash: Mapped[str] = mapped_column(String(64), nullable=False)
    safety_rule_version: Mapped[str] = mapped_column(String(50), nullable=False)
    knowledge_called: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    selected_knowledge_ids: Mapped[str | None] = mapped_column(String(500), nullable=True)
    query_terms: Mapped[str | None] = mapped_column(Text, nullable=True)
    tool_trace: Mapped[str | None] = mapped_column(Text, nullable=True)
    final_section_ids: Mapped[str | None] = mapped_column(String(500), nullable=True)
    discarded_conflicts: Mapped[str | None] = mapped_column(Text, nullable=True)
    final_answer: Mapped[str | None] = mapped_column(Text, nullable=True)
    status: Mapped[str] = mapped_column(String(20), nullable=False)
    tool_cost_ms: Mapped[int | None] = mapped_column(Integer, nullable=True)
    total_cost_ms: Mapped[int | None] = mapped_column(Integer, nullable=True)
    error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
    attention_created: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)


class KnowledgeRetrievalCandidate(Base):
    __tablename__ = "sys_knowledge_retrieval_candidate"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    retrieval_log_id: Mapped[int] = mapped_column(ForeignKey("sys_knowledge_retrieval_log.id"), index=True, nullable=False)
    knowledge_id: Mapped[int] = mapped_column(BigInteger, index=True, nullable=False)
    version_id: Mapped[int] = mapped_column(BigInteger, index=True, nullable=False)
    chunk_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
    section_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
    lexical_score: Mapped[str] = mapped_column(String(30), nullable=False)
    rerank_score: Mapped[str | None] = mapped_column(String(30), nullable=True)
    selected: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    discard_reason: Mapped[str | None] = mapped_column(String(255), nullable=True)


class HumanAttentionRecord(Base):
    __tablename__ = "sys_human_attention_record"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    session_id: Mapped[int] = mapped_column(BigInteger, index=True, nullable=False)
    message_id: Mapped[int] = mapped_column(BigInteger, index=True, nullable=False)
    user_id: Mapped[int] = mapped_column(BigInteger, index=True, nullable=False)
    trigger_message: Mapped[str] = mapped_column(Text, nullable=False)
    problem_summary: Mapped[str] = mapped_column(Text, nullable=False)
    trigger_reason: Mapped[str] = mapped_column(Text, nullable=False)
    priority: Mapped[str] = mapped_column(String(20), index=True, nullable=False)
    status: Mapped[str] = mapped_column(String(20), index=True, default="pending", nullable=False)
    handler_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    handler_note: Mapped[str | None] = mapped_column(Text, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
    updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now(), nullable=False)


class HumanAttentionHistory(Base):
    __tablename__ = "sys_human_attention_history"

    id: Mapped[int] = mapped_column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
    attention_id: Mapped[int] = mapped_column(ForeignKey("sys_human_attention_record.id"), index=True, nullable=False)
    from_status: Mapped[str | None] = mapped_column(String(20), nullable=True)
    to_status: Mapped[str] = mapped_column(String(20), nullable=False)
    note: Mapped[str | None] = mapped_column(Text, nullable=True)
    operated_by: Mapped[int] = mapped_column(BigInteger, nullable=False)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
