<?php
/**
 * HuSNS - 一款免费开源的社交平台
 * 
 * @author  HYR
 * @QQ      281900864
 * @website https://huyourui.com
 * @license MIT
 * @声明    严禁用于违法违规用途
 */

/**
 * 数据库升级类
 * 用于从旧版本升级数据库结构
 * 注意：新版本安装已包含完整表结构，此文件主要用于兼容旧版本升级
 */
class Upgrade
{
    public static function run()
    {
        try {
            $db = Database::getInstance();
            
            if (!self::tableExists($db, 'version')) {
                self::createVersionTable($db);
            }
            
            // 确保旧版本数据库包含所有缺失的字段
            self::ensureColumns($db);
            
            $currentVersion = self::getCurrentVersion($db);
            
            $upgrades = self::getUpgrades();
            
            foreach ($upgrades as $version => $queries) {
                if (version_compare($version, $currentVersion, '>')) {
                    foreach ($queries as $query) {
                        try {
                            $db->query($query);
                        } catch (Exception $e) {
                            // 忽略已存在的错误
                        }
                    }
                    self::updateVersion($db, $version);
                }
            }
        } catch (Exception $e) {
            // 静默处理
        }
    }
    
    /**
     * 确保旧版本数据库包含新版本新增的字段
     * 此方法用于兼容旧版本升级
     */
    private static function ensureColumns($db)
    {
        // users 表新增字段
        self::addColumnIfNotExists($db, 'users', 'remember_token', "varchar(64) NOT NULL DEFAULT '' COMMENT '保持登录令牌' AFTER `bio`");
        self::addColumnIfNotExists($db, 'users', 'ban_type', "tinyint(1) NOT NULL DEFAULT 0 COMMENT '限制类型：0正常 1禁言 2封禁' AFTER `status`");
        self::addColumnIfNotExists($db, 'users', 'ban_until', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '限制到期时间，0表示永久' AFTER `ban_type`");
        self::addColumnIfNotExists($db, 'users', 'ban_reason', "varchar(255) NOT NULL DEFAULT '' COMMENT '限制原因' AFTER `ban_until`");
        self::addColumnIfNotExists($db, 'users', 'points', "int(11) NOT NULL DEFAULT 0 COMMENT '积分' AFTER `ban_reason`");
        self::addColumnIfNotExists($db, 'users', 'last_activity', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后活跃时间' AFTER `updated_at`");
        self::addColumnIfNotExists($db, 'users', 'background', "varchar(255) NOT NULL DEFAULT '' COMMENT '个人主页背景图片' AFTER `avatar`");
        
        // posts 表新增字段
        self::addColumnIfNotExists($db, 'posts', 'repost_id', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '转发的原动态ID，0为原创' AFTER `images`");
        self::addColumnIfNotExists($db, 'posts', 'repost_user_id', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '被转发动态的用户ID' AFTER `repost_id`");
        self::addColumnIfNotExists($db, 'posts', 'attachments', "text COMMENT '附件JSON' AFTER `images`");
        self::addColumnIfNotExists($db, 'posts', 'videos', "text COMMENT '视频JSON' AFTER `attachments`");
        self::addColumnIfNotExists($db, 'posts', 'is_anonymous', "tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否匿名发布：0否 1是' AFTER `user_id`");
        self::addColumnIfNotExists($db, 'posts', 'is_pinned', "tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否置顶：0否 1是' AFTER `status`");
        self::addColumnIfNotExists($db, 'posts', 'is_featured', "tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否精华：0否 1是' AFTER `is_pinned`");
        self::addColumnIfNotExists($db, 'posts', 'ip', "varchar(50) NOT NULL DEFAULT '' COMMENT '发布IP' AFTER `status`");
        self::addColumnIfNotExists($db, 'posts', 'location_name', "varchar(255) NOT NULL DEFAULT '' COMMENT '位置名称' AFTER `status`");
        self::addColumnIfNotExists($db, 'posts', 'location_lat', "decimal(10,7) DEFAULT NULL COMMENT '纬度' AFTER `location_name`");
        self::addColumnIfNotExists($db, 'posts', 'location_lng', "decimal(10,7) DEFAULT NULL COMMENT '经度' AFTER `location_lat`");
        self::addColumnIfNotExists($db, 'posts', 'views', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '阅读量' AFTER `reposts`");
        self::addColumnIfNotExists($db, 'posts', 'circle_id', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '圈子ID' AFTER `location_lng`");
        self::addColumnIfNotExists($db, 'posts', 'circle_name', "varchar(100) NOT NULL DEFAULT '' COMMENT '圈子名称' AFTER `circle_id`");
        self::addColumnIfNotExists($db, 'posts', 'edit_count', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '编辑次数' AFTER `is_featured`");
        self::addColumnIfNotExists($db, 'posts', 'edited_at', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后编辑时间' AFTER `edit_count`");
        
        // posts 表新增索引
        self::addIndexIfNotExists($db, 'posts', 'is_pinned', '`is_pinned`');
        self::addIndexIfNotExists($db, 'posts', 'is_featured', '`is_featured`');
        self::addIndexIfNotExists($db, 'posts', 'repost_id', '`repost_id`');
        
        // comments 表新增字段
        self::addColumnIfNotExists($db, 'comments', 'parent_id', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '父评论ID，0为一级评论' AFTER `content`");
        self::addColumnIfNotExists($db, 'comments', 'reply_to_user_id', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '回复的用户ID' AFTER `parent_id`");
        self::addColumnIfNotExists($db, 'comments', 'likes', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '点赞数' AFTER `status`");
        self::addColumnIfNotExists($db, 'comments', 'ip', "varchar(50) NOT NULL DEFAULT '' COMMENT '评论IP' AFTER `status`");
        self::addIndexIfNotExists($db, 'comments', 'parent_id', '`parent_id`');
        
        // reports 表新增字段
        self::addColumnIfNotExists($db, 'reports', 'handle_result', "varchar(255) NOT NULL DEFAULT '' COMMENT '处理结果说明' AFTER `handled_by`");
        
        // circles 表新增字段（注意：数据库表使用 is_private，不是 is_public）
        self::addColumnIfNotExists($db, 'circles', 'is_verified', "tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否认证' AFTER `description`");
        self::addColumnIfNotExists($db, 'circles', 'verify_type', "tinyint(1) NOT NULL DEFAULT 0 COMMENT '认证类型 0-无 1-官方认证 2-企业认证 3-个人认证' AFTER `is_verified`");
        self::addColumnIfNotExists($db, 'circles', 'verify_info', "varchar(200) NOT NULL DEFAULT '' COMMENT '认证信息/说明' AFTER `verify_type`");
        self::addColumnIfNotExists($db, 'circles', 'verify_time', "int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '认证时间' AFTER `verify_info`");
        self::addColumnIfNotExists($db, 'circles', 'verify_admin', "int(11) NOT NULL DEFAULT 0 COMMENT '认证管理员ID' AFTER `verify_time`");
    }
    
    private static function tableExists($db, $table)
    {
        $prefix = $db->getPrefix();
        $sql = "SHOW TABLES LIKE '{$prefix}{$table}'";
        $result = $db->fetch($sql);
        return $result !== false;
    }
    
    private static function columnExists($db, $table, $column)
    {
        $prefix = $db->getPrefix();
        $sql = "SHOW COLUMNS FROM `{$prefix}{$table}` LIKE '{$column}'";
        $result = $db->fetch($sql);
        return $result !== false;
    }
    
    private static function addColumnIfNotExists($db, $table, $column, $definition)
    {
        if (!self::columnExists($db, $table, $column)) {
            $prefix = $db->getPrefix();
            $sql = "ALTER TABLE `{$prefix}{$table}` ADD COLUMN `{$column}` {$definition}";
            try {
                $db->query($sql);
            } catch (Exception $e) {
                // 忽略已存在的错误
            }
        }
    }
    
    private static function addIndexIfNotExists($db, $table, $indexName, $columns)
    {
        $prefix = $db->getPrefix();
        $sql = "SHOW INDEX FROM `{$prefix}{$table}` WHERE Key_name = '{$indexName}'";
        $result = $db->fetch($sql);
        if (!$result) {
            $sql = "ALTER TABLE `{$prefix}{$table}` ADD INDEX `{$indexName}` ({$columns})";
            try {
                $db->query($sql);
            } catch (Exception $e) {
                // 忽略已存在的错误
            }
        }
    }
    
    private static function createVersionTable($db)
    {
        $prefix = $db->getPrefix();
        $sql = "CREATE TABLE IF NOT EXISTS `{$prefix}version` (
            `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
            `version` varchar(20) NOT NULL DEFAULT '' COMMENT '版本号',
            `created_at` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
            PRIMARY KEY (`id`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='版本表'";
        
        $db->query($sql);
        
        $db->insert('version', [
            'version' => '0.0.0',
            'created_at' => time()
        ]);
    }
    
    private static function getCurrentVersion($db)
    {
        $prefix = $db->getPrefix();
        $sql = "SELECT version FROM `{$prefix}version` ORDER BY id DESC LIMIT 1";
        $result = $db->fetch($sql);
        return $result ? $result['version'] : '0.0.0';
    }
    
    private static function updateVersion($db, $version)
    {
        $db->insert('version', [
            'version' => $version,
            'created_at' => time()
        ]);
    }
    
    /**
     * 获取升级脚本
     * 注意：新版本(3.9.2+)安装已包含完整表结构
     * 此方法主要用于旧版本(0.0.0 - 3.9.1)的升级兼容
     */
    private static function getUpgrades()
    {
        $prefix = Database::getInstance()->getPrefix();
        
        return [
            /**
             * 版本 3.9.2 - 当前最新版本
             * 新安装已包含完整表结构，无需额外操作
             */
            '3.9.2' => [],
            
            /**
             * 版本 3.9.3 - 新增隐私功能相关表
             */
            '3.9.3' => [
                // 用户黑名单表
                "CREATE TABLE IF NOT EXISTS `{$prefix}user_blacklist` (
                  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
                  `user_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户ID',
                  `blacklist_user_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '被拉黑用户ID',
                  `created_at` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
                  PRIMARY KEY (`id`),
                  UNIQUE KEY `user_blacklist` (`user_id`, `blacklist_user_id`),
                  KEY `user_id` (`user_id`),
                  KEY `blacklist_user_id` (`blacklist_user_id`)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户黑名单表'",
                
                // 用户会话表
                "CREATE TABLE IF NOT EXISTS `{$prefix}user_sessions` (
                  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
                  `user_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户ID',
                  `session_token` varchar(64) NOT NULL DEFAULT '' COMMENT '会话令牌',
                  `device_name` varchar(100) NOT NULL DEFAULT '' COMMENT '设备名称',
                  `device_type` varchar(50) NOT NULL DEFAULT '' COMMENT '设备类型：pc/mobile/tablet',
                  `ip_address` varchar(50) NOT NULL DEFAULT '' COMMENT 'IP地址',
                  `user_agent` varchar(500) NOT NULL DEFAULT '' COMMENT '用户代理',
                  `login_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '登录时间',
                  `last_active` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后活跃时间',
                  `expire_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '过期时间',
                  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态：0失效 1有效',
                  PRIMARY KEY (`id`),
                  UNIQUE KEY `session_token` (`session_token`),
                  KEY `user_id` (`user_id`),
                  KEY `status` (`status`),
                  KEY `expire_time` (`expire_time`)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户会话表'",
            ],
            
            /**
             * 版本 3.9.4 - 新增通话功能相关表
             */
            '3.9.4' => [
                // 通话请求表
                "CREATE TABLE IF NOT EXISTS `{$prefix}call_requests` (
                  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
                  `call_id` varchar(64) NOT NULL DEFAULT '' COMMENT '通话ID',
                  `caller_id` int(11) NOT NULL DEFAULT 0 COMMENT '呼叫者ID',
                  `caller_name` varchar(100) NOT NULL DEFAULT '' COMMENT '呼叫者名称',
                  `caller_avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '呼叫者头像',
                  `callee_id` int(11) NOT NULL DEFAULT 0 COMMENT '被叫者ID',
                  `type` varchar(10) NOT NULL DEFAULT 'voice' COMMENT '通话类型：voice/video',
                  `status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '状态：pending/incoming/connected/ended/rejected',
                  `created_at` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
                  `updated_at` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
                  PRIMARY KEY (`id`),
                  UNIQUE KEY `call_id` (`call_id`),
                  KEY `caller_id` (`caller_id`),
                  KEY `callee_id` (`callee_id`),
                  KEY `status` (`status`)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='通话请求表'",
            ],
        ];
    }
}
