<?php
/**
 * 项目系统对接插件 - 核心功能类
 * 处理与宝塔面板API的所有交互
 */

namespace plugin\shop\project_system;

class Server {
    
    // 宝塔面板配置
    private $btPanelUrl;
    private $btApiKey;
    private $config;
    
    // 数据库连接
    private $db;
    
    /**
     * 构造函数
     */
    public function __construct() {
        // 加载配置
        $this->config = $this->getConfig();
        $this->btPanelUrl = rtrim($this->config['bt_panel_url']['value'], '/');
        $this->btApiKey = $this->config['bt_api_key']['value'];
        
        // 初始化数据库连接
        global $db;
        $this->db = $db;
    }
    
    /**
     * 获取插件配置
     */
    private function getConfig() {
        $configFile = __DIR__ . '/config.php';
        if (file_exists($configFile)) {
            $config = require $configFile;
            return isset($config['config']) ? $config['config'] : [];
        }
        return [];
    }
    
    /**
     * 宝塔API请求
     * @param string $url API地址
     * @param array $data 请求数据
     * @return array
     */
    public function btApiRequest($url, $data = []) {
        if (empty($this->btPanelUrl) || empty($this->btApiKey)) {
            return ['status' => false, 'msg' => '宝塔面板配置未设置'];
        }
        
        // 生成请求时间戳
        $nowTime = time();
        
        // 生成请求token
        $token = md5($nowTime . md5($this->btApiKey));
        
        // 构造请求头
        $headers = [
            'Authorization: ' . $token,
            'Timestamp: ' . $nowTime
        ];
        
        // 发送请求
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->btPanelUrl . $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        
        $result = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($httpCode != 200 || empty($result)) {
            return ['status' => false, 'msg' => '请求失败，HTTP状态码：' . $httpCode];
        }
        
        $data = json_decode($result, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return ['status' => false, 'msg' => '返回数据解析失败'];
        }
        
        return $data;
    }
    
    /**
     * 创建网站
     * @param string $domain 域名
     * @param string $rootPath 根目录
     * @param string $phpVersion PHP版本
     * @return array
     */
    public function createWebsite($domain, $rootPath = '', $phpVersion = '') {
        // 使用默认PHP版本
        if (empty($phpVersion)) {
            $phpVersion = $this->config['default_php_version']['value'] ?? '74';
        }
        
        // 构造根目录
        if (empty($rootPath)) {
            $rootPath = '/www/wwwroot/' . $domain;
        }
        
        // 准备请求数据
        $data = [
            'domain' => $domain,
            'path' => $rootPath,
            'type' => 'PHP',
            'version' => $phpVersion,
            'port' => '80',
            'ps' => '项目系统-' . $domain,
            'ftp' => 'false',
            'sql' => 'false'
        ];
        
        // 调用宝塔API创建网站
        $result = $this->btApiRequest('/site?action=AddSite', $data);
        
        if (isset($result['siteId']) || (isset($result['status']) && $result['status'])) {
            // 记录到数据库
            $this->recordWebsite($domain, $rootPath, $phpVersion);
            
            // 如果开启自动SSL，申请证书
            if (($this->config['auto_ssl']['value'] ?? '0') == '1') {
                $this->applySSL($domain);
            }
            
            return ['status' => true, 'msg' => '网站创建成功', 'data' => $result];
        }
        
        return ['status' => false, 'msg' => $result['msg'] ?? '网站创建失败'];
    }
    
    /**
     * 删除网站
     * @param string $domain 域名
     * @param bool $deletePath 是否删除目录
     * @return array
     */
    public function deleteWebsite($domain, $deletePath = false) {
        // 获取网站ID
        $siteInfo = $this->getWebsiteInfo($domain);
        if (!$siteInfo) {
            return ['status' => false, 'msg' => '网站不存在'];
        }
        
        $data = [
            'id' => $siteInfo['id'],
            'webname' => $domain,
            'ftp' => '1',
            'database' => '1',
            'path' => $deletePath ? '1' : '0'
        ];
        
        $result = $this->btApiRequest('/site?action=DeleteSite', $data);
        
        if (isset($result['status']) && $result['status']) {
            // 删除数据库记录
            $this->deleteWebsiteRecord($domain);
            return ['status' => true, 'msg' => '网站删除成功'];
        }
        
        return ['status' => false, 'msg' => $result['msg'] ?? '网站删除失败'];
    }
    
    /**
     * 获取网站信息
     * @param string $domain 域名
     * @return array|null
     */
    public function getWebsiteInfo($domain) {
        $result = $this->btApiRequest('/data?action=getData&table=sites');
        
        if (isset($result['data']) && is_array($result['data'])) {
            foreach ($result['data'] as $site) {
                if ($site['name'] == $domain) {
                    return $site;
                }
            }
        }
        
        return null;
    }
    
    /**
     * 创建数据库
     * @param string $dbName 数据库名
     * @param string $username 用户名
     * @param string $password 密码
     * @return array
     */
    public function createDatabase($dbName, $username = '', $password = '') {
        // 添加前缀
        $prefix = $this->config['db_prefix']['value'] ?? 'project_';
        $dbName = $prefix . $dbName;
        
        // 自动生成用户名和密码
        if (empty($username)) {
            $username = $dbName;
        }
        if (empty($password)) {
            $password = $this->generateRandomPassword();
        }
        
        $data = [
            'name' => $dbName,
            'codeing' => 'utf8mb4',
            'db_user' => $username,
            'password' => $password,
            'dataAccess' => '%',
            'ps' => '项目系统自动创建'
        ];
        
        $result = $this->btApiRequest('/database?action=AddDatabase', $data);
        
        if (isset($result['status']) && $result['status']) {
            // 记录到数据库
            $this->recordDatabase($dbName, $username, $password);
            
            return [
                'status' => true, 
                'msg' => '数据库创建成功',
                'data' => [
                    'db_name' => $dbName,
                    'username' => $username,
                    'password' => $password
                ]
            ];
        }
        
        return ['status' => false, 'msg' => $result['msg'] ?? '数据库创建失败'];
    }
    
    /**
     * 删除数据库
     * @param string $dbName 数据库名
     * @return array
     */
    public function deleteDatabase($dbName) {
        $data = [
            'name' => $dbName
        ];
        
        $result = $this->btApiRequest('/database?action=DeleteDatabase', $data);
        
        if (isset($result['status']) && $result['status']) {
            $this->deleteDatabaseRecord($dbName);
            return ['status' => true, 'msg' => '数据库删除成功'];
        }
        
        return ['status' => false, 'msg' => $result['msg'] ?? '数据库删除失败'];
    }
    
    /**
     * 创建FTP账户
     * @param string $username FTP用户名
     * @param string $password 密码
     * @param string $path 根目录
     * @return array
     */
    public function createFtp($username, $password = '', $path = '') {
        // 自动生成密码
        if (empty($password)) {
            $password = $this->generateRandomPassword();
        }
        
        // 使用默认路径
        if (empty($path)) {
            $path = ($this->config['ftp_root_path']['value'] ?? '/www/wwwroot/') . $username;
        }
        
        $data = [
            'ftp_username' => $username,
            'ftp_password' => $password,
            'path' => $path,
            'ps' => '项目系统自动创建'
        ];
        
        $result = $this->btApiRequest('/ftp?action=AddUser', $data);
        
        if (isset($result['status']) && $result['status']) {
            $this->recordFtp($username, $path);
            
            return [
                'status' => true,
                'msg' => 'FTP账户创建成功',
                'data' => [
                    'username' => $username,
                    'password' => $password,
                    'path' => $path
                ]
            ];
        }
        
        return ['status' => false, 'msg' => $result['msg'] ?? 'FTP账户创建失败'];
    }
    
    /**
     * 删除FTP账户
     * @param string $username FTP用户名
     * @return array
     */
    public function deleteFtp($username) {
        $data = [
            'username' => $username,
            'delete_path' => '0'
        ];
        
        $result = $this->btApiRequest('/ftp?action=DeleteUser', $data);
        
        if (isset($result['status']) && $result['status']) {
            $this->deleteFtpRecord($username);
            return ['status' => true, 'msg' => 'FTP账户删除成功'];
        }
        
        return ['status' => false, 'msg' => $result['msg'] ?? 'FTP账户删除失败'];
    }
    
    /**
     * 申请SSL证书
     * @param string $domain 域名
     * @return array
     */
    public function applySSL($domain) {
        $data = [
            'siteName' => $domain,
            'forceHttps' => '1',
            'type' => '1' // Let's Encrypt
        ];
        
        $result = $this->btApiRequest('/site?action=CreateLet', $data);
        
        if (isset($result['status']) && $result['status']) {
            return ['status' => true, 'msg' => 'SSL证书申请成功'];
        }
        
        return ['status' => false, 'msg' => $result['msg'] ?? 'SSL证书申请失败'];
    }
    
    /**
     * 生成自动登录Token
     * @param int $userId 用户ID
     * @param string $username 用户名
     * @return string
     */
    public function generateLoginToken($userId, $username) {
        $key = $this->config['auto_login_key']['value'] ?? 'default_key';
        $timestamp = time();
        $expire = 3600; // 1小时有效期
        
        $data = [
            'user_id' => $userId,
            'username' => $username,
            'timestamp' => $timestamp,
            'expire' => $timestamp + $expire
        ];
        
        $token = base64_encode(json_encode($data)) . '.' . 
                 hash_hmac('sha256', json_encode($data), $key);
        
        return $token;
    }
    
    /**
     * 验证登录Token
     * @param string $token
     * @return array|false
     */
    public function verifyLoginToken($token) {
        $parts = explode('.', $token);
        if (count($parts) != 2) {
            return false;
        }
        
        $data = json_decode(base64_decode($parts[0]), true);
        if (!$data) {
            return false;
        }
        
        // 检查是否过期
        if ($data['expire'] < time()) {
            return false;
        }
        
        // 验证签名
        $key = $this->config['auto_login_key']['value'] ?? 'default_key';
        $expectedHash = hash_hmac('sha256', json_encode($data), $key);
        
        if (!hash_equals($expectedHash, $parts[1])) {
            return false;
        }
        
        return $data;
    }
    
    /**
     * 获取用户中心跳转URL
     * @param int $userId
     * @param string $username
     * @return string
     */
    public function getUserCenterUrl($userId, $username) {
        $baseUrl = $this->config['user_center_url']['value'] ?? '';
        if (empty($baseUrl)) {
            return '';
        }
        
        $token = $this->generateLoginToken($userId, $username);
        return $baseUrl . '?auto_login=' . urlencode($token);
    }
    
    /**
     * 记录网站信息到数据库
     */
    private function recordWebsite($domain, $path, $phpVersion) {
        $sql = "INSERT INTO lzsys_project_websites (domain, root_path, php_version, create_time) 
                VALUES (?, ?, ?, ?)";
        $this->db->query($sql, [$domain, $path, $phpVersion, time()]);
    }
    
    /**
     * 删除网站记录
     */
    private function deleteWebsiteRecord($domain) {
        $sql = "DELETE FROM lzsys_project_websites WHERE domain = ?";
        $this->db->query($sql, [$domain]);
    }
    
    /**
     * 记录数据库信息
     */
    private function recordDatabase($dbName, $username, $password) {
        $sql = "INSERT INTO lzsys_project_databases (db_name, username, password, create_time) 
                VALUES (?, ?, ?, ?)";
        $this->db->query($sql, [$dbName, $username, $password, time()]);
    }
    
    /**
     * 删除数据库记录
     */
    private function deleteDatabaseRecord($dbName) {
        $sql = "DELETE FROM lzsys_project_databases WHERE db_name = ?";
        $this->db->query($sql, [$dbName]);
    }
    
    /**
     * 记录FTP信息
     */
    private function recordFtp($username, $path) {
        $sql = "INSERT INTO lzsys_project_ftp (username, root_path, create_time) 
                VALUES (?, ?, ?)";
        $this->db->query($sql, [$username, $path, time()]);
    }
    
    /**
     * 删除FTP记录
     */
    private function deleteFtpRecord($username) {
        $sql = "DELETE FROM lzsys_project_ftp WHERE username = ?";
        $this->db->query($sql, [$username]);
    }
    
    /**
     * 生成随机密码
     */
    private function generateRandomPassword($length = 16) {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';
        $password = '';
        for ($i = 0; $i < $length; $i++) {
            $password .= $chars[random_int(0, strlen($chars) - 1)];
        }
        return $password;
    }
    
    /**
     * 获取网站列表
     */
    public function getWebsiteList($page = 1, $limit = 10) {
        $sql = "SELECT * FROM lzsys_project_websites ORDER BY create_time DESC LIMIT ?, ?";
        $offset = ($page - 1) * $limit;
        return $this->db->query($sql, [$offset, $limit])->fetchAll();
    }
    
    /**
     * 获取数据库列表
     */
    public function getDatabaseList($page = 1, $limit = 10) {
        $sql = "SELECT * FROM lzsys_project_databases ORDER BY create_time DESC LIMIT ?, ?";
        $offset = ($page - 1) * $limit;
        return $this->db->query($sql, [$offset, $limit])->fetchAll();
    }
    
    /**
     * 获取FTP列表
     */
    public function getFtpList($page = 1, $limit = 10) {
        $sql = "SELECT * FROM lzsys_project_ftp ORDER BY create_time DESC LIMIT ?, ?";
        $offset = ($page - 1) * $limit;
        return $this->db->query($sql, [$offset, $limit])->fetchAll();
    }
    
    /**
     * 测试宝塔连接
     */
    public function testConnection() {
        $result = $this->btApiRequest('/system?action=GetSystemTotal');
        
        if (isset($result['status']) && !$result['status']) {
            return ['status' => false, 'msg' => $result['msg'] ?? '连接失败'];
        }
        
        if (isset($result['systemdate'])) {
            return ['status' => true, 'msg' => '连接成功'];
        }
        
        return ['status' => false, 'msg' => '连接失败，请检查配置'];
    }
}
