<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;

/**
 * 数据库表与字段注释迁移
 *
 * 优化说明（2026-07-28）：
 * 1. 仅包含系统核心表注释，应用表注释由各应用 install.sql 自行负责（应用隔离原则）
 * 2. 跳过判断：若核心表已带注释（install.sql 已通过 COMMENT 内联设置），直接 return，避免全新安装场景下的冗余 ALTER
 * 3. 批量优化：
 *    - 一次 SHOW TABLES 替代 N 次 Schema::hasTable()
 *    - 一次 information_schema.COLUMNS 批量查询替代 N 次 hasColumn + SELECT COLUMN_TYPE
 *    - 同表的多个 MODIFY COLUMN 合并为单条 ALTER TABLE，将 N 次表锁降为 1 次
 */
return new class extends Migration
{
    /**
     * 系统核心表注释定义（仅系统表，应用表注释由各应用 install.sql 负责）
     */
    private array $comments = [

        // ==================== 系统核心表 ====================

        'users' => [
            'comment' => '前台用户表',
            'columns' => [
                'id' => '主键ID',
                'username' => '用户名',
                'email' => '邮箱地址',
                'phone' => '手机号码',
                'password' => '密码（bcrypt加密）',
                'nickname' => '昵称',
                'avatar' => '头像URL',
                'gender' => '性别：0-未知 1-男 2-女',
                'birthday' => '出生日期',
                'signature' => '个性签名',
                'group_id' => '用户组ID，关联user_groups表',
                'status' => '状态：0-禁用 1-启用',
                'email_verified_at' => '邮箱验证时间',
                'phone_verified_at' => '手机验证时间',
                'last_login_at' => '最后登录时间',
                'last_login_ip' => '最后登录IP地址',
                'login_count' => '累计登录次数',
                'remember_token' => '记住我Token',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'admin_users' => [
            'comment' => '后台管理员表',
            'columns' => [
                'id' => '主键ID',
                'username' => '管理员用户名',
                'password' => '密码（bcrypt加密）',
                'name' => '真实姓名',
                'email' => '邮箱地址',
                'phone' => '手机号码',
                'avatar' => '头像URL',
                'status' => '状态：0-禁用 1-启用',
                'last_login_at' => '最后登录时间',
                'last_login_ip' => '最后登录IP地址',
                'login_count' => '累计登录次数',
                'password_changed_at' => '密码最后修改时间',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'admin_roles' => [
            'comment' => '后台角色表',
            'columns' => [
                'id' => '主键ID',
                'name' => '角色名称',
                'code' => '角色编码（如super_admin）',
                'description' => '角色描述',
                'parent_id' => '父角色ID，用于树形结构',
                'sort' => '排序值，越小越靠前',
                'status' => '状态：0-禁用 1-启用',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'admin_permissions' => [
            'comment' => '后台权限表',
            'columns' => [
                'id' => '主键ID',
                'name' => '权限名称',
                'code' => '权限编码（如admin.user.store）',
                'module' => '所属模块',
                'app_id' => '所属应用ID，NULL表示系统权限',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'admin_menus' => [
            'comment' => '后台菜单表',
            'columns' => [
                'id' => '主键ID',
                'parent_id' => '父菜单ID，用于树形结构',
                'name' => '菜单名称',
                'icon' => '菜单图标CSS类名',
                'path' => '路由路径',
                'component' => '前端组件路径',
                'permission_code' => '关联权限编码',
                'type' => '类型：1-目录 2-菜单 3-按钮',
                'visible' => '是否可见：0-隐藏 1-显示',
                'sort' => '排序值，越小越靠前',
                'status' => '状态：0-禁用 1-启用',
                'terminal_type' => '终端类型',
                'app_id' => '所属应用ID，NULL表示系统菜单',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'admin_menu_terminals' => [
            'comment' => '菜单终端类型表',
            'columns' => [
                'id' => '主键ID',
                'type' => '终端类型标识',
                'name' => '终端类型名称',
                'description' => '终端类型描述',
                'sort' => '排序值',
                'status' => '状态',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'admin_user_roles' => [
            'comment' => '管理员-角色关联表',
            'columns' => [
                'id' => '主键ID',
                'user_id' => '管理员ID，关联admin_users表',
                'role_id' => '角色ID，关联admin_roles表',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'admin_role_permissions' => [
            'comment' => '角色-权限关联表',
            'columns' => [
                'id' => '主键ID',
                'role_id' => '角色ID，关联admin_roles表',
                'permission_id' => '权限ID，关联admin_permissions表',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'admin_role_menus' => [
            'comment' => '角色-菜单关联表',
            'columns' => [
                'id' => '主键ID',
                'role_id' => '角色ID，关联admin_roles表',
                'menu_id' => '菜单ID，关联admin_menus表',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'admin_operation_logs' => [
            'comment' => '操作日志表',
            'columns' => [
                'id' => '主键ID',
                'user_id' => '操作人ID，关联admin_users表',
                'module' => '操作模块',
                'action' => '操作动作',
                'method' => 'HTTP请求方法',
                'path' => '请求路径',
                'params' => '请求参数（JSON）',
                'ip' => '操作IP地址',
                'user_agent' => '浏览器User-Agent',
                'status' => '操作状态',
                'error_message' => '错误信息',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'config_groups' => [
            'comment' => '配置分组表',
            'columns' => [
                'id' => '主键ID',
                'name' => '分组名称',
                'code' => '分组编码（唯一标识）',
                'app_id' => '所属应用ID，NULL表示系统配置组',
                'sort' => '排序值，越小越靠前',
                'status' => '状态：0-禁用 1-启用',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'config_items' => [
            'comment' => '配置项表',
            'columns' => [
                'id' => '主键ID',
                'group_id' => '分组ID，关联config_groups表',
                'name' => '配置项名称',
                'code' => '配置项编码（唯一标识）',
                'value' => '配置值',
                'type' => '类型：text/switch/select/image/number/textarea/password',
                'options' => '选项列表（JSON，select类型用）',
                'tips' => '提示信息',
                'sort' => '排序值，越小越靠前',
                'status' => '状态：0-禁用 1-启用',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'attachments' => [
            'comment' => '附件表',
            'columns' => [
                'id' => '主键ID',
                'user_id' => '上传者ID',
                'name' => '原始文件名',
                'path' => '存储路径',
                'url' => '访问URL',
                'mime_type' => 'MIME类型',
                'extension' => '文件扩展名',
                'size' => '文件大小（字节）',
                'hash' => '文件哈希值（用于去重）',
                'disk' => '存储磁盘标识',
                'category' => '附件分类',
                'group_id' => '分组ID，关联attachment_groups表',
                'status' => '状态：0-禁用 1-启用',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'attachment_groups' => [
            'comment' => '附件分组表',
            'columns' => [
                'id' => '主键ID',
                'name' => '分组名称',
                'code' => '分组编码（唯一标识）',
                'description' => '分组描述',
                'sort' => '排序值，越小越靠前',
                'status' => '状态：0-禁用 1-启用',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'content_models' => [
            'comment' => '内容模型表',
            'columns' => [
                'id' => '主键ID',
                'name' => '模型名称',
                'alias' => '模型别名',
                'description' => '模型描述',
                'table_name' => '对应数据表名',
                'sort' => '排序值，越小越靠前',
                'status' => '状态：0-禁用 1-启用',
                'is_default' => '是否默认模型：0-否 1-是',
                'field_config' => '字段配置（JSON）',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'content_model_fields' => [
            'comment' => '内容模型字段表',
            'columns' => [
                'id' => '主键ID',
                'model_id' => '模型ID，关联content_models表',
                'name' => '字段名称',
                'field' => '字段标识',
                'type' => '字段类型：varchar/text/int等',
                'length' => '字段长度',
                'decimal_precision' => '小数精度',
                'default_value' => '默认值',
                'form_type' => '表单类型',
                'form_config' => '表单配置（JSON）',
                'sort' => '排序值，越小越靠前',
                'status' => '状态：0-禁用 1-启用',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'content_categories' => [
            'comment' => '内容分类表',
            'columns' => [
                'id' => '主键ID',
                'parent_id' => '父分类ID，用于树形结构',
                'model_id' => '模型ID，关联content_models表',
                'name' => '分类名称',
                'icon' => '分类图标',
                'image' => '分类图片',
                'description' => '分类描述',
                'sort' => '排序值，越小越靠前',
                'status' => '状态：0-禁用 1-启用',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'contents' => [
            'comment' => '内容表',
            'columns' => [
                'id' => '主键ID',
                'category_id' => '分类ID，关联content_categories表',
                'model_id' => '模型ID，关联content_models表',
                'title' => '内容标题',
                'content' => '内容正文',
                'summary' => '内容摘要',
                'image' => '封面图URL',
                'author' => '作者',
                'source' => '来源',
                'publish_at' => '发布时间',
                'pv' => '浏览量',
                'sort' => '排序值',
                'status' => '状态：0-草稿 1-已发布 2-已下架',
                'user_id' => '创建者ID',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'user_groups' => [
            'comment' => '前台用户组表',
            'columns' => [
                'id' => '主键ID',
                'name' => '用户组名称',
                'code' => '用户组编码（唯一标识）',
                'description' => '用户组描述',
                'icon' => '用户组图标',
                'color' => '用户组颜色标识',
                'is_default' => '是否默认组：0-否 1-是',
                'sort' => '排序值，越小越靠前',
                'status' => '状态：0-禁用 1-启用',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'user_third_party' => [
            'comment' => '第三方登录绑定表',
            'columns' => [
                'id' => '主键ID',
                'user_id' => '用户ID，关联users表',
                'platform' => '第三方平台标识（github/wechat等）',
                'open_id' => '第三方OpenID',
                'union_id' => '第三方UnionID',
                'nickname' => '第三方昵称',
                'avatar' => '第三方头像URL',
                'access_token' => '访问令牌',
                'refresh_token' => '刷新令牌',
                'expires_at' => '令牌过期时间',
                'raw_data' => '第三方返回的原始数据（JSON）',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'apps' => [
            'comment' => '应用表',
            'columns' => [
                'id' => '主键ID',
                'app_id' => '应用唯一标识',
                'name' => '应用名称',
                'description' => '应用描述',
                'version' => '当前版本号',
                'author' => '应用作者',
                'icon' => '应用图标路径',
                'path' => '应用目录相对路径',
                'status' => '状态：0-已安装 1-已启用 2-已禁用',
                'is_system' => '是否系统应用：0-否 1-是',
                'manifest' => 'manifest.json内容（JSON）',
                'install_time' => '安装时间',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'app_dependencies' => [
            'comment' => '应用依赖关系表',
            'columns' => [
                'id' => '主键ID',
                'app_id' => '应用ID',
                'depend_app_id' => '依赖的应用ID',
                'depend_version' => '依赖版本约束',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'app_operation_logs' => [
            'comment' => '应用操作日志表',
            'columns' => [
                'id' => '主键ID',
                'app_id' => '应用ID',
                'operation' => '操作类型：install/uninstall/enable/disable/upgrade',
                'version_from' => '操作前版本号',
                'version_to' => '操作后版本号',
                'operator_id' => '操作人ID，关联admin_users表',
                'result' => '操作结果：success/failed',
                'error_message' => '错误信息',
                'detail' => '操作详情（JSON）',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],

        'app_backups' => [
            'comment' => '应用备份表',
            'columns' => [
                'id' => '主键ID',
                'app_id' => '应用ID',
                'app_name' => '应用名称',
                'app_version' => '备份时应用版本',
                'backup_type' => '备份类型：full=完整备份',
                'file_path' => '备份文件路径',
                'file_size' => '备份文件大小(字节)',
                'db_tables' => '备份的数据库表列表（JSON）',
                'status' => '状态：0=失败 1=成功',
                'operator_id' => '操作人ID',
                'error_message' => '错误信息',
                'create_time' => '创建时间',
                'update_time' => '更新时间',
            ],
        ],
    ];

    public function up(): void
    {
        if (DB::getDriverName() !== 'mysql') {
            return;
        }

        // 跳过判断：install.sql 的 CREATE TABLE 已通过 COMMENT 内联设置所有注释
        // 全新安装场景下，此迁移是冗余的，直接 return 避免数百次无意义的 ALTER TABLE
        // 仅在升级场景（旧库无注释）下才执行
        if ($this->commentsAlreadyApplied()) {
            return;
        }

        // 批量优化1：一次 SHOW TABLES 获取所有存在的表，替代 N 次 Schema::hasTable()
        $existingTables = $this->getExistingTables();

        // 批量优化2：一次 information_schema.COLUMNS 查询获取所有列的元信息
        // 替代 N 次 Schema::hasColumn + N 次 SELECT COLUMN_TYPE
        $columnsMeta = $this->getColumnsMeta();

        foreach ($this->comments as $table => $config) {
            if (!isset($existingTables[$table])) {
                continue;
            }

            // 表注释：单独一条 ALTER TABLE
            $this->addTableComment($table, $config['comment']);

            // 列注释：同表的多个 MODIFY COLUMN 合并为单条 ALTER TABLE
            $this->addColumnCommentsBatch($table, $config['columns'], $columnsMeta);
        }
    }

    public function down(): void
    {
        if (DB::getDriverName() !== 'mysql') {
            return;
        }

        $existingTables = $this->getExistingTables();
        $columnsMeta = $this->getColumnsMeta();

        foreach ($this->comments as $table => $config) {
            if (!isset($existingTables[$table])) {
                continue;
            }

            $this->addTableComment($table, '');
            $this->addColumnCommentsBatch($table, $config['columns'], $columnsMeta, true);
        }
    }

    /**
     * 检查核心表注释是否已应用（全新安装场景跳过判断）
     *
     * 通过抽样检查任意一张核心表的表注释是否非空来判断：
     * - install.sql 已通过 COMMENT='...' 设置注释 → 已应用，跳过迁移
     * - 旧库无注释（升级场景）→ 未应用，执行迁移
     */
    private function commentsAlreadyApplied(): bool
    {
        // 抽样 users 表的表注释
        $row = DB::selectOne("
            SELECT TABLE_COMMENT
            FROM information_schema.TABLES
            WHERE TABLE_SCHEMA = DATABASE()
              AND TABLE_NAME = 'users'
        ");

        // TABLE_COMMENT 非空且非 'VIEW' 等特殊值，视为已应用
        return $row && !empty($row->TABLE_COMMENT);
    }

    /**
     * 一次查询获取当前库所有表（键为表名）
     * 使用 information_schema 替代 SHOW TABLES，列名固定为 TABLE_NAME 更稳健
     *
     * @return array<string,bool> 表名 => true
     */
    private function getExistingTables(): array
    {
        $rows = DB::select("
            SELECT TABLE_NAME
            FROM information_schema.TABLES
            WHERE TABLE_SCHEMA = DATABASE()
              AND TABLE_TYPE = 'BASE TABLE'
        ");
        $tables = [];
        foreach ($rows as $row) {
            $tables[$row->TABLE_NAME] = true;
        }
        return $tables;
    }

    /**
     * 批量查询所有核心表的列元信息
     * 一次 SQL 替代 N 次 Schema::hasColumn + N 次 SELECT COLUMN_TYPE
     *
     * @return array<string, array<string, \stdClass>> 结构：[table => [column => row]]
     */
    private function getColumnsMeta(): array
    {
        return $this->getColumnsMetaForTables(array_keys($this->comments));
    }

    /**
     * 查询指定表列表的列元信息
     *
     * @param array<string> $tables
     * @return array<string, array<string, \stdClass>>
     */
    private function getColumnsMetaForTables(array $tables): array
    {
        if (empty($tables)) {
            return [];
        }

        $placeholders = implode(',', array_fill(0, count($tables), '?'));
        $rows = DB::select("
            SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_KEY, EXTRA
            FROM information_schema.COLUMNS
            WHERE TABLE_SCHEMA = DATABASE()
              AND TABLE_NAME IN ({$placeholders})
        ", $tables);

        $meta = [];
        foreach ($rows as $row) {
            $meta[$row->TABLE_NAME][$row->COLUMN_NAME] = $row;
        }
        return $meta;
    }

    /**
     * 设置表注释
     */
    private function addTableComment(string $table, string $comment): void
    {
        $escaped = str_replace("'", "\\'", $comment);
        DB::statement("ALTER TABLE `{$table}` COMMENT '{$escaped}'");
    }

    /**
     * 批量为同表的多个列添加注释
     * 将 N 次 ALTER TABLE MODIFY COLUMN 合并为单条 ALTER TABLE，降低表锁次数
     *
     * @param string $table
     * @param array<string,string> $columns 列名 => 注释
     * @param array<string, array<string, \stdClass>> $columnsMeta 列元信息
     * @param bool $clearComment 是否清空注释（down 方法用）
     */
    private function addColumnCommentsBatch(string $table, array $columns, array $columnsMeta, bool $clearComment = false): void
    {
        $tableMeta = $columnsMeta[$table] ?? [];
        if (empty($tableMeta)) {
            return;
        }

        $modifyParts = [];
        foreach ($columns as $column => $comment) {
            $row = $tableMeta[$column] ?? null;
            if (!$row) {
                continue;
            }

            $part = $this->buildModifyColumnSql($column, $row, $clearComment ? '' : $comment);
            if ($part !== null) {
                $modifyParts[] = $part;
            }
        }

        if (empty($modifyParts)) {
            return;
        }

        // 合并同表的多个 MODIFY COLUMN 为单条 ALTER TABLE，一次表锁完成
        $sql = "ALTER TABLE `{$table}` " . implode(', ', $modifyParts);
        DB::statement($sql);
    }

    /**
     * 构造单个列的 MODIFY COLUMN 子句
     *
     * @param string $column
     * @param \stdClass $row information_schema.COLUMNS 查询结果
     * @param string $comment
     * @return string|null 无法构造时返回 null
     */
    private function buildModifyColumnSql(string $column, $row, string $comment): ?string
    {
        $type = strtoupper($row->COLUMN_TYPE);
        $nullable = $row->IS_NULLABLE === 'YES' ? 'NULL' : 'NOT NULL';
        $isAutoIncrement = str_contains(strtoupper($row->EXTRA), 'AUTO_INCREMENT');
        $isPrimaryKey = $row->COLUMN_KEY === 'PRI';

        $defaultPart = '';
        if (!$isAutoIncrement && !$isPrimaryKey) {
            if ($row->COLUMN_DEFAULT === null) {
                if ($row->IS_NULLABLE === 'YES') {
                    $defaultPart = 'DEFAULT NULL';
                }
            } elseif (strtoupper($row->COLUMN_DEFAULT) === 'CURRENT_TIMESTAMP') {
                $defaultPart = 'DEFAULT CURRENT_TIMESTAMP';
            } elseif (str_contains(strtoupper($row->EXTRA), 'DEFAULT_GENERATED')) {
                $defaultPart = 'DEFAULT ' . $row->COLUMN_DEFAULT;
            } else {
                $defaultPart = "DEFAULT '" . addslashes($row->COLUMN_DEFAULT) . "'";
            }
        }

        $extra = '';
        $extraUpper = strtoupper($row->EXTRA);
        if (str_contains($extraUpper, 'AUTO_INCREMENT')) {
            $extra = 'AUTO_INCREMENT';
        } elseif (str_contains($extraUpper, 'ON UPDATE CURRENT_TIMESTAMP')) {
            $extra = 'ON UPDATE CURRENT_TIMESTAMP';
        }

        $escapedComment = str_replace("'", "\\'", $comment);
        return "MODIFY COLUMN `{$column}` {$type} {$nullable} {$defaultPart} {$extra} COMMENT '{$escapedComment}'";
    }
};
