"""Initial migration

Revision ID: 001
Revises:
Create Date: 2024-01-01 00:00:00.000000

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision: str = "001"
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    # sys_dept
    op.create_table(
        "sys_dept",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("name", sa.String(100), nullable=False),
        sa.Column("parent_id", sa.Integer(), sa.ForeignKey("sys_dept.id"), nullable=True),
        sa.Column("sort_order", sa.Integer(), default=0),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # sys_role
    op.create_table(
        "sys_role",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("name", sa.String(50), unique=True, nullable=False),
        sa.Column("code", sa.String(50), unique=True, nullable=False),
        sa.Column("description", sa.String(200)),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # sys_user
    op.create_table(
        "sys_user",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("username", sa.String(50), unique=True, nullable=False, index=True),
        sa.Column("email", sa.String(100), unique=True, nullable=True),
        sa.Column("hashed_password", sa.String(255), nullable=False),
        sa.Column("real_name", sa.String(50)),
        sa.Column("phone", sa.String(20)),
        sa.Column("is_active", sa.Boolean(), default=True),
        sa.Column("is_superuser", sa.Boolean(), default=False),
        sa.Column("dept_id", sa.Integer(), sa.ForeignKey("sys_dept.id"), nullable=True),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
        sa.Column("updated_at", sa.DateTime(), default=sa.func.now(), onupdate=sa.func.now()),
    )

    # sys_user_role
    op.create_table(
        "sys_user_role",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("user_id", sa.Integer(), sa.ForeignKey("sys_user.id"), nullable=False),
        sa.Column("role_id", sa.Integer(), sa.ForeignKey("sys_role.id"), nullable=False),
    )

    # data_source
    op.create_table(
        "data_source",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("name", sa.String(100), nullable=False),
        sa.Column("source_type", sa.String(50), nullable=False),
        sa.Column("host", sa.String(200)),
        sa.Column("port", sa.Integer()),
        sa.Column("database_name", sa.String(100)),
        sa.Column("username", sa.String(100)),
        sa.Column("encrypted_password", sa.Text()),
        sa.Column("extra_params", sa.Text()),
        sa.Column("status", sa.String(20), default="active"),
        sa.Column("dept_id", sa.Integer(), sa.ForeignKey("sys_dept.id"), nullable=True),
        sa.Column("created_by", sa.Integer(), sa.ForeignKey("sys_user.id")),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
        sa.Column("updated_at", sa.DateTime(), default=sa.func.now(), onupdate=sa.func.now()),
    )

    # meta_database
    op.create_table(
        "meta_database",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("source_id", sa.Integer(), sa.ForeignKey("data_source.id"), nullable=False),
        sa.Column("name", sa.String(100), nullable=False),
        sa.Column("charset", sa.String(50)),
        sa.Column("table_count", sa.Integer(), default=0),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # meta_table
    op.create_table(
        "meta_table",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("database_id", sa.Integer(), sa.ForeignKey("meta_database.id"), nullable=False),
        sa.Column("name", sa.String(200), nullable=False),
        sa.Column("comment", sa.String(500)),
        sa.Column("row_count", sa.BigInteger(), default=0),
        sa.Column("column_count", sa.Integer(), default=0),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # meta_column
    op.create_table(
        "meta_column",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("table_id", sa.Integer(), sa.ForeignKey("meta_table.id"), nullable=False),
        sa.Column("name", sa.String(200), nullable=False),
        sa.Column("data_type", sa.String(100)),
        sa.Column("length", sa.Integer()),
        sa.Column("comment", sa.String(500)),
        sa.Column("is_nullable", sa.Boolean(), default=True),
        sa.Column("sample_data", sa.Text()),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # unstructured_file
    op.create_table(
        "unstructured_file",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("original_name", sa.String(255), nullable=False),
        sa.Column("file_type", sa.String(50)),
        sa.Column("file_size", sa.BigInteger()),
        sa.Column("storage_path", sa.String(500)),
        sa.Column("extracted_text", sa.Text()),
        sa.Column("status", sa.String(20), default="pending"),
        sa.Column("created_by", sa.Integer(), sa.ForeignKey("sys_user.id")),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # category
    op.create_table(
        "category",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("parent_id", sa.Integer(), sa.ForeignKey("category.id"), nullable=True),
        sa.Column("level", sa.Integer(), default=1),
        sa.Column("code", sa.String(50), unique=True, nullable=False),
        sa.Column("name", sa.String(100), nullable=False),
        sa.Column("description", sa.Text()),
        sa.Column("sort_order", sa.Integer(), default=0),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # data_level
    op.create_table(
        "data_level",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("code", sa.String(20), unique=True, nullable=False),
        sa.Column("name", sa.String(50), nullable=False),
        sa.Column("description", sa.Text()),
        sa.Column("color", sa.String(20), default="#999999"),
        sa.Column("control_requirements", sa.JSON()),
        sa.Column("sort_order", sa.Integer(), default=0),
    )

    # classification_template
    op.create_table(
        "classification_template",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("name", sa.String(100), nullable=False),
        sa.Column("industry_type", sa.String(50), default="insurance_property"),
        sa.Column("version", sa.String(20), default="1.0"),
        sa.Column("description", sa.Text()),
        sa.Column("is_builtin", sa.Boolean(), default=False),
        sa.Column("is_active", sa.Boolean(), default=True),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # recognition_rule
    op.create_table(
        "recognition_rule",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("template_id", sa.Integer(), sa.ForeignKey("classification_template.id"), nullable=False),
        sa.Column("category_id", sa.Integer(), sa.ForeignKey("category.id"), nullable=True),
        sa.Column("level_id", sa.Integer(), sa.ForeignKey("data_level.id"), nullable=True),
        sa.Column("rule_type", sa.String(20), nullable=False),
        sa.Column("rule_name", sa.String(100)),
        sa.Column("rule_content", sa.Text(), nullable=False),
        sa.Column("target_field", sa.String(20), default="column_name"),
        sa.Column("priority", sa.Integer(), default=100),
        sa.Column("hit_count", sa.Integer(), default=0),
        sa.Column("is_active", sa.Boolean(), default=True),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # classification_project
    op.create_table(
        "classification_project",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("name", sa.String(200), nullable=False),
        sa.Column("template_id", sa.Integer(), sa.ForeignKey("classification_template.id")),
        sa.Column("description", sa.Text()),
        sa.Column("status", sa.String(20), default="created"),
        sa.Column("target_source_ids", sa.Text()),
        sa.Column("target_database_ids", sa.Text()),
        sa.Column("target_table_ids", sa.Text()),
        sa.Column("planned_start", sa.DateTime()),
        sa.Column("planned_end", sa.DateTime()),
        sa.Column("created_by", sa.Integer(), sa.ForeignKey("sys_user.id"), nullable=False),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
        sa.Column("updated_at", sa.DateTime(), default=sa.func.now(), onupdate=sa.func.now()),
    )

    # classification_task
    op.create_table(
        "classification_task",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("project_id", sa.Integer(), sa.ForeignKey("classification_project.id"), nullable=False),
        sa.Column("name", sa.String(200)),
        sa.Column("assigner_id", sa.Integer(), sa.ForeignKey("sys_user.id")),
        sa.Column("assignee_id", sa.Integer(), sa.ForeignKey("sys_user.id")),
        sa.Column("target_type", sa.String(20), default="table"),
        sa.Column("target_ids", sa.Text()),
        sa.Column("status", sa.String(20), default="pending"),
        sa.Column("deadline", sa.DateTime()),
        sa.Column("completed_at", sa.DateTime()),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # classification_result
    op.create_table(
        "classification_result",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("project_id", sa.Integer(), sa.ForeignKey("classification_project.id"), nullable=False),
        sa.Column("column_id", sa.Integer(), sa.ForeignKey("meta_column.id"), nullable=True),
        sa.Column("file_id", sa.Integer(), sa.ForeignKey("unstructured_file.id"), nullable=True),
        sa.Column("category_id", sa.Integer(), sa.ForeignKey("category.id")),
        sa.Column("level_id", sa.Integer(), sa.ForeignKey("data_level.id")),
        sa.Column("source", sa.String(20), default="auto"),
        sa.Column("confidence", sa.Float(), default=0.0),
        sa.Column("labeler_id", sa.Integer(), sa.ForeignKey("sys_user.id")),
        sa.Column("reviewer_id", sa.Integer(), sa.ForeignKey("sys_user.id")),
        sa.Column("status", sa.String(20), default="auto"),
        sa.Column("label_time", sa.DateTime()),
        sa.Column("review_time", sa.DateTime()),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
        sa.Column("updated_at", sa.DateTime(), default=sa.func.now(), onupdate=sa.func.now()),
    )

    # classification_change
    op.create_table(
        "classification_change",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("result_id", sa.Integer(), sa.ForeignKey("classification_result.id"), nullable=False),
        sa.Column("change_type", sa.String(20), nullable=False),
        sa.Column("old_category_id", sa.Integer(), sa.ForeignKey("category.id")),
        sa.Column("new_category_id", sa.Integer(), sa.ForeignKey("category.id")),
        sa.Column("old_level_id", sa.Integer(), sa.ForeignKey("data_level.id")),
        sa.Column("new_level_id", sa.Integer(), sa.ForeignKey("data_level.id")),
        sa.Column("reason", sa.Text()),
        sa.Column("applicant_id", sa.Integer(), sa.ForeignKey("sys_user.id")),
        sa.Column("approver_id", sa.Integer(), sa.ForeignKey("sys_user.id")),
        sa.Column("approval_status", sa.String(20), default="pending"),
        sa.Column("approval_comment", sa.Text()),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )

    # sys_operation_log
    op.create_table(
        "sys_operation_log",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("user_id", sa.Integer(), sa.ForeignKey("sys_user.id"), nullable=True),
        sa.Column("username", sa.String(50)),
        sa.Column("module", sa.String(50)),
        sa.Column("action", sa.String(50)),
        sa.Column("method", sa.String(10)),
        sa.Column("path", sa.String(500)),
        sa.Column("ip", sa.String(50)),
        sa.Column("request_body", sa.Text()),
        sa.Column("response_body", sa.Text()),
        sa.Column("status_code", sa.Integer()),
        sa.Column("duration_ms", sa.Integer()),
        sa.Column("created_at", sa.DateTime(), default=sa.func.now()),
    )


def downgrade() -> None:
    tables = [
        "sys_operation_log",
        "classification_change",
        "classification_result",
        "classification_task",
        "classification_project",
        "recognition_rule",
        "classification_template",
        "data_level",
        "category",
        "unstructured_file",
        "meta_column",
        "meta_table",
        "meta_database",
        "data_source",
        "sys_user_role",
        "sys_user",
        "sys_role",
        "sys_dept",
    ]
    for t in tables:
        op.drop_table(t)
