<?php
define('EMLOG_ROOT', dirname(__DIR__, 3) . '/');
require_once EMLOG_ROOT . 'init.php';

define('CIYUN_PUBLISHER_VERSION', '1.0.2');

$configFile = __DIR__ . '/config.php';
$config = file_exists($configFile) ? include $configFile : ['token' => '', 'whitelist_ips' => '', 'force_draft' => '1'];

try {
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        ciyun_response(405, ['success' => false, 'message' => 'Only POST is allowed']);
    }
    if (stripos($_SERVER['CONTENT_TYPE'] ?? '', 'application/json') === false) {
        ciyun_response(400, ['success' => false, 'message' => 'Content-Type must be application/json']);
    }
    ciyun_check_token($config);
    ciyun_check_ip($config);
    $data = json_decode(file_get_contents('php://input'), true);
    if (!is_array($data)) {
        ciyun_response(400, ['success' => false, 'message' => 'Invalid JSON']);
    }
    if (($data['action'] ?? '') === 'self_check') {
        ciyun_response(200, ciyun_self_check($config));
    }
    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);
    $postId = ciyun_save_article($data, $config);
    ciyun_log('success', $data['title'], 'post_id=' . $postId);
    ciyun_response(200, ['success' => true, 'post_id' => $postId, 'message' => '发布成功']);
} catch (Throwable $e) {
    ciyun_log('error', '', $e->getMessage());
    ciyun_response(500, ['success' => false, 'message' => '服务器错误', 'error' => $e->getMessage()]);
}

function ciyun_self_check($config) {
    $categories = ciyun_terms('category');
    $authors = ciyun_terms('author');
    return [
        'success' => true,
        'message' => 'self_check ok',
        'checks' => [
            'token' => strlen($config['token'] ?? '') >= 32,
            'log_writable' => ciyun_log_writable(),
            'categories' => count($categories),
            'authors' => count($authors),
            'force_draft' => ($config['force_draft'] ?? '1') === '1',
        ],
        'api' => '/content/plugins/ciyun_publisher/api.php',
        'version' => CIYUN_PUBLISHER_VERSION,
    ];
}

function ciyun_version_payload() {
    return [
        'success' => true,
        'name' => 'CiyunPublisher',
        'cms' => 'emlog',
        '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) {
    if ($type === 'author') {
        return ciyun_authors();
    }
    if ($type === 'tag') {
        return ciyun_tags();
    }
    return ciyun_categories();
}

function ciyun_categories() {
    $items = [];
    if (!class_exists('Sort_Model')) {
        return $items;
    }
    $model = new Sort_Model();
    $rows = ciyun_model_rows($model, ['getSorts', 'getSort', 'getAllSorts']);
    if (!is_array($rows)) {
        return $items;
    }
    foreach ($rows as $row) {
        $id = ciyun_value($row, ['sid', 'sortid', 'id', 'ID']);
        $name = ciyun_value($row, ['sortname', 'name', 'Name', 'title']);
        if (intval($id) > 0 && trim((string)$name) !== '') {
            $items[] = ['id' => intval($id), 'name' => trim((string)$name)];
        }
    }
    return $items;
}

function ciyun_authors() {
    $items = [];
    if (!class_exists('User_Model')) {
        return $items;
    }
    $model = new User_Model();
    $rows = ciyun_model_rows($model, ['getUsers', 'getUserList', 'getAllUsers']);
    if (!is_array($rows)) {
        return $items;
    }
    foreach ($rows as $row) {
        $id = ciyun_value($row, ['uid', 'id', 'ID']);
        $name = ciyun_value($row, ['username', 'nickname', 'name', 'Name']);
        if (intval($id) > 0 && trim((string)$name) !== '') {
            $items[] = ['id' => intval($id), 'name' => trim((string)$name)];
        }
    }
    return $items;
}

function ciyun_tags() {
    $items = [];
    if (!class_exists('Tag_Model')) {
        return $items;
    }
    $model = new Tag_Model();
    $rows = ciyun_model_rows($model, ['getTags', 'getTag', 'getAllTags']);
    if (!is_array($rows)) {
        return $items;
    }
    foreach ($rows as $row) {
        $id = ciyun_value($row, ['tid', 'id', 'ID']);
        $name = ciyun_value($row, ['tagname', 'name', 'Name']);
        if (intval($id) > 0 && trim((string)$name) !== '') {
            $items[] = ['id' => intval($id), 'name' => trim((string)$name)];
        }
    }
    return $items;
}

function ciyun_model_rows($model, $methods) {
    foreach ($methods as $method) {
        if (!method_exists($model, $method)) {
            continue;
        }
        try {
            $rows = $model->$method();
            if (is_array($rows)) {
                return $rows;
            }
        } catch (Throwable $e) {
            continue;
        }
    }
    return [];
}

function ciyun_value($row, $keys) {
    foreach ($keys as $key) {
        if (is_array($row) && array_key_exists($key, $row)) {
            return $row[$key];
        }
        if (is_object($row) && isset($row->$key)) {
            return $row->$key;
        }
    }
    return '';
}

function ciyun_save_article($data, $config) {
    $isDraft = ($config['force_draft'] ?? '1') === '1' || ($data['status'] ?? 'draft') !== 'publish';
    $logData = [
        'title' => $data['title'],
        'content' => $data['content'],
        'excerpt' => $data['excerpt'] ?? '',
        'gid' => 0,
        'date' => !empty($data['created_at']) ? strtotime($data['created_at']) : time(),
        'author' => intval($data['author_id'] ?? UID),
        'sortid' => intval($data['category_id'] ?? -1),
        'type' => 'blog',
        'hide' => $isDraft ? 'y' : 'n',
        'allow_remark' => 'y',
        'alias' => $data['slug'] ?? '',
        'password' => '',
        'template' => '',
        'tags' => is_array($data['tags'] ?? null) ? implode(',', $data['tags']) : '',
    ];
    $logModel = new Log_Model();
    if (method_exists($logModel, 'addlog')) {
        return $logModel->addlog($logData);
    }
    if (method_exists($logModel, 'addLog')) {
        return $logModel->addLog($logData);
    }
    throw new RuntimeException('当前 emlog 版本未找到可用的文章保存方法');
}

function ciyun_check_token($config) {
    $token = $config['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($config) {
    $list = preg_split('/[\s,]+/', trim($config['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_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;
}
