<?php
/*
 * @author: CloudZA(云之安) <2922619853@qq.com>
 * @hitokoto: 一场秋雨一场凉，秋心酌满泪为霜。
 * Copyright (c) 2022 by CloudZA, All Rights Reserved.
 */

/**
 * OnlineUpdater 类
 *
 * 用于从服务器下载更新文件和更新 SQL 数据库
 *
 * @author  [CloudZA]
 * @version 1.0
 */
class OnlineUpdater
{
    private $db;

    public function __construct ($dbHost , $dbUser , $dbPassword , $dbName)
    {
        // 连接数据库
        $this->db = new mysqli($dbHost , $dbUser , $dbPassword , $dbName);
        if ($this->db->connect_error) {
            die('连接数据库失败：' . $this->db->connect_error);
        }
    }

    public function updateFile ($fileUrl , $filePath)
    {
        // 下载更新文件
        $newFile = file_get_contents($fileUrl);
        if ($newFile === false) {
            return [
                'success' => false ,
                'error'   => '下载更新文件失败'
            ];
        }

        // 保存下载的更新文件
        file_put_contents($filePath , $newFile);

        // 查找已存在的文件
        $existingFiles = scandir(dirname($filePath));

        $zip = new ZipArchive;
        if ($zip->open($filePath) === true) {
            for ($i = 0; $i < $zip->numFiles; $i++) {
                $filename = $zip->getNameIndex($i);
                $newFiles[] = $filename;
                $zip->extractTo(dirname($filePath), $filename);
            }
            $zip->close();
        } else {
            return [
                'success' => false,
                'error'   => '解压更新文件失败'
            ];
        }

        // 删除下载的更新文件
        unlink($filePath);

        return [
            'success'   => true ,
            'new_files' => $newFiles
        ];
    }

    public function updateDatabase ($sqlFile)
    {
        // 读取 SQL 文件
        $sql = file_get_contents($sqlFile);
        if ($sql === false) {
            return [
                'success' => false ,
                'error'   => '读取 SQL 文件失败'
            ];
        }

        // 分割 SQL 语句
        $sqlQueries = explode(';' , $sql);

        $successCount = 0;
        $failCount    = 0;
        $failReasons  = [];
        // 执行 SQL 语句
        foreach ($sqlQueries as $query) {
            if (trim($query) != '') {
                $result = $this->db->query($query);
                if ($result) {
                    $successCount++;
                } else {
                    $failCount++;
                    $failReasons[] = $this->db->error;
                }
            }
        }

        return [
            'success'       => true ,
            'success_count' => $successCount ,
            'fail_count'    => $failCount ,
            'fail_reasons'  => $failReasons
        ];
    }

    public function update ($fileUrl , $filePath , $sqlFile)
    {
        $fileResult = $this->updateFile($fileUrl , $filePath);
        $dbResult   = $this->updateDatabase($sqlFile);

        $newFiles  = $fileResult[ 'new_files' ];
        $fileCount = count($newFiles);
        $files     = array_merge([$filePath] , $newFiles);

        return [
            'files'         => $files ,
            'file_count'    => $fileCount ,
            'success_count' => $dbResult[ 'success_count' ] ,
            'fail_count'    => $dbResult[ 'fail_count' ] ,
            'fail_reasons'  => $dbResult[ 'fail_reasons' ]
        ];
    }
}