from __future__ import annotations

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

revision = "0007_knowledge_agent_rebuild"
down_revision = "0006_expand_ai_request_log_text"
branch_labels = None
depends_on = None


def upgrade() -> None:
    for column in [
        sa.Column("source_title", sa.String(255), nullable=True),
        sa.Column("knowledge_type", sa.String(30), nullable=False, server_default="general"),
        sa.Column("review_mode", sa.String(30), nullable=False, server_default="manual"),
        sa.Column("lifecycle_status", sa.String(30), nullable=False, server_default="active"),
        sa.Column("source_status", sa.String(30), nullable=False, server_default="normal"),
        sa.Column("source_error", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("manifest_confirmed", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("current_version_id", sa.BigInteger(), nullable=True),
        sa.Column("pending_version_id", sa.BigInteger(), nullable=True),
        sa.Column("last_synced_at", sa.DateTime(), nullable=True),
        sa.Column("last_published_at", sa.DateTime(), nullable=True),
        sa.Column("migration_status", sa.String(30), nullable=False, server_default="pending"),
    ]:
        op.add_column("sys_knowledge", column)

    op.create_table(
        "sys_knowledge_source_snapshot",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
        sa.Column("sync_job_id", sa.BigInteger(), nullable=True),
        sa.Column("source_title", sa.String(255), nullable=False),
        sa.Column("source_content", mysql.LONGTEXT(), nullable=False),
        sa.Column("content_hash", sa.String(64), nullable=False),
        sa.Column("source_identifier", sa.String(255), nullable=False),
        sa.Column("fetched_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
        sa.Column("created_by", sa.BigInteger(), nullable=True),
        sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_knowledge_source_snapshot", "knowledge_id", "sync_job_id", "content_hash")

    op.create_table(
        "sys_knowledge_version",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
        sa.Column("snapshot_id", sa.BigInteger(), nullable=False),
        sa.Column("version_no", sa.Integer(), nullable=False),
        sa.Column("status", sa.String(30), nullable=False),
        sa.Column("quality_status", sa.String(30), nullable=False, server_default="pending"),
        sa.Column("change_summary", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("quality_report", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("processing_rule_version", sa.String(50), nullable=False),
        sa.Column("generation_model", sa.String(100), nullable=True),
        sa.Column("created_by", sa.BigInteger(), nullable=True),
        sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
        sa.Column("published_by", sa.BigInteger(), nullable=True),
        sa.Column("published_at", sa.DateTime(), nullable=True),
        sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
        sa.ForeignKeyConstraint(["snapshot_id"], ["sys_knowledge_source_snapshot.id"]),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("knowledge_id", "version_no", name="uq_kb_version_no"),
    )
    _indexes("sys_knowledge_version", "knowledge_id", "status")

    op.create_table(
        "sys_knowledge_manifest",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
        sa.Column("version_id", sa.BigInteger(), nullable=False),
        sa.Column("purpose", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("applicable_questions", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("inapplicable_questions", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("core_topics", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("entities", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("boundaries", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("content_hash", sa.String(64), nullable=False),
        sa.Column("change_level", sa.String(20), nullable=False, server_default="major"),
        sa.Column("confirmed", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("confirmed_by", sa.BigInteger(), nullable=True),
        sa.Column("confirmed_at", sa.DateTime(), nullable=True),
        sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
        sa.ForeignKeyConstraint(["version_id"], ["sys_knowledge_version.id"]),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_knowledge_manifest", "knowledge_id", "version_id")

    op.create_table(
        "sys_knowledge_section",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
        sa.Column("version_id", sa.BigInteger(), nullable=False),
        sa.Column("section_key", sa.String(64), nullable=False),
        sa.Column("title", sa.String(255), nullable=False),
        sa.Column("content", mysql.LONGTEXT(), nullable=False),
        sa.Column("source_start", sa.Integer(), nullable=False),
        sa.Column("source_end", sa.Integer(), nullable=False),
        sa.Column("sort_order", sa.Integer(), nullable=False),
        sa.Column("content_hash", sa.String(64), nullable=False),
        sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
        sa.ForeignKeyConstraint(["version_id"], ["sys_knowledge_version.id"]),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_knowledge_section", "knowledge_id", "version_id")

    op.create_table(
        "sys_knowledge_chunk",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
        sa.Column("version_id", sa.BigInteger(), nullable=False),
        sa.Column("section_id", sa.BigInteger(), nullable=False),
        sa.Column("title", sa.String(255), nullable=False),
        sa.Column("content", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("normalized_text", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("keywords", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("synonyms", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("source_start", sa.Integer(), nullable=False),
        sa.Column("source_end", sa.Integer(), nullable=False),
        sa.Column("sort_order", sa.Integer(), nullable=False),
        sa.Column("content_hash", sa.String(64), nullable=False),
        sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
        sa.ForeignKeyConstraint(["version_id"], ["sys_knowledge_version.id"]),
        sa.ForeignKeyConstraint(["section_id"], ["sys_knowledge_section.id"]),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_knowledge_chunk", "knowledge_id", "version_id", "section_id")

    op.create_table(
        "sys_knowledge_card",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
        sa.Column("version_id", sa.BigInteger(), nullable=False),
        sa.Column("section_id", sa.BigInteger(), nullable=False),
        sa.Column("title", sa.String(255), nullable=False),
        sa.Column("summary", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("core_conclusion", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("applicable_questions", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("inapplicable_questions", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("keywords", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("synonyms", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("entities", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("risk_level", sa.String(20), nullable=False, server_default="normal"),
        sa.Column("source_range", sa.String(100), nullable=False),
        sa.Column("content_hash", sa.String(64), nullable=False),
        sa.Column("generation_model", sa.String(100), nullable=True),
        sa.Column("generation_rule_version", sa.String(50), nullable=False),
        sa.Column("review_status", sa.String(20), nullable=False, server_default="pending"),
        sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
        sa.ForeignKeyConstraint(["version_id"], ["sys_knowledge_version.id"]),
        sa.ForeignKeyConstraint(["section_id"], ["sys_knowledge_section.id"]),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_knowledge_card", "knowledge_id", "version_id", "section_id")

    _create_job_and_log_tables()


def _create_job_and_log_tables() -> None:
    op.create_table(
        "sys_knowledge_sync_job",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
        sa.Column("mode", sa.String(30), nullable=False),
        sa.Column("status", sa.String(30), nullable=False),
        sa.Column("stage", sa.String(50), nullable=False),
        sa.Column("progress", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("source_error", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("result_summary", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("requested_by", sa.BigInteger(), nullable=False),
        sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
        sa.Column("started_at", sa.DateTime(), nullable=True),
        sa.Column("finished_at", sa.DateTime(), nullable=True),
        sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_knowledge_sync_job", "knowledge_id", "status")

    op.create_table(
        "sys_knowledge_review_record",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
        sa.Column("version_id", sa.BigInteger(), nullable=False),
        sa.Column("card_id", sa.BigInteger(), nullable=True),
        sa.Column("action", sa.String(30), nullable=False),
        sa.Column("reason", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("reviewed_by", sa.BigInteger(), nullable=False),
        sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
        sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
        sa.ForeignKeyConstraint(["version_id"], ["sys_knowledge_version.id"]),
        sa.ForeignKeyConstraint(["card_id"], ["sys_knowledge_card.id"]),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_knowledge_review_record", "knowledge_id", "version_id")

    op.create_table(
        "sys_knowledge_publish_log",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
        sa.Column("from_version_id", sa.BigInteger(), nullable=True),
        sa.Column("to_version_id", sa.BigInteger(), nullable=True),
        sa.Column("action", sa.String(30), nullable=False),
        sa.Column("keep_open", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("detail_json", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("operated_by", sa.BigInteger(), nullable=False),
        sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
        sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_knowledge_publish_log", "knowledge_id")

    op.create_table(
        "sys_knowledge_retrieval_log",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("session_id", sa.BigInteger(), nullable=True),
        sa.Column("message_id", sa.BigInteger(), nullable=True),
        sa.Column("user_id", sa.BigInteger(), nullable=True),
        sa.Column("question", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("catalog_snapshot", mysql.LONGTEXT(), nullable=False),
        sa.Column("catalog_hash", sa.String(64), nullable=False),
        sa.Column("safety_rule_version", sa.String(50), nullable=False),
        sa.Column("knowledge_called", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("selected_knowledge_ids", sa.String(500), nullable=True),
        sa.Column("query_terms", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("tool_trace", mysql.LONGTEXT(), nullable=True),
        sa.Column("final_section_ids", sa.String(500), nullable=True),
        sa.Column("discarded_conflicts", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("final_answer", mysql.LONGTEXT(), nullable=True),
        sa.Column("status", sa.String(20), nullable=False),
        sa.Column("tool_cost_ms", sa.Integer(), nullable=True),
        sa.Column("total_cost_ms", sa.Integer(), nullable=True),
        sa.Column("error_message", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("attention_created", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_knowledge_retrieval_log", "session_id", "message_id", "user_id")

    op.create_table(
        "sys_knowledge_retrieval_candidate",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("retrieval_log_id", sa.BigInteger(), nullable=False),
        sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
        sa.Column("version_id", sa.BigInteger(), nullable=False),
        sa.Column("chunk_id", sa.BigInteger(), nullable=False),
        sa.Column("section_id", sa.BigInteger(), nullable=False),
        sa.Column("lexical_score", sa.String(30), nullable=False),
        sa.Column("rerank_score", sa.String(30), nullable=True),
        sa.Column("selected", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("discard_reason", sa.String(255), nullable=True),
        sa.ForeignKeyConstraint(["retrieval_log_id"], ["sys_knowledge_retrieval_log.id"]),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_knowledge_retrieval_candidate", "retrieval_log_id", "knowledge_id", "version_id")

    op.create_table(
        "sys_human_attention_record",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("session_id", sa.BigInteger(), nullable=False),
        sa.Column("message_id", sa.BigInteger(), nullable=False),
        sa.Column("user_id", sa.BigInteger(), nullable=False),
        sa.Column("trigger_message", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("problem_summary", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("trigger_reason", mysql.MEDIUMTEXT(), nullable=False),
        sa.Column("priority", sa.String(20), nullable=False),
        sa.Column("status", sa.String(20), nullable=False, server_default="pending"),
        sa.Column("handler_id", sa.BigInteger(), nullable=True),
        sa.Column("handler_note", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
        sa.Column("updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_human_attention_record", "session_id", "message_id", "user_id", "priority", "status")

    op.create_table(
        "sys_human_attention_history",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("attention_id", sa.BigInteger(), nullable=False),
        sa.Column("from_status", sa.String(20), nullable=True),
        sa.Column("to_status", sa.String(20), nullable=False),
        sa.Column("note", mysql.MEDIUMTEXT(), nullable=True),
        sa.Column("operated_by", sa.BigInteger(), nullable=False),
        sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
        sa.ForeignKeyConstraint(["attention_id"], ["sys_human_attention_record.id"]),
        sa.PrimaryKeyConstraint("id"),
    )
    _indexes("sys_human_attention_history", "attention_id")


def _indexes(table: str, *columns: str) -> None:
    for column in columns:
        op.create_index(f"ix_{table}_{column}", table, [column])


def downgrade() -> None:
    for table in [
        "sys_human_attention_history",
        "sys_human_attention_record",
        "sys_knowledge_retrieval_candidate",
        "sys_knowledge_retrieval_log",
        "sys_knowledge_publish_log",
        "sys_knowledge_review_record",
        "sys_knowledge_sync_job",
        "sys_knowledge_card",
        "sys_knowledge_chunk",
        "sys_knowledge_section",
        "sys_knowledge_manifest",
        "sys_knowledge_version",
        "sys_knowledge_source_snapshot",
    ]:
        op.drop_table(table)
    for column in [
        "migration_status", "last_published_at", "last_synced_at", "pending_version_id",
        "current_version_id", "manifest_confirmed", "source_error", "source_status",
        "lifecycle_status", "review_mode", "knowledge_type", "source_title",
    ]:
        op.drop_column("sys_knowledge", column)
