<?php
require_once dirname(__DIR__) . '/core/lib/session.php';
cmsStartSession();

if (!cmsValidateAdminSession() || empty($_SESSION['admin_id'])) {
    jsonResponse(['code' => 401, 'msg' => '未登录']);
}

require_once dirname(__DIR__) . '/core/db/db.php';
require_once dirname(__DIR__) . '/core/lib/common.php';
require_once dirname(__DIR__) . '/core/lib/rbac.php';

$db = \Core\Db\DB::getInstance();
cmsRequireAdminPermission(cmsLoadCurrentAdminAccess($db), 'upload', true);

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

switch ($action) {
    case 'upload':
        uploadImage();
        break;
    case 'delete':
        deleteImage();
        break;
    case 'install_template':
    case 'upload_template':
        installTemplatePackage();
        break;
    default:
        jsonResponse(['code' => 400, 'msg' => '未知操作']);
}

function uploadImage()
{
    requireAdminCsrfToken(true);
    $file = $_FILES['file'] ?? null;
    if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
        jsonResponse(['code' => 400, 'msg' => '请选择要上传的图片']);
    }

    $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mimeType = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);

    if (!in_array($mimeType, $allowedTypes, true)) {
        jsonResponse(['code' => 400, 'msg' => '仅支持 JPG、PNG、GIF、WebP 格式']);
    }

    if ($file['size'] > 5 * 1024 * 1024) {
        jsonResponse(['code' => 400, 'msg' => '图片大小不能超过 5MB']);
    }

    $uploadDir = dirname(__DIR__) . '/public/uploads/' . date('Ymd') . '/';
    $saveResult = cmsStoreUploadedImage($file['tmp_name'], $file['name'], $uploadDir, 'img', [
        'apply_watermark' => !isset($_POST['apply_watermark']) || (string) $_POST['apply_watermark'] !== '0',
    ]);
    if (!$saveResult['success']) {
        jsonResponse(['code' => 500, 'msg' => $saveResult['message'] ?? '文件保存失败']);
    }

    $filename = $saveResult['filename'];
    $url = '/public/uploads/' . date('Ymd') . '/' . $filename;
    jsonResponse([
        'code' => 0,
        'msg' => '上传成功',
        'data' => [
            'url' => $url,
            'filename' => $filename,
            'converted' => !empty($saveResult['converted'])
        ]
    ]);
}

function deleteImage()
{
    requireAdminCsrfToken(true);
    $url = $_POST['url'] ?? '';
    if ($url === '') {
        jsonResponse(['code' => 400, 'msg' => '缺少文件路径']);
    }

    $allowedBases = [
        realpath(dirname(__DIR__) . '/public/uploads'),
        realpath(dirname(__DIR__) . '/uploads'),
    ];
    $filepath = realpath(dirname(__DIR__) . '/' . ltrim($url, '/\\'));
    if ($filepath === false || !file_exists($filepath)) {
        jsonResponse(['code' => 404, 'msg' => '文件不存在']);
    }

    $isAllowed = false;
    foreach ($allowedBases as $base) {
        if ($base && strpos($filepath, $base . DIRECTORY_SEPARATOR) === 0) {
            $isAllowed = true;
            break;
        }
    }
    if (!$isAllowed) {
        jsonResponse(['code' => 403, 'msg' => '禁止删除该路径文件']);
    }

    unlink($filepath);
    jsonResponse(['code' => 0, 'msg' => '删除成功']);
}

function installTemplatePackage()
{
    requireAdminCsrfToken(true);

    if (!class_exists('ZipArchive')) {
        jsonResponse(['code' => 500, 'msg' => '服务器未启用 ZipArchive 扩展']);
    }

    $templateKey = trim((string) ($_POST['template_key'] ?? $_POST['template_name'] ?? ''));
    if ($templateKey === '' || !preg_match('/^[A-Za-z0-9_-]+$/', $templateKey)) {
        jsonResponse(['code' => 400, 'msg' => '模板标识不能为空，且只能包含字母、数字、下划线和中划线']);
    }

    $fileField = isset($_FILES['template_zip']) ? 'template_zip' : (isset($_FILES['template_package']) ? 'template_package' : '');
    if ($fileField === '' || (int) ($_FILES[$fileField]['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
        jsonResponse(['code' => 400, 'msg' => '请选择要安装的模板 ZIP 文件']);
    }

    $templateRoot = dirname(__DIR__) . '/template/';
    $targetDir = $templateRoot . $templateKey . '/';
    if (!is_dir($templateRoot) && !mkdir($templateRoot, 0755, true)) {
        jsonResponse(['code' => 500, 'msg' => '模板目录创建失败']);
    }

    clearTemplateDirectory($targetDir);
    if (!is_dir($targetDir) && !mkdir($targetDir, 0755, true)) {
        jsonResponse(['code' => 500, 'msg' => '模板安装目录创建失败']);
    }

    $zipFile = $targetDir . '__upload.zip';
    if (!move_uploaded_file($_FILES[$fileField]['tmp_name'], $zipFile)) {
        jsonResponse(['code' => 500, 'msg' => '上传文件保存失败']);
    }

    $zip = new ZipArchive();
    if ($zip->open($zipFile) !== true) {
        @unlink($zipFile);
        jsonResponse(['code' => 400, 'msg' => 'ZIP 文件打开失败']);
    }

    $extractResult = extractTemplateZipSafely($zip, $targetDir);
    $zip->close();
    @unlink($zipFile);
    if (!$extractResult['success']) {
        clearTemplateDirectory($targetDir);
        jsonResponse(['code' => 400, 'msg' => $extractResult['message']]);
    }

    $db = \Core\Db\DB::getInstance();
    foreach (['site_template', 'last_template_key'] as $configKey) {
        $exists = $db->fetch("SELECT id FROM {$db->table('config')} WHERE config_key = ?", [$configKey]);
        if ($exists) {
            $db->update('config', ['config_value' => $templateKey], 'config_key = ?', [$configKey]);
        } else {
            $db->insert('config', [
                'config_key' => $configKey,
                'config_value' => $templateKey,
                'config_type' => 'text',
                'config_group' => 'basic',
            ]);
        }
    }

    jsonResponse(['code' => 200, 'msg' => '模板安装成功', 'template' => $templateKey]);
}

function clearTemplateDirectory($dir)
{
    if (!is_dir($dir)) {
        return;
    }

    $items = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    foreach ($items as $item) {
        $path = $item->getPathname();
        $item->isDir() ? @rmdir($path) : @unlink($path);
    }
    @rmdir($dir);
}

function extractTemplateZipSafely(ZipArchive $zip, $targetDir)
{
    $targetRoot = realpath($targetDir);
    if ($targetRoot === false) {
        return ['success' => false, 'message' => '模板安装目录不存在'];
    }

    for ($i = 0; $i < $zip->numFiles; $i++) {
        $entry = (string) $zip->getNameIndex($i);
        $entry = str_replace('\\', '/', $entry);
        $entry = ltrim($entry, '/');
        if ($entry === '' || strpos($entry, '../') !== false || preg_match('/^[A-Za-z]:\//', $entry)) {
            return ['success' => false, 'message' => 'ZIP 包含非法路径'];
        }

        $destination = $targetRoot . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $entry);
        $parent = dirname($destination);
        if (!is_dir($parent) && !mkdir($parent, 0755, true)) {
            return ['success' => false, 'message' => '模板文件目录创建失败'];
        }

        if (substr($entry, -1) === '/') {
            if (!is_dir($destination) && !mkdir($destination, 0755, true)) {
                return ['success' => false, 'message' => '模板目录创建失败'];
            }
            continue;
        }

        $source = $zip->getStream($zip->getNameIndex($i));
        if (!$source) {
            return ['success' => false, 'message' => '模板文件读取失败'];
        }
        $target = fopen($destination, 'wb');
        if (!$target) {
            fclose($source);
            return ['success' => false, 'message' => '模板文件写入失败'];
        }
        stream_copy_to_stream($source, $target);
        fclose($source);
        fclose($target);
    }

    return ['success' => true, 'message' => ''];
}

function jsonResponse($data)
{
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}
