"""role system — 统一入口角色系统迁移

新增 roles 表（角色定义）。
新增 user_roles 表（用户角色关联）。
新增 role_mapping_rules 表（角色映射规则）。
预置三个基础角色：user、agent、admin。

Revision ID: 007_role_system
Revises: 006_admin_ext
Create Date: 2026-06-12 23:00:00.000000
"""

from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '007_role_system'
down_revision = '006_admin_ext'
branch_labels = None
depends_on = None


def upgrade() -> None:
    """执行角色系统迁移。"""

    # 1. 创建 roles 表
    op.create_table(
        'roles',
        sa.Column('id', sa.String(36), primary_key=True),
        sa.Column('name', sa.String(50), unique=True, nullable=False, comment='角色标识：user/agent/admin'),
        sa.Column('display_name', sa.String(100), nullable=False, comment='显示名称：用户/坐席/管理员'),
        sa.Column('description', sa.Text, nullable=True, comment='角色描述'),
        sa.Column('permissions', sa.JSON, nullable=False, server_default='[]', comment='权限列表'),
        sa.Column('is_default', sa.Boolean, nullable=False, server_default='0', comment='是否默认角色'),
        sa.Column('created_at', sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now(), comment='创建时间'),
        sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now(), comment='更新时间'),
    )

    # 2. 创建 user_roles 表
    op.create_table(
        'user_roles',
        sa.Column('id', sa.String(36), primary_key=True),
        sa.Column('employee_id', sa.String(100), nullable=False, comment='企微 UserID'),
        sa.Column('role_id', sa.String(36), sa.ForeignKey('roles.id', ondelete='CASCADE'), nullable=False, comment='角色 ID'),
        sa.Column('source', sa.String(50), nullable=False, comment='角色来源：auto/tag/ehr/manual'),
        sa.Column('assigned_by', sa.String(100), nullable=True, comment='分配者'),
        sa.Column('assigned_at', sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now(), comment='分配时间'),
        sa.Column('expires_at', sa.DateTime(timezone=True), nullable=True, comment='过期时间'),
        sa.UniqueConstraint('employee_id', 'role_id', name='uq_user_role'),
    )
    # 创建索引
    op.create_index('idx_user_roles_employee_id', 'user_roles', ['employee_id'])
    op.create_index('idx_user_roles_role_id', 'user_roles', ['role_id'])

    # 3. 创建 role_mapping_rules 表
    op.create_table(
        'role_mapping_rules',
        sa.Column('id', sa.String(36), primary_key=True),
        sa.Column('role_id', sa.String(36), sa.ForeignKey('roles.id', ondelete='CASCADE'), nullable=False, comment='目标角色 ID'),
        sa.Column('source_type', sa.String(50), nullable=False, comment='来源类型：wecom_tag/ehr_position'),
        sa.Column('source_value', sa.String(200), nullable=False, comment='来源值：标签名/岗位关键词'),
        sa.Column('priority', sa.Integer(), nullable=False, server_default='0', comment='优先级'),
        sa.Column('is_active', sa.Boolean(), nullable=False, server_default='1', comment='是否启用'),
        sa.Column('created_at', sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now(), comment='创建时间'),
    )
    # 创建索引
    op.create_index('idx_role_mapping_rules_role_id', 'role_mapping_rules', ['role_id'])
    op.create_index('idx_role_mapping_rules_source_type', 'role_mapping_rules', ['source_type'])

    # 4. 预置三个基础角色
    # 注意：使用 op.execute 直接插入数据，因为 server_default 不适用于 Python 端生成的 UUID
    # PostgreSQL 使用 NOW() 替代 SQLite 的 datetime('now')
    op.execute("""
        INSERT INTO roles (id, name, display_name, description, permissions, is_default, created_at, updated_at) VALUES
        ('role_user_001', 'user', '用户', '所有在职员工默认角色，可提交工单、查看进度、浏览知识库', '["ticket.create", "ticket.view", "knowledge.view"]', TRUE, NOW(), NOW()),
        ('role_agent_001', 'agent', '坐席', 'IT支持人员，可处理会话、使用AI辅助、管理工单', '["conversation.manage", "ticket.assign", "knowledge.edit", "ai.wingman"]', FALSE, NOW(), NOW()),
        ('role_admin_001', 'admin', '管理员', '系统管理员，可配置系统、管理权限、查看数据分析', '["system.config", "user.manage", "role.manage", "analytics.view"]', FALSE, NOW(), NOW())
    """)

    # 5. 预置默认映射规则（企微标签 → agent 角色）
    op.execute("""
        INSERT INTO role_mapping_rules (id, role_id, source_type, source_value, priority, is_active, created_at) VALUES
        ('rule_agent_tag_001', 'role_agent_001', 'wecom_tag', 'IT坐席', 10, TRUE, NOW()),
        ('rule_agent_ehr_001', 'role_agent_001', 'ehr_position', 'IT支持', 10, TRUE, NOW()),
        ('rule_agent_ehr_002', 'role_agent_001', 'ehr_position', 'IT运维', 10, TRUE, NOW()),
        ('rule_agent_ehr_003', 'role_agent_001', 'ehr_position', '技术支持', 10, TRUE, NOW())
    """)


def downgrade() -> None:
    """回滚角色系统迁移。"""

    # 删除 role_mapping_rules 表索引和表
    op.drop_index('idx_role_mapping_rules_source_type', table_name='role_mapping_rules')
    op.drop_index('idx_role_mapping_rules_role_id', table_name='role_mapping_rules')
    op.drop_table('role_mapping_rules')

    # 删除 user_roles 表索引和表
    op.drop_index('idx_user_roles_role_id', table_name='user_roles')
    op.drop_index('idx_user_roles_employee_id', table_name='user_roles')
    op.drop_table('user_roles')

    # 删除 roles 表
    op.drop_table('roles')
