<?php
declare (strict_types = 1);

namespace app\admin\model;

use think\admin\Model;

class Version extends Model
{
    protected $name = 'version';
    
    // 自动写入时间戳
    protected $autoWriteTimestamp = true;
    
    // 版本状态
    const STATUS_DISABLED = 0;
    const STATUS_ENABLED = 1;
    
    /**
     * 获取下一个版本号
     * @param string $currentVersion 当前版本号
     * @return string
     */
    public static function getNextVersion($currentVersion = '')
    {
        if (empty($currentVersion)) {
            // 获取最新版本号
            $latest = self::order('version_no DESC')->value('version_no');
            $currentVersion = $latest ?: '1.0.0';
        }
        
        // 拆分版本号
        $parts = explode('.', $currentVersion);
        $major = intval($parts[0] ?? 1);
        $minor = intval($parts[1] ?? 0);
        $patch = intval($parts[2] ?? 0);
        
        // 增加修订号
        $patch++;
        // 如果修订号超过99,增加次版本号
        if ($patch > 99) {
            $minor++;
            $patch = 0;
        }
        // 如果次版本号超过99,增加主版本号
        if ($minor > 99) {
            $major++;
            $minor = 0;
        }
        
        return sprintf('%d.%d.%d', $major, $minor, $patch);
    }
    
    /**
     * 生成版本名称
     * @param string $version_no 版本号
     * @param string $filename 文件名
     * @return string
     */
    public static function generateVersionName($version_no, $filename = '')
    {
        // 如果有文件名,尝试从文件名中提取有意义的部分
        if ($filename) {
            // 移除扩展名
            $name = pathinfo($filename, PATHINFO_FILENAME);
            // 移除版本号部分 (匹配v后面的所有数字和点)
            $name = preg_replace('/v\d+[\d\.]+/', '', $name);
            $name = trim($name);
            if (!empty($name)) {
                return $name;
            }
        }
        
        // 默认使用版本号作为名称
        return sprintf('版本 %s', $version_no);
    }
    
    /**
     * 从文件名解析版本号
     * @param string $filename
     * @return string
     */
    public static function parseVersionFromFilename($filename)
    {
        // 移除扩展名
        $name = pathinfo($filename, PATHINFO_FILENAME);
        
        // 匹配版本号 (匹配v后面的所有数字和点)
        if (preg_match('/v(\d+[\d\.]+)/', $name, $matches)) {
            return $matches[1];
        }
        
        // 如果没有找到版本号,使用当前最新版本号加1
        return self::getNextVersion();
    }
    
    /**
     * 获取最新版本信息
     * @param string $platform 平台
     * @return array|null
     */
    public function getLatestVersion($platform = 'all')
    {
        return $this->where([
            ['status', '=', self::STATUS_ENABLED],
            ['platform', 'in', [$platform, 'all']]
        ])->order('version_no DESC')->find();
    }
    
    /**
     * 检查版本更新
     * @param string $currentVersion 当前版本
     * @param string $platform 平台
     * @return array
     */
    public function checkUpdate($currentVersion, $platform = 'all')
    {
        $latest = $this->getLatestVersion($platform);
        if (!$latest) {
            return ['has_update' => false];
        }
        
        // 版本号比较
        if (version_compare($latest['version_no'], $currentVersion) > 0) {
            // 检查是否满足最低版本要求
            if ($latest['min_version'] && version_compare($currentVersion, $latest['min_version']) < 0) {
                return [
                    'has_update' => false,
                    'error' => '当前版本过低,请先更新到' . $latest['min_version'] . '版本'
                ];
            }
            
            return [
                'has_update' => true,
                'is_force' => $latest['is_force'],
                'version_info' => $latest
            ];
        }
        
        return ['has_update' => false];
    }
    
    /**
     * 检查版本权限
     * @param int $versionId 版本ID
     * @param int $targetId 目标ID
     * @param string $targetType 目标类型
     * @return bool
     */
    public function checkVersionPermission($versionId, $targetId, $targetType)
    {
        $control = \think\facade\Db::name('version_control')
            ->where([
                ['version_id', '=', $versionId],
                ['target_id', '=', $targetId],
                ['target_type', '=', $targetType],
                ['expire_time', '>', date('Y-m-d H:i:s')]
            ])
            ->find();
            
        if (!$control) {
            return true;
        }
        
        return $control['control_type'] === 'white_list';
    }
} 