from sqlalchemy import (
    JSON,
    BigInteger,
    Boolean,
    Column,
    Date,
    Float,
    ForeignKey,
    Integer,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy.orm import relationship

from app.models.base import BaseModel


class KnowledgeBase(BaseModel):
    __tablename__ = "knowledge_bases"
    name = Column(String(100), nullable=False)
    code = Column(String(100), nullable=True)
    description = Column(Text, nullable=True)
    icon = Column(String(50), default="📚")
    type = Column(String(50), default="general")
    status = Column(String(20), default="enabled")
    is_public = Column(Boolean, default=True)
    doc_count = Column(Integer, default=0)
    qa_count = Column(Integer, default=0)
    entity_count = Column(Integer, default=0)
    tenant_id = Column(Integer, ForeignKey("public.tenants.id"), nullable=False, index=True)
    created_by = Column(Integer, ForeignKey("public.users.id"), nullable=True, index=True)
    graph_status = Column(String(50), default="not_built")
    categories = relationship("KnowledgeCategory", back_populates="knowledge_base")


class KnowledgeCategory(BaseModel):
    __tablename__ = "knowledge_categories"
    knowledge_base_id = Column(Integer, ForeignKey("knowledge_bases.id"), nullable=True)
    name = Column(String(100), nullable=False)
    description = Column(Text, nullable=True)
    parent_id = Column(Integer, ForeignKey("knowledge_categories.id"), nullable=True)
    icon = Column(String(50), nullable=True)
    color = Column(String(20), nullable=True)
    sort_order = Column(Integer, default=0)
    knowledge_base = relationship("KnowledgeBase", back_populates="categories")
    documents = relationship("KnowledgeDocument", back_populates="category")
    parent = relationship(
        "KnowledgeCategory",
        remote_side="KnowledgeCategory.id",
        backref="children",
        foreign_keys=[parent_id],
    )


class TagCategory(BaseModel):
    __tablename__ = "tag_categories"
    tenant_id = Column(Integer, ForeignKey("public.tenants.id"), nullable=False, index=True)
    name = Column(String(100), nullable=False)
    code = Column(String(50), nullable=False, unique=True)
    description = Column(Text, nullable=True)
    part_number = Column(Integer, nullable=False)
    sort_order = Column(Integer, default=0)
    icon = Column(String(50), nullable=True)
    color = Column(String(20), nullable=True)
    tags = relationship("KnowledgeTag", back_populates="category")


class KnowledgeTag(BaseModel):
    __tablename__ = "knowledge_tags"
    tenant_id = Column(Integer, ForeignKey("public.tenants.id"), nullable=False, index=True)
    name = Column(String(50), nullable=False, unique=True)
    description = Column(Text, nullable=True)
    parent_id = Column(Integer, ForeignKey("knowledge_tags.id"), nullable=True, index=True)
    tag_category_id = Column(Integer, ForeignKey("tag_categories.id"), nullable=True, index=True)
    tag_code = Column(String(50), nullable=True, index=True)
    is_predefined = Column(Boolean, default=False, index=True)
    is_system = Column(Boolean, default=False)
    keywords = Column(JSON, nullable=True)
    search_weight = Column(Float, default=1.0)
    search_priority = Column(Integer, default=0)
    icon = Column(String(50), nullable=True, default="🏷️")
    color = Column(String(20), nullable=True, default="#6366f1")
    sort_order = Column(Integer, default=0)
    status = Column(String(20), default="enabled")
    category = relationship("TagCategory", back_populates="tags")
    parent = relationship(
        "KnowledgeTag", remote_side="KnowledgeTag.id", backref="children", foreign_keys=[parent_id]
    )
    documents = relationship("KnowledgeDocument", secondary="document_tags", back_populates="tags")


class TagAutoRule(BaseModel):
    __tablename__ = "tag_auto_rules"
    tenant_id = Column(Integer, ForeignKey("public.tenants.id"), nullable=False, index=True)
    tag_id = Column(Integer, ForeignKey("knowledge_tags.id"), nullable=False, index=True)
    rule_type = Column(String(50), nullable=False)
    rule_config = Column(JSON, nullable=False)
    confidence_threshold = Column(Float, default=0.6)
    is_active = Column(Boolean, default=True)
    priority = Column(Integer, default=0)
    tag = relationship("KnowledgeTag", backref="auto_rules")


class KnowledgeDocument(BaseModel):
    __tablename__ = "knowledge_documents"
    title = Column(String(255), nullable=False, index=True)
    content = Column(Text, nullable=False)
    summary = Column(Text, nullable=True)
    category_id = Column(Integer, ForeignKey("knowledge_categories.id"), nullable=True, index=True)
    tenant_id = Column(Integer, ForeignKey("public.tenants.id"), nullable=False, index=True)
    author_id = Column(Integer, ForeignKey("public.users.id"), nullable=False, index=True)
    source = Column(String(255), nullable=True)
    reference_url = Column(String(500), nullable=True)
    file_path = Column(String(500), nullable=True)
    file_type = Column(String(50), nullable=True)
    status = Column(String(20), default="draft")
    is_public = Column(Boolean, default=True)
    view_count = Column(Integer, default=0)
    is_vectorized = Column(Boolean, default=False)
    vector_model = Column(String(100), nullable=True)
    vectorization_status = Column(String(50), default="pending")
    vectorization_progress = Column(Integer, default=0)
    vectorization_error = Column(Text, nullable=True)
    graph_status = Column(String(50), default="pending")
    entity_count = Column(Integer, default=0)
    segmentation_mode = Column(String(50), default="automatic")
    chunk_size = Column(Integer, default=1000)
    chunk_overlap = Column(Integer, default=200)
    splitter_type = Column(String(50), default="recursive")
    window_size = Column(Integer, default=4, nullable=True)
    enable_parent_child = Column(Boolean, default=False)
    enable_reference_extraction = Column(Boolean, default=True)
    character_count = Column(Integer, default=0)
    recall_count = Column(Integer, default=0)
    data_center_doc_id = Column(Integer, nullable=True)
    doc_type = Column(String(50), nullable=True)
    doc_number = Column(String(100), nullable=True)
    issuing_authority = Column(String(200), nullable=True)
    doc_number_year = Column(Integer, nullable=True)
    doc_number_serial = Column(Integer, nullable=True)
    issue_date = Column(Date, nullable=True)
    effective_date = Column(Date, nullable=True)
    expire_date = Column(Date, nullable=True)
    doc_status = Column(String(20), nullable=True)
    supersedes_doc_ids = Column(JSON, nullable=True)
    superseded_by_doc_id = Column(
        Integer, ForeignKey("knowledge_documents.id", ondelete="SET NULL"), nullable=True
    )
    tax_type_tags = Column(JSON, nullable=True)
    has_attachment = Column(Boolean, default=False)
    attachment_types = Column(JSON, nullable=True)
    parse_quality_score = Column(Float, nullable=True)
    content_hash = Column(String(64), nullable=True, index=True)
    version_number = Column(Integer, default=1)
    category = relationship("KnowledgeCategory", back_populates="documents")
    author = relationship("User", foreign_keys=[author_id])
    tags = relationship("KnowledgeTag", secondary="document_tags")
    vectors = relationship(
        "DocumentVector", back_populates="document", cascade="all, delete-orphan"
    )
    versions = relationship(
        "DocumentVersion", back_populates="document", cascade="all, delete-orphan"
    )


class DocumentTag(BaseModel):
    __tablename__ = "document_tags"
    __table_args__ = {"extend_existing": True}
    document_id = Column(
        Integer, ForeignKey("knowledge_documents.id", ondelete="CASCADE"), primary_key=True
    )
    tag_id = Column(Integer, ForeignKey("knowledge_tags.id", ondelete="CASCADE"), primary_key=True)
    id = None


class DocumentVector(BaseModel):
    __tablename__ = "document_vectors"
    document_id = Column(Integer, ForeignKey("knowledge_documents.id"), nullable=False)
    chunk_index = Column(Integer, default=0)
    chunk_text = Column(Text, nullable=False)
    vector = Column(JSON, nullable=True)
    milvus_id = Column(String(100), nullable=True)
    model_name = Column(String(100), nullable=False)
    parent_chunk_id = Column(String(100), nullable=True, index=True)
    is_parent = Column(Boolean, server_default="false", nullable=False, index=True)
    chunk_level = Column(String(20), nullable=True)
    prev_chunk_id = Column(String(100), nullable=True)
    next_chunk_id = Column(String(100), nullable=True)
    doc_type = Column(String(50), nullable=True, index=True)
    doc_number = Column(String(100), nullable=True)
    issuing_authority = Column(String(100), nullable=True)
    references = Column(JSON, nullable=True)
    chunk_id = Column(String(100), nullable=True, index=True)
    doc_status = Column(String(20), nullable=True)
    issue_date_int = Column(BigInteger, nullable=True)
    chunk_type = Column(String(20), nullable=True, index=True)
    media_path = Column(String(500), nullable=True)
    document = relationship("KnowledgeDocument", back_populates="vectors")


class DocumentVersion(BaseModel):
    __tablename__ = "document_versions"
    document_id = Column(Integer, ForeignKey("knowledge_documents.id"), nullable=False)
    version_number = Column(Integer, nullable=False)
    title = Column(String(255), nullable=False)
    content = Column(Text, nullable=False)
    change_summary = Column(Text, nullable=True)
    editor_id = Column(Integer, ForeignKey("public.users.id"), nullable=False)
    document = relationship("KnowledgeDocument", back_populates="versions")
    editor = relationship("User", foreign_keys=[editor_id])


class KnowledgeQA(BaseModel):
    __tablename__ = "knowledge_qa"
    question = Column(Text, nullable=False)
    answer = Column(Text, nullable=False)
    category_id = Column(Integer, ForeignKey("knowledge_categories.id"), nullable=True)
    related_documents = Column(JSON, nullable=True)
    is_vectorized = Column(Boolean, default=False)
    question_vector = Column(JSON, nullable=True)
    vector_model = Column(String(100), nullable=True)
    use_count = Column(Integer, default=0)
    helpful_count = Column(Integer, default=0)
    status = Column(String(20), default="active")
    created_by = Column(Integer, ForeignKey("public.users.id"), nullable=False)
    category = relationship("KnowledgeCategory")
    creator = relationship("User", foreign_keys=[created_by])


class KnowledgeMetadataField(BaseModel):
    __tablename__ = "knowledge_metadata_fields"
    knowledge_base_id = Column(
        Integer, ForeignKey("knowledge_bases.id"), nullable=False, index=True
    )
    field_name = Column(String(100), nullable=False)
    field_key = Column(String(100), nullable=False)
    field_type = Column(String(20), nullable=False)
    field_options = Column(JSON, nullable=True)
    default_value = Column(String(500), nullable=True)
    is_required = Column(Boolean, default=False)
    sort_order = Column(Integer, default=0)
    description = Column(Text, nullable=True)
    knowledge_base = relationship("KnowledgeBase", backref="metadata_fields")
    __table_args__ = (UniqueConstraint("knowledge_base_id", "field_key", name="uq_kb_field_key"),)


class DocumentMetadataValue(BaseModel):
    __tablename__ = "document_metadata_values"
    document_id = Column(Integer, ForeignKey("knowledge_documents.id"), nullable=False, index=True)
    field_id = Column(
        Integer, ForeignKey("knowledge_metadata_fields.id"), nullable=False, index=True
    )
    value = Column(Text, nullable=True)
    document = relationship("KnowledgeDocument", backref="metadata_values")
    field = relationship("KnowledgeMetadataField")
    __table_args__ = (UniqueConstraint("document_id", "field_id", name="uq_doc_field"),)


class GraphBuildStatus(BaseModel):
    __tablename__ = "graph_build_status"
    knowledge_base_id = Column(
        Integer, ForeignKey("knowledge_bases.id"), nullable=False, index=True
    )
    status = Column(String(50), nullable=True)
    error_message = Column(Text, nullable=True)
    node_count = Column(Integer, nullable=True)
    edge_count = Column(Integer, nullable=True)


class GraphEntity(BaseModel):
    __tablename__ = "graph_entities"
    kb_id = Column(Integer, ForeignKey("knowledge_bases.id"), nullable=False, index=True)
    entity_type = Column(String(100), nullable=True)
    entity_name = Column(String(500), nullable=True)
    properties = Column(JSON, nullable=True)


class KnowledgeBaseMetadata(BaseModel):
    __tablename__ = "knowledge_base_metadata"
    knowledge_base_id = Column(
        Integer, ForeignKey("knowledge_bases.id"), nullable=False, index=True
    )
    key = Column(String(200), nullable=False)
    value = Column(Text, nullable=True)


class KnowledgeBaseMetadataField(BaseModel):
    __tablename__ = "knowledge_base_metadata_fields"
    knowledge_base_id = Column(
        Integer, ForeignKey("knowledge_bases.id"), nullable=False, index=True
    )
    field_key = Column(String(200), nullable=False)
    field_label = Column(String(200), nullable=True)
    field_type = Column(String(50), nullable=True)
    is_required = Column(Boolean, default=False)
    sort_order = Column(Integer, default=0)


class MetadataField(BaseModel):
    __tablename__ = "metadata_fields"
    knowledge_base_id = Column(
        Integer, ForeignKey("knowledge_bases.id"), nullable=False, index=True
    )
    field_key = Column(String(200), nullable=False)
    field_label = Column(String(200), nullable=True)
    field_type = Column(String(50), nullable=True)
    is_required = Column(Boolean, default=False)
    sort_order = Column(Integer, default=0)
