<?php

declare(strict_types=1);

$nosession = true;
$nosecu = true;
include("./includes/common.php");

session_start();

function api_result(array $arr): never
{
    header('Content-Type: application/json; charset=UTF-8');
    exit(json_encode($arr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
}

function api_auth_user(): array
{
    global $DB, $islogin2, $uid, $userrow;

    $token = isset($_SERVER['HTTP_AUTHORIZATION']) ? trim(str_replace('Bearer ', '', $_SERVER['HTTP_AUTHORIZATION'])) : '';
    if (empty($token)) {
        $token = $_POST['user_token'] ?? $_GET['user_token'] ?? '';
    }

    if (!empty($token)) {
        $decoded = authcode($token, 'DECODE', SYS_KEY);
        if ($decoded) {
            $parts = explode("\t", $decoded);
            if (count($parts) >= 2) {
                $tokenUid = intval($parts[0]);
                $userrow = $DB->getRow("SELECT * FROM pre_user WHERE uid=:uid LIMIT 1", [':uid' => $tokenUid]);
                if ($userrow) {
                    $session = md5($userrow['username'] . $userrow['password'] . $GLOBALS['password_hash']);
                    if (isset($parts[1]) && $session === $parts[1] && intval($parts[2]) > time()) {
                        if ($userrow['enable'] == 1) {
                            $islogin2 = 1;
                            $uid = intval($userrow['uid']);
                            return ['code' => 0, 'uid' => $uid, 'userrow' => $userrow];
                        }
                        return ['code' => -5, 'msg' => '账号已被禁用'];
                    }
                }
            }
        }
        return ['code' => -6, 'msg' => 'Token无效或已过期'];
    }

    $api_key = $_POST['api_key'] ?? $_GET['api_key'] ?? '';
    if (!empty($api_key)) {
        $userrow = $DB->getRow("SELECT * FROM pre_user WHERE api_key=:api_key AND enable=1 LIMIT 1", [':api_key' => $api_key]);
        if ($userrow) {
            $islogin2 = true;
            $uid = intval($userrow['uid']);
            return ['code' => 0, 'uid' => $uid, 'userrow' => $userrow];
        }
        return ['code' => -6, 'msg' => 'API密钥无效'];
    }

    if ($islogin2 && $uid > 0) {
        return ['code' => 0, 'uid' => $uid, 'userrow' => $userrow];
    }

    return ['code' => -1, 'msg' => '请提供有效的用户Token或API密钥'];
}

function get_user_token(int $uid, string $username, string $password): string
{
    global $password_hash;
    $sid = md5($username . $password . $password_hash);
    $expiretime = time() + 86400 * 30;
    return authcode("{$uid}\t{$sid}\t{$expiretime}", 'ENCODE', SYS_KEY);
}

$action = $_POST['action'] ?? $_GET['action'] ?? '';

switch ($action) {

    case 'login':
        if (!isset($conf['userlogin']) || !$conf['userlogin']) {
            api_result(['code' => -1, 'msg' => '未开启用户系统']);
        }
        $username = trim($_POST['username'] ?? '');
        $password = $_POST['password'] ?? '';
        if (empty($username) || empty($password)) {
            api_result(['code' => -1, 'msg' => '用户名和密码不能为空']);
        }
        if (!preg_match('/^[a-zA-Z0-9_]{4,20}$/', $username)) {
            api_result(['code' => -1, 'msg' => '用户名格式不正确']);
        }
        $userrow = $DB->getRow("SELECT * FROM pre_user WHERE username=:username LIMIT 1", [':username' => $username]);
        if (!$userrow) {
            api_result(['code' => -1, 'msg' => '用户名或密码错误']);
        }
        if ($userrow['enable'] != 1) {
            api_result(['code' => -5, 'msg' => '账号已被禁用']);
        }
        if (!password_verify($password, $userrow['password'])) {
            api_result(['code' => -1, 'msg' => '用户名或密码错误']);
        }
        $token = get_user_token(intval($userrow['uid']), $userrow['username'], $userrow['password']);
        $storage_used_mb = round(intval($userrow['storage_used'] ?? 0) / 1048576, 2);
        $traffic_quota_info = get_traffic_quota(intval($userrow['uid']));
        api_result([
            'code' => 0,
            'msg' => '登录成功',
            'data' => [
                'uid' => intval($userrow['uid']),
                'username' => $userrow['username'],
                'nickname' => $userrow['nickname'] ?? '',
                'email' => $userrow['email'] ?? '',
                'level' => intval($userrow['level'] ?? 0),
                'storage_used_mb' => $storage_used_mb,
                'storage_limit_mb' => intval($userrow['storage_limit'] ?? 0),
                'traffic_used_mb' => round(intval($traffic_quota_info['quota_used'] ?? 0) / 1048576, 2),
                'traffic_limit_mb' => intval($traffic_quota_info['quota_limit'] ?? 0) > 0 ? round(intval($traffic_quota_info['quota_limit']) / 1048576, 2) : 0,
                'api_key' => $userrow['api_key'] ?? '',
                'user_token' => $token,
                'token_expire' => time() + 86400 * 30,
                'register_time' => $userrow['regtime'] ?? '',
            ]
        ]);
        break;

    case 'register':
        if (!isset($conf['userlogin']) || !$conf['userlogin']) {
            api_result(['code' => -1, 'msg' => '未开启用户系统']);
        }
        $username = trim($_POST['username'] ?? '');
        $password = $_POST['password'] ?? '';
        $nickname = trim($_POST['nickname'] ?? '');
        $email = trim($_POST['email'] ?? '');
        if (empty($username) || empty($password)) {
            api_result(['code' => -1, 'msg' => '用户名和密码不能为空']);
        }
        if (!preg_match('/^[a-zA-Z0-9_]{4,20}$/', $username)) {
            api_result(['code' => -1, 'msg' => '用户名格式不正确，仅支持4-20位字母、数字和下划线']);
        }
        if (strlen($password) < 6) {
            api_result(['code' => -1, 'msg' => '密码长度不能少于6位']);
        }
        if (strlen($password) > 32) {
            api_result(['code' => -1, 'msg' => '密码长度不能超过32位']);
        }
        if (!empty($email) && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
            api_result(['code' => -1, 'msg' => '邮箱格式不正确']);
        }
        if (!empty($nickname) && mb_strlen($nickname, 'UTF-8') > 20) {
            api_result(['code' => -1, 'msg' => '昵称不能超过20个字符']);
        }
        if (empty($nickname)) {
            $nickname = $username;
        }
        $exists = $DB->getColumn("SELECT COUNT(*) FROM pre_user WHERE username=:username", [':username' => $username]);
        if ($exists > 0) {
            api_result(['code' => -1, 'msg' => '用户名已被注册']);
        }
        if (!empty($email)) {
            $emailExists = $DB->getColumn("SELECT COUNT(*) FROM pre_user WHERE email=:email", [':email' => $email]);
            if ($emailExists > 0) {
                api_result(['code' => -1, 'msg' => '邮箱已被其他用户使用']);
            }
        }
        $regip = $clientip;
        $passwordHash = password_hash($password, PASSWORD_DEFAULT);
        $apiKey = substr(md5(uniqid($username, true) . mt_rand()), 0, 32);
        $storageQuota = isset($conf['user_storage_quota']) ? intval($conf['user_storage_quota']) : 0;
        $trafficQuotaDefault = isset($conf['user_traffic_quota']) ? intval($conf['user_traffic_quota']) : 0;
        $resetInterval = isset($conf['traffic_quota_reset_interval']) ? intval($conf['traffic_quota_reset_interval']) : 30;
        $now = date('Y-m-d H:i:s');

        $sql = "INSERT INTO pre_user (username, password, nickname, email, api_key, regtime, regip, enable, level, storage_limit, traffic_limit, storage_used, traffic_used, last_traffic_reset_time, traffic_quota_reset_interval) 
                VALUES (:username, :password, :nickname, :email, :api_key, :regtime, :regip, 1, 0, :storage_limit, :traffic_limit, 0, 0, :reset_time, :reset_interval)";
        $params = [
            ':username' => $username,
            ':password' => $passwordHash,
            ':nickname' => $nickname,
            ':email' => $email !== '' ? $email : null,
            ':api_key' => $apiKey,
            ':regtime' => $now,
            ':regip' => $regip,
            ':storage_limit' => $storageQuota,
            ':traffic_limit' => $trafficQuotaDefault,
            ':reset_time' => $resetInterval > 0 ? $now : null,
            ':reset_interval' => $resetInterval,
        ];
        $result = $DB->exec($sql, $params);
        if (!$result) {
            api_result(['code' => -1, 'msg' => '注册失败，请稍后重试']);
        }
        $newUid = intval($DB->lastInsertId());
        $newUserrow = $DB->getRow("SELECT * FROM pre_user WHERE uid=:uid LIMIT 1", [':uid' => $newUid]);
        $token = get_user_token($newUid, $username, $newUserrow['password']);
        api_result([
            'code' => 0,
            'msg' => '注册成功',
            'data' => [
                'uid' => $newUid,
                'username' => $username,
                'nickname' => $nickname,
                'api_key' => $apiKey,
                'user_token' => $token,
                'token_expire' => time() + 86400 * 30,
                'storage_limit_mb' => $storageQuota,
                'traffic_limit_mb' => $trafficQuotaDefault,
            ]
        ]);
        break;

    case 'profile':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $u = $auth['userrow'];
        $traffic_quota_info = get_traffic_quota($auth['uid']);
        api_result([
            'code' => 0,
            'data' => [
                'uid' => intval($u['uid']),
                'username' => $u['username'],
                'nickname' => $u['nickname'] ?? '',
                'email' => $u['email'] ?? '',
                'level' => intval($u['level'] ?? 0),
                'enable' => intval($u['enable'] ?? 1),
                'api_key' => $u['api_key'] ?? '',
                'storage_used_mb' => round(intval($u['storage_used'] ?? 0) / 1048576, 2),
                'storage_limit_mb' => intval($u['storage_limit'] ?? 0),
                'traffic_used_mb' => round(intval($traffic_quota_info['quota_used'] ?? 0) / 1048576, 2),
                'traffic_limit_mb' => intval($traffic_quota_info['quota_limit'] ?? 0) > 0 ? round(intval($traffic_quota_info['quota_limit']) / 1048576, 2) : 0,
                'register_time' => $u['regtime'] ?? '',
                'last_login_time' => $u['lasttime'] ?? '',
            ]
        ]);
        break;

    case 'update_profile':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $nickname = trim($_POST['nickname'] ?? '');
        $email = trim($_POST['email'] ?? '');
        if (empty($nickname)) {
            api_result(['code' => -1, 'msg' => '昵称不能为空']);
        }
        if (mb_strlen($nickname, 'UTF-8') > 20) {
            api_result(['code' => -1, 'msg' => '昵称不能超过20个字符']);
        }
        if (!empty($email) && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
            api_result(['code' => -1, 'msg' => '邮箱格式不正确']);
        }
        if (!empty($email) && $email !== ($auth['userrow']['email'] ?? '')) {
            $emailExists = $DB->getColumn("SELECT COUNT(*) FROM pre_user WHERE email=:email AND uid!=:uid", [':email' => $email, ':uid' => $auth['uid']]);
            if ($emailExists > 0) {
                api_result(['code' => -1, 'msg' => '邮箱已被其他用户使用']);
            }
        }
        $result = $DB->exec("UPDATE pre_user SET nickname=:nickname, email=:email WHERE uid=:uid", [
            ':nickname' => $nickname,
            ':email' => $email !== '' ? $email : null,
            ':uid' => $auth['uid']
        ]);
        if ($result !== false) {
            api_result(['code' => 0, 'msg' => '资料更新成功']);
        } else {
            api_result(['code' => -1, 'msg' => '更新失败']);
        }
        break;

    case 'change_password':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $oldPassword = $_POST['old_password'] ?? '';
        $newPassword = $_POST['new_password'] ?? '';
        if (empty($oldPassword) || empty($newPassword)) {
            api_result(['code' => -1, 'msg' => '请提供旧密码和新密码']);
        }
        if (!password_verify($oldPassword, $auth['userrow']['password'])) {
            api_result(['code' => -1, 'msg' => '原密码错误']);
        }
        if (strlen($newPassword) < 6) {
            api_result(['code' => -1, 'msg' => '新密码长度不能少于6位']);
        }
        if (strlen($newPassword) > 32) {
            api_result(['code' => -1, 'msg' => '新密码长度不能超过32位']);
        }
        $newHash = password_hash($newPassword, PASSWORD_DEFAULT);
        $result = $DB->exec("UPDATE pre_user SET password=:password WHERE uid=:uid", [
            ':password' => $newHash,
            ':uid' => $auth['uid']
        ]);
        if ($result !== false) {
            api_result(['code' => 0, 'msg' => '密码修改成功，请重新登录']);
        } else {
            api_result(['code' => -1, 'msg' => '密码修改失败']);
        }
        break;

    case 'file_list':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $page = max(1, intval($_GET['page'] ?? 1));
        $limit = min(100, max(1, intval($_GET['limit'] ?? 20)));
        $offset = ($page - 1) * $limit;
        $folderId = intval($_GET['folder_id'] ?? 0);
        $sortField = in_array($_GET['sort'] ?? 'id', ['id', 'name', 'size', 'addtime', 'count']) ? ($_GET['sort'] ?? 'id') : 'id';
        $sortOrder = in_array(strtoupper($_GET['order'] ?? 'DESC'), ['ASC', 'DESC']) ? strtoupper($_GET['order'] ?? 'DESC') : 'DESC';
        $where = "uid=:uid";
        $params = [':uid' => $auth['uid']];
        if ($folderId >= 0) {
            $where .= " AND folder_id=:folder_id";
            $params[':folder_id'] = $folderId;
        }
        $total = intval($DB->getColumn("SELECT COUNT(*) FROM pre_file WHERE {$where}", $params));
        $totalPage = ceil($total / $limit);
        $files = $DB->getAll("SELECT id, name, type, size, hash, addtime, hide, folder_id, count FROM pre_file WHERE {$where} ORDER BY {$sortField} {$sortOrder} LIMIT {$offset},{$limit}", $params);
        $list = [];
        foreach ((array)$files as $f) {
            $list[] = [
                'id' => intval($f['id']),
                'name' => $f['name'],
                'type' => $f['type'],
                'size' => intval($f['size']),
                'size_formatted' => size_format(intval($f['size'])),
                'hash' => $f['hash'],
                'addtime' => $f['addtime'],
                'hide' => intval($f['hide'] ?? 0),
                'folder_id' => intval($f['folder_id'] ?? 0),
                'download_count' => intval($f['count'] ?? 0),
                'download_url' => $siteurl . 'down.php?hash=' . $f['hash'],
                'view_url' => is_view($f['type']) ? $siteurl . 'view.php?hash=' . $f['hash'] . '.' . $f['type'] : null,
            ];
        }
        api_result([
            'code' => 0,
            'data' => [
                'page' => $page,
                'limit' => $limit,
                'total' => $total,
                'total_page' => $totalPage,
                'list' => $list,
            ]
        ]);
        break;

    case 'file_info':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $fileId = intval($_GET['id'] ?? 0);
        $fileHash = trim($_GET['hash'] ?? '');
        if ($fileId <= 0 && empty($fileHash)) {
            api_result(['code' => -1, 'msg' => '请提供文件ID或Hash']);
        }
        if ($fileId > 0) {
            $file = $DB->getRow("SELECT * FROM pre_file WHERE id=:id AND uid=:uid LIMIT 1", [':id' => $fileId, ':uid' => $auth['uid']]);
        } else {
            if (!preg_match('/^[0-9a-z]{32}$/i', $fileHash)) {
                api_result(['code' => -1, 'msg' => 'Hash格式不正确']);
            }
            $file = $DB->getRow("SELECT * FROM pre_file WHERE hash=:hash AND uid=:uid LIMIT 1", [':hash' => $fileHash, ':uid' => $auth['uid']]);
        }
        if (!$file) {
            api_result(['code' => -1, 'msg' => '文件不存在或无权限']);
        }
        api_result([
            'code' => 0,
            'data' => [
                'id' => intval($file['id']),
                'name' => $file['name'],
                'type' => $file['type'],
                'size' => intval($file['size']),
                'size_formatted' => size_format(intval($file['size'])),
                'hash' => $file['hash'],
                'addtime' => $file['addtime'],
                'ip' => $file['ip'],
                'hide' => intval($file['hide'] ?? 0),
                'block' => intval($file['block'] ?? 0),
                'folder_id' => intval($file['folder_id'] ?? 0),
                'download_count' => intval($file['count'] ?? 0),
                'has_password' => !empty($file['pwd']),
                'download_url' => $siteurl . 'down.php?hash=' . $file['hash'],
                'view_url' => is_view($file['type']) ? $siteurl . 'view.php?hash=' . $file['hash'] . '.' . $file['type'] : null,
                'share_key' => $file['share_key'] ?? null,
                'share_type' => intval($file['share_type'] ?? 0),
                'share_count' => intval($file['share_count'] ?? 0),
                'description' => $file['description'] ?? '',
            ]
        ]);
        break;

    case 'file_search':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $keyword = trim($_GET['kw'] ?? '');
        if (empty($keyword)) {
            api_result(['code' => -1, 'msg' => '请输入搜索关键词']);
        }
        if (mb_strlen($keyword, 'UTF-8') > 50) {
            api_result(['code' => -1, 'msg' => '搜索关键词过长']);
        }
        $page = max(1, intval($_GET['page'] ?? 1));
        $limit = min(100, max(1, intval($_GET['limit'] ?? 20)));
        $offset = ($page - 1) * $limit;
        $typeFilter = trim($_GET['type'] ?? '');
        $where = "uid=:uid AND name LIKE :kw";
        $params = [':uid' => $auth['uid'], ':kw' => '%' . $keyword . '%'];
        if (!empty($typeFilter)) {
            $validTypes = array_filter(explode(',', $typeFilter), fn($t) => preg_match('/^[a-zA-Z0-9]+$/', trim($t)));
            if (!empty($validTypes)) {
                $placeholders = [];
                foreach ($validTypes as $i => $vt) {
                    $key = ':type' . $i;
                    $placeholders[] = $key;
                    $params[$key] = strtolower(trim($vt));
                }
                $where .= " AND LOWER(type) IN (" . implode(',', $placeholders) . ")";
            }
        }
        $total = intval($DB->getColumn("SELECT COUNT(*) FROM pre_file WHERE {$where}", $params));
        $totalPage = ceil($total / $limit);
        $files = $DB->getAll("SELECT id, name, type, size, hash, addtime, hide, folder_id, count FROM pre_file WHERE {$where} ORDER BY id DESC LIMIT {$offset},{$limit}", $params);
        $list = [];
        foreach ((array)$files as $f) {
            $list[] = [
                'id' => intval($f['id']),
                'name' => $f['name'],
                'type' => $f['type'],
                'size' => intval($f['size']),
                'size_formatted' => size_format(intval($f['size'])),
                'hash' => $f['hash'],
                'addtime' => $f['addtime'],
                'hide' => intval($f['hide'] ?? 0),
                'folder_id' => intval($f['folder_id'] ?? 0),
                'download_count' => intval($f['count'] ?? 0),
            ];
        }
        api_result([
            'code' => 0,
            'data' => [
                'keyword' => $keyword,
                'page' => $page,
                'limit' => $limit,
                'total' => $total,
                'total_page' => $totalPage,
                'list' => $list,
            ]
        ]);
        break;

    case 'file_rename':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $fileId = intval($_POST['file_id'] ?? 0);
        $newName = trim($_POST['new_name'] ?? '');
        if ($fileId <= 0) {
            api_result(['code' => -1, 'msg' => '请提供文件ID']);
        }
        if (empty($newName)) {
            api_result(['code' => -1, 'msg' => '新文件名不能为空']);
        }
        $file = $DB->getRow("SELECT * FROM pre_file WHERE id=:id AND uid=:uid LIMIT 1", [':id' => $fileId, ':uid' => $auth['uid']]);
        if (!$file) {
            api_result(['code' => -1, 'msg' => '文件不存在或无权限']);
        }
        $newName = str_replace(['/', '\\', ':', '*', '"', '<', '>', '|', '?'], '', $newName);
        $result = $DB->exec("UPDATE pre_file SET name=:name WHERE id=:id", [':name' => $newName, ':id' => $fileId]);
        if ($result !== false) {
            api_result(['code' => 0, 'msg' => '重命名成功']);
        } else {
            api_result(['code' => -1, 'msg' => '重命名失败']);
        }
        break;

    case 'file_delete':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $fileId = intval($_POST['file_id'] ?? 0);
        if ($fileId <= 0) {
            api_result(['code' => -1, 'msg' => '请提供文件ID']);
        }
        $file = $DB->getRow("SELECT * FROM pre_file WHERE id=:id AND uid=:uid LIMIT 1", [':id' => $fileId, ':uid' => $auth['uid']]);
        if (!$file) {
            api_result(['code' => -1, 'msg' => '文件不存在或无权限']);
        }
        if ($file['block'] == 1) {
            api_result(['code' => -1, 'msg' => '文件已被冻结，无法删除']);
        }
        $count = intval($DB->getColumn("SELECT COUNT(*) FROM pre_file WHERE hash=:hash", [':hash' => $file['hash']]));
        if ($count <= 1) {
            $stor->delete($file['hash']);
        }
        $result = $DB->exec("DELETE FROM pre_file WHERE id=:id", [':id' => $fileId]);
        if ($result) {
            $DB->exec("UPDATE pre_user SET storage_used=storage_used-:size WHERE uid=:uid AND storage_used>=:size", [':size' => $file['size'], ':uid' => $auth['uid']]);
            api_result(['code' => 0, 'msg' => '删除成功']);
        } else {
            api_result(['code' => -1, 'msg' => '删除失败']);
        }
        break;

    case 'file_toggle_hide':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $fileId = intval($_POST['file_id'] ?? 0);
        if ($fileId <= 0) {
            api_result(['code' => -1, 'msg' => '请提供文件ID']);
        }
        $file = $DB->getRow("SELECT * FROM pre_file WHERE id=:id AND uid=:uid LIMIT 1", [':id' => $fileId, ':uid' => $auth['uid']]);
        if (!$file) {
            api_result(['code' => -1, 'msg' => '文件不存在或无权限']);
        }
        $newHide = intval($file['hide'] ?? 0) === 1 ? 0 : 1;
        $DB->exec("UPDATE pre_file SET hide=:hide WHERE id=:id", [':hide' => $newHide, ':id' => $fileId]);
        api_result(['code' => 0, 'msg' => '操作成功', 'data' => ['hide' => $newHide]]);
        break;

    case 'share_create':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $fileId = intval($_POST['file_id'] ?? 0);
        if ($fileId <= 0) {
            api_result(['code' => -1, 'msg' => '请提供文件ID']);
        }
        $file = $DB->getRow("SELECT id, hash FROM pre_file WHERE id=:id AND uid=:uid LIMIT 1", [':id' => $fileId, ':uid' => $auth['uid']]);
        if (!$file) {
            api_result(['code' => -1, 'msg' => '文件不存在或无权限']);
        }
        $columns = $DB->getAll("SHOW COLUMNS FROM pre_file");
        $columnNames = [];
        foreach ((array)$columns as $col) {
            if (isset($col['Field'])) {
                $columnNames[$col['Field']] = true;
            }
        }
        if (!isset($columnNames['share_key'])) {
            $DB->exec("ALTER TABLE pre_file ADD COLUMN share_key varchar(64) DEFAULT NULL");
        }
        if (!isset($columnNames['share_type'])) {
            $DB->exec("ALTER TABLE pre_file ADD COLUMN share_type tinyint(1) NOT NULL DEFAULT 0");
        }
        if (!isset($columnNames['share_notice'])) {
            $DB->exec("ALTER TABLE pre_file ADD COLUMN share_notice text");
        }
        $row = $DB->getRow("SELECT share_key FROM pre_file WHERE id=:id LIMIT 1", [':id' => $fileId]);
        $shareKey = !empty($row['share_key']) ? $row['share_key'] : substr(md5(uniqid((string)$auth['uid'], true) . mt_rand()), 0, 16);
        $DB->exec("UPDATE pre_file SET share_key=:key, share_type=0 WHERE id=:id", [':key' => $shareKey, ':id' => $fileId]);
        $shareLink = $siteurl . 'share.php?key=' . $shareKey;
        api_result([
            'code' => 0,
            'msg' => '分享链接创建成功',
            'data' => [
                'share_key' => $shareKey,
                'share_link' => $shareLink,
                'direct_link' => $siteurl . 'file.php?hash=' . $file['hash'],
            ]
        ]);
        break;

    case 'share_revoke':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $fileId = intval($_POST['file_id'] ?? 0);
        if ($fileId <= 0) {
            api_result(['code' => -1, 'msg' => '请提供文件ID']);
        }
        $file = $DB->getRow("SELECT id FROM pre_file WHERE id=:id AND uid=:uid LIMIT 1", [':id' => $fileId, ':uid' => $auth['uid']]);
        if (!$file) {
            api_result(['code' => -1, 'msg' => '文件不存在或无权限']);
        }
        $DB->exec("UPDATE pre_file SET share_key=:key WHERE id=:id", [':key' => null, ':id' => $fileId]);
        api_result(['code' => 0, 'msg' => '分享链接已撤销']);
        break;

    case 'share_info':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $fileId = intval($_GET['file_id'] ?? 0);
        if ($fileId <= 0) {
            api_result(['code' => -1, 'msg' => '请提供文件ID']);
        }
        $file = $DB->getRow("SELECT id, name, hash, share_key, share_type, share_notice, share_count FROM pre_file WHERE id=:id AND uid=:uid LIMIT 1", [':id' => $fileId, ':uid' => $auth['uid']]);
        if (!$file) {
            api_result(['code' => -1, 'msg' => '文件不存在或无权限']);
        }
        $shareLink = !empty($file['share_key']) ? $siteurl . 'share.php?key=' . $file['share_key'] : null;
        api_result([
            'code' => 0,
            'data' => [
                'file_id' => intval($file['id']),
                'name' => $file['name'],
                'share_key' => $file['share_key'] ?? null,
                'share_type' => intval($file['share_type'] ?? 0),
                'share_notice' => $file['share_notice'] ?? '',
                'share_count' => intval($file['share_count'] ?? 0),
                'share_link' => $shareLink,
                'direct_link' => $siteurl . 'file.php?hash=' . $file['hash'],
                'is_shared' => !empty($file['share_key']),
            ]
        ]);
        break;

    case 'folder_list':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $parentId = intval($_GET['parent_id'] ?? 0);
        $folder = new \lib\Folder($DB);
        $folders = $folder->getFolders($auth['uid'], $parentId);
        $path = $folder->getPath($auth['uid'], $parentId);
        api_result([
            'code' => 0,
            'data' => [
                'parent_id' => $parentId,
                'folders' => $folders,
                'path' => $path,
            ]
        ]);
        break;

    case 'folder_create':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $name = trim($_POST['name'] ?? '');
        $parentId = intval($_POST['parent_id'] ?? 0);
        if (empty($name)) {
            api_result(['code' => -1, 'msg' => '文件夹名称不能为空']);
        }
        if (mb_strlen($name, 'UTF-8') > 50) {
            api_result(['code' => -1, 'msg' => '文件夹名称过长']);
        }
        $folder = new \lib\Folder($DB);
        $result = $folder->create($auth['uid'], $name, $parentId);
        api_result($result);
        break;

    case 'stats_summary':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $u = $auth['userrow'];
        $storageUsed = intval($u['storage_used'] ?? 0);
        $storageLimit = intval($u['storage_limit'] ?? 0);
        $storageUsedMb = round($storageUsed / 1048576, 2);
        $storageLimitMb = $storageLimit > 0 ? round($storageLimit * 1048576 / 1048576, 2) : 0;
        $trafficQuotaInfo = get_traffic_quota($auth['uid']);
        $trafficUsed = intval($trafficQuotaInfo['quota_used'] ?? 0);
        $trafficLimit = intval($trafficQuotaInfo['quota_limit'] ?? 0);
        $trafficUsedMb = round($trafficUsed / 1048576, 2);
        $trafficLimitMb = $trafficLimit > 0 ? round($trafficLimit / 1048576, 2) : 0;
        $fileCount = intval($DB->getColumn("SELECT COUNT(*) FROM pre_file WHERE uid=:uid", [':uid' => $auth['uid']]));
        $folderCount = intval($DB->getColumn("SELECT COUNT(*) FROM pre_folder WHERE uid=:uid", [':uid' => $auth['uid']]));
        $todayUploads = intval($DB->getColumn("SELECT COUNT(*) FROM pre_file WHERE uid=:uid AND addtime>=:today", [':uid' => $auth['uid'], ':today' => date('Y-m-d 00:00:00')]));
        $totalDownloads = intval($DB->getColumn("SELECT SUM(count) FROM pre_file WHERE uid=:uid", [':uid' => $auth['uid']]));
        api_result([
            'code' => 0,
            'data' => [
                'storage' => [
                    'used_bytes' => $storageUsed,
                    'used_mb' => $storageUsedMb,
                    'limit_mb' => $storageLimitMb,
                    'limit_bytes' => $storageLimit * 1048576,
                    'is_unlimited' => $storageLimit <= 0,
                    'usage_percent' => $storageLimit > 0 ? round(($storageUsed / ($storageLimit * 1048576)) * 100, 2) : 0,
                ],
                'traffic' => [
                    'used_bytes' => $trafficUsed,
                    'used_mb' => $trafficUsedMb,
                    'limit_mb' => $trafficLimitMb,
                    'limit_bytes' => $trafficLimit,
                    'is_unlimited' => $trafficLimit <= 0,
                    'usage_percent' => $trafficLimit > 0 ? round(($trafficUsed / $trafficLimit) * 100, 2) : 0,
                    'reset_interval_days' => intval($trafficQuotaInfo['quota_reset_interval'] ?? 30),
                ],
                'files' => [
                    'total_count' => $fileCount,
                    'today_uploads' => $todayUploads,
                    'total_downloads' => $totalDownloads,
                ],
                'folders' => [
                    'total_count' => $folderCount,
                ],
            ]
        ]);
        break;

    case 'traffic_logs':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $page = max(1, intval($_GET['page'] ?? 1));
        $limit = min(100, max(1, intval($_GET['limit'] ?? 20)));
        $offset = ($page - 1) * $limit;
        $days = min(90, max(1, intval($_GET['days'] ?? 7)));
        $since = date('Y-m-d H:i:s', time() - $days * 86400);
        $total = intval($DB->getColumn("SELECT COUNT(*) FROM pre_traffic_log WHERE owner_uid=:uid AND created_at>=:since", [':uid' => $auth['uid'], ':since' => $since]));
        $totalPage = ceil($total / $limit);
        $logs = $DB->getAll("SELECT * FROM pre_traffic_log WHERE owner_uid=:uid AND created_at>=:since ORDER BY id DESC LIMIT {$offset},{$limit}", [':uid' => $auth['uid'], ':since' => $since]);
        $list = [];
        foreach ((array)$logs as $log) {
            $list[] = [
                'id' => intval($log['id'] ?? 0),
                'file_id' => intval($log['file_id'] ?? 0),
                'file_name' => $log['file_name'] ?? '',
                'file_size' => intval($log['file_size'] ?? 0),
                'file_type' => $log['file_type'] ?? '',
                'access_type' => $log['access_type'] ?? '',
                'traffic_size' => intval($log['traffic_size'] ?? 0),
                'traffic_size_formatted' => size_format(intval($log['traffic_size'] ?? 0)),
                'visitor_ip' => $log['visitor_ip'] ?? '',
                'visitor_uid' => intval($log['visitor_uid'] ?? 0),
                'created_at' => $log['created_at'] ?? '',
            ];
        }
        api_result([
            'code' => 0,
            'data' => [
                'page' => $page,
                'limit' => $limit,
                'total' => $total,
                'total_page' => $totalPage,
                'days' => $days,
                'list' => $list,
            ]
        ]);
        break;

    case 'disk_usage':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $storageUsed = intval($auth['userrow']['storage_used'] ?? 0);
        $storageLimit = intval($auth['userrow']['storage_limit'] ?? 0);
        $typeStats = $DB->getAll("SELECT type, COUNT(*) as cnt, SUM(size) as total_size FROM pre_file WHERE uid=:uid GROUP BY type ORDER BY total_size DESC", [':uid' => $auth['uid']]);
        $breakdown = [];
        foreach ((array)$typeStats as $ts) {
            $breakdown[] = [
                'type' => $ts['type'],
                'count' => intval($ts['cnt'] ?? 0),
                'total_size_bytes' => intval($ts['total_size'] ?? 0),
                'total_size_formatted' => size_format(intval($ts['total_size'] ?? 0)),
            ];
        }
        api_result([
            'code' => 0,
            'data' => [
                'total_used_bytes' => $storageUsed,
                'total_used_formatted' => size_format($storageUsed),
                'storage_limit_mb' => $storageLimit,
                'is_unlimited' => $storageLimit <= 0,
                'usage_percent' => $storageLimit > 0 ? round(($storageUsed / ($storageLimit * 1048576)) * 100, 2) : 0,
                'by_type' => $breakdown,
            ]
        ]);
        break;

    case 'api_key_info':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $apiKey = $auth['userrow']['api_key'] ?? '';
        if (empty($apiKey)) {
            $apiKey = substr(md5(uniqid((string)$auth['uid'], true) . mt_rand()), 0, 32);
            $DB->exec("UPDATE pre_user SET api_key=:key WHERE uid=:uid", [':key' => $apiKey, ':uid' => $auth['uid']]);
        }
        api_result([
            'code' => 0,
            'data' => [
                'api_key' => $apiKey,
                'uid' => $auth['uid'],
                'hint' => '在请求参数中添加api_key=' . $apiKey . ' 即可使用API密钥认证',
            ]
        ]);
        break;

    case 'regenerate_api_key':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $newKey = substr(md5(uniqid((string)$auth['uid'], true) . mt_rand()), 0, 32);
        $DB->exec("UPDATE pre_user SET api_key=:key WHERE uid=:uid", [':key' => $newKey, ':uid' => $auth['uid']]);
        api_result([
            'code' => 0,
            'msg' => 'API密钥已重新生成',
            'data' => [
                'api_key' => $newKey,
                'uid' => $auth['uid'],
            ]
        ]);
        break;

    case 'redeem':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $cardCode = trim($_POST['card_code'] ?? '');
        if (empty($cardCode)) {
            api_result(['code' => -1, 'msg' => '请输入卡密代码']);
        }
        $result = redeem_card($cardCode, $auth['uid']);
        if ($result['code'] === 0) {
            $resourceInfo = get_user_resource_info($auth['uid']);
            api_result([
                'code' => 0,
                'msg' => $result['msg'],
                'data' => [
                    'storage_added_mb' => round(intval($result['storage_added'] ?? 0) / 1048576, 2),
                    'traffic_added_mb' => round(intval($result['traffic_added'] ?? 0) / 1048576, 2),
                    'resource_info' => $resourceInfo,
                ]
            ]);
        } else {
            api_result($result);
        }
        break;

    case 'redeem_history':
        $auth = api_auth_user();
        if ($auth['code'] !== 0) {
            api_result($auth);
        }
        $page = max(1, intval($_GET['page'] ?? 1));
        $limit = min(100, max(1, intval($_GET['limit'] ?? 20)));
        $offset = ($page - 1) * $limit;
        $total = intval($DB->getColumn("SELECT COUNT(*) FROM pre_card_redeem WHERE uid=:uid", [':uid' => $auth['uid']]));
        $totalPage = ceil($total / $limit);
        $records = $DB->getAll("SELECT card_code, addtime FROM pre_card_redeem WHERE uid=:uid ORDER BY id DESC LIMIT {$offset},{$limit}", [':uid' => $auth['uid']]);
        api_result([
            'code' => 0,
            'data' => [
                'page' => $page,
                'limit' => $limit,
                'total' => $total,
                'total_page' => $totalPage,
                'list' => array_map(fn($r) => ['card_code' => $r['card_code'], 'redeem_time' => $r['addtime']], (array)$records),
            ]
        ]);
        break;

    default:
        api_result(['code' => -4, 'msg' => '未指定操作，请查看API文档: ' . $siteurl . 'doc.php']);
        break;
}