<?php
require '../../../zb_system/function/c_system_base.php';
$zbp->Load();

define('CIYUN_PUBLISHER_VERSION', '1.0.2');

ciyun_json_api(function ($data) use ($zbp) {
    $article = new Post();
    $article->Title = $data['title'];
    $article->Content = $data['content'];
    $article->Intro = $data['excerpt'] ?? '';
    $article->CateID = intval($data['category_id'] ?? 0);
    $article->AuthorID = intval($data['author_id'] ?? 1);
    $article->Alias = $data['slug'] ?? '';
    $article->Status = ciyun_force_draft() || ($data['status'] ?? 'draft') !== 'publish' ? ZC_POST_STATUS_DRAFT : ZC_POST_STATUS_PUBLIC;
    if (!empty($data['created_at'])) {
        $article->PostTime = strtotime($data['created_at']);
    }
    $article->Save();
    if (!empty($data['tags']) && is_array($data['tags'])) {
        foreach ($data['tags'] as $tagName) {
            $tag = new Tag();
            $tag->Name = trim($tagName);
            if ($tag->Name !== '') {
                $tag->Save();
                $article->Tags[] = $tag;
            }
        }
        $article->Save();
    }
    ciyun_log('success', $data['title'], 'post_id=' . $article->ID);
    ciyun_response(200, ['success' => true, 'post_id' => $article->ID, 'message' => '发布成功']);
});

function ciyun_json_api($handler) {
    try {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            ciyun_response(405, ['success' => false, 'message' => 'Only POST is allowed']);
        }
        $contentType = $_SERVER['CONTENT_TYPE'] ?? '';
        if (stripos($contentType, 'application/json') === false) {
            ciyun_response(400, ['success' => false, 'message' => 'Content-Type must be application/json']);
        }
        ciyun_check_token();
        ciyun_check_ip();
        $raw = file_get_contents('php://input');
        $data = json_decode($raw, true);
        if (!is_array($data)) {
            ciyun_response(400, ['success' => false, 'message' => 'Invalid JSON']);
        }
        if (($data['action'] ?? '') === 'self_check') {
            ciyun_response(200, ciyun_self_check());
        }
        if (($data['action'] ?? '') === 'version') {
            ciyun_response(200, ciyun_version_payload());
        }
        if (($data['action'] ?? '') === 'logs') {
            ciyun_response(200, ['success' => true, 'items' => ciyun_recent_logs(intval($data['limit'] ?? 50))]);
        }
        if (($data['action'] ?? '') === 'terms') {
            ciyun_response(200, ['success' => true, 'items' => ciyun_terms($data['type'] ?? 'category')]);
        }
        ciyun_validate($data);
        $handler($data);
    } catch (Throwable $e) {
        ciyun_log('error', $_POST['title'] ?? '', $e->getMessage());
        ciyun_response(500, ['success' => false, 'message' => '服务器错误', 'error' => $e->getMessage()]);
    }
}

function ciyun_self_check() {
    global $zbp;
    $token = $zbp->Config('CiyunPublisher')->token;
    $categories = ciyun_terms('category');
    $authors = ciyun_terms('author');
    return [
        'success' => true,
        'message' => 'self_check ok',
        'checks' => [
            'token' => strlen($token) >= 32,
            'log_writable' => ciyun_log_writable(),
            'categories' => count($categories),
            'authors' => count($authors),
            'force_draft' => ciyun_force_draft(),
        ],
        'api' => $zbp->host . 'zb_users/plugin/CiyunPublisher/api.php',
        'version' => CIYUN_PUBLISHER_VERSION,
    ];
}

function ciyun_version_payload() {
    return [
        'success' => true,
        'name' => 'CiyunPublisher',
        'cms' => 'zblogphp',
        'version' => CIYUN_PUBLISHER_VERSION,
    ];
}

function ciyun_recent_logs($limit) {
    $limit = max(1, min($limit, 200));
    $file = __DIR__ . '/publish.log';
    if (!file_exists($file)) {
        return [];
    }
    $lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    if (!is_array($lines)) {
        return [];
    }
    $lines = array_slice($lines, -$limit);
    $items = [];
    foreach (array_reverse($lines) as $line) {
        $parts = explode("\t", $line, 5);
        $items[] = [
            'time' => $parts[0] ?? '',
            'ip' => $parts[1] ?? '',
            'status' => $parts[2] ?? '',
            'title' => $parts[3] ?? '',
            'message' => $parts[4] ?? '',
        ];
    }
    return $items;
}

function ciyun_log_writable() {
    $file = __DIR__ . '/publish.log';
    if (file_exists($file)) {
        return is_writable($file);
    }
    return is_writable(__DIR__);
}

function ciyun_terms($type) {
    global $zbp;
    $items = [];
    if ($type === 'author') {
        $members = [];
        if (isset($zbp->members) && is_array($zbp->members)) {
            $members = $zbp->members;
        } elseif (method_exists($zbp, 'GetMemberList')) {
            try {
                $members = $zbp->GetMemberList();
            } catch (Throwable $e) {
                $members = [];
            }
        }
        foreach ($members as $member) {
            $id = intval($member->ID ?? $member->id ?? 0);
            $name = trim($member->Name ?? $member->name ?? $member->Alias ?? '');
            if ($id > 0 && $name !== '') {
                $items[] = ['id' => $id, 'name' => $name];
            }
        }
        return $items;
    }
    if ($type === 'tag') {
        $tags = isset($zbp->tags) && is_array($zbp->tags) ? $zbp->tags : [];
        foreach ($tags as $tag) {
            $id = intval($tag->ID ?? $tag->id ?? 0);
            $name = trim($tag->Name ?? $tag->name ?? '');
            if ($id > 0 && $name !== '') {
                $items[] = ['id' => $id, 'name' => $name];
            }
        }
        return $items;
    }
    $categories = isset($zbp->categorys) && is_array($zbp->categorys) ? $zbp->categorys : [];
    foreach ($categories as $category) {
        $id = intval($category->ID ?? $category->id ?? 0);
        $name = trim($category->Name ?? $category->name ?? '');
        if ($id > 0 && $name !== '') {
            $items[] = ['id' => $id, 'name' => $name];
        }
    }
    return $items;
}

function ciyun_check_token() {
    global $zbp;
    $token = $zbp->Config('CiyunPublisher')->token;
    $header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if (strlen($token) < 32 || !preg_match('/Bearer\s+(.+)/i', $header, $m) || !hash_equals($token, trim($m[1]))) {
        ciyun_log('unauthorized', '', 'Token error');
        ciyun_response(401, ['success' => false, 'message' => 'Token 错误']);
    }
}

function ciyun_check_ip() {
    global $zbp;
    $list = preg_split('/[\s,]+/', trim($zbp->Config('CiyunPublisher')->whitelist_ips));
    $list = array_filter($list);
    if ($list && !in_array($_SERVER['REMOTE_ADDR'] ?? '', $list, true)) {
        ciyun_response(401, ['success' => false, 'message' => 'IP 不在白名单']);
    }
}

function ciyun_validate($data) {
    if (empty($data['title']) || empty($data['content'])) {
        ciyun_response(400, ['success' => false, 'message' => 'title 和 content 必填']);
    }
    if (ciyun_strlen($data['title']) > 200 || ciyun_strlen($data['content']) > 200000) {
        ciyun_response(400, ['success' => false, 'message' => '标题或正文过长']);
    }
}

function ciyun_strlen($value) {
    return function_exists('mb_strlen') ? mb_strlen($value, 'UTF-8') : strlen($value);
}

function ciyun_force_draft() {
    global $zbp;
    return $zbp->Config('CiyunPublisher')->force_draft === '1';
}

function ciyun_log($status, $title, $message) {
    $line = date('Y-m-d H:i:s') . "\t" . ($_SERVER['REMOTE_ADDR'] ?? '') . "\t" . $status . "\t" . str_replace(["\r", "\n"], ' ', $title) . "\t" . str_replace(["\r", "\n"], ' ', $message) . PHP_EOL;
    file_put_contents(__DIR__ . '/publish.log', $line, FILE_APPEND);
}

function ciyun_response($code, $payload) {
    http_response_code($code);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($payload, JSON_UNESCAPED_UNICODE);
    exit;
}
