<?php
if (!defined('ABSPATH')) {
    exit;
}

define('ICEFOX_THEME_VERSION', '1.0.0');
define('ICEFOX_DB_VERSION', '1.0.0');

function icefox_get_default_options()
{
    return array(
        'top_video' => 0,
        'top_image' => 0,
        'avatar_link' => '',
        'tencent_map_key' => '',
        'beian_info' => '',
        'auto_collapse' => '1',
        'custom_css' => '',
        'custom_js' => '',
        'analytics' => '',
    );
}

function icefox_get_option($key, $fallback = null)
{
    $defaults = icefox_get_default_options();

    if (array_key_exists($key, $defaults)) {
        $fallback = $defaults[$key];
    }

    return get_theme_mod('icefox_' . $key, $fallback);
}

function icefox_get_media_url($key)
{
    $value = icefox_get_option($key);

    if (empty($value)) {
        return '';
    }

    if (is_numeric($value)) {
        $url = wp_get_attachment_url((int) $value);

        return $url ? $url : '';
    }

    return esc_url_raw($value);
}

function icefox_get_frontend_tencent_map_key()
{
    if (is_admin() || !current_user_can('edit_posts')) {
        return '';
    }

    return trim((string) icefox_get_option('tencent_map_key'));
}

function icefox_setup_theme()
{
    add_theme_support('title-tag');
    add_theme_support('automatic-feed-links');
    add_theme_support('post-thumbnails');
    add_theme_support(
        'html5',
        array(
            'search-form',
            'comment-form',
            'comment-list',
            'gallery',
            'caption',
            'style',
            'script',
        )
    );
}
add_action('after_setup_theme', 'icefox_setup_theme');

add_filter('pre_option_link_manager_enabled', '__return_true');

function icefox_cleanup_legacy_theme_mods()
{
    if (get_option('icefox_legacy_cleanup_v1') === '1') {
        return;
    }

    remove_theme_mod('icefox_logo_image');
    update_option('icefox_legacy_cleanup_v1', '1');
}
add_action('init', 'icefox_cleanup_legacy_theme_mods');

function icefox_enqueue_assets()
{
    if (!is_admin() && current_user_can('edit_posts')) {
        wp_enqueue_media();
    }

    $tencent_map_key = icefox_get_frontend_tencent_map_key();

    if ($tencent_map_key !== '') {
        wp_enqueue_script(
            'icefox-tencent-map',
            add_query_arg(
                array(
                    'v' => '1.exp',
                    'key' => $tencent_map_key,
                    'libraries' => 'service',
                ),
                'https://map.qq.com/api/gljs'
            ),
            array(),
            null,
            false
        );
    }

    if (!is_admin()) {
        wp_deregister_script('jquery');
        wp_register_script(
            'jquery',
            get_template_directory_uri() . '/assets/js/jquery.min.js',
            array(),
            '3.7.1',
            false
        );
    }

    wp_enqueue_style(
        'icefox-bulma',
        get_template_directory_uri() . '/assets/css/bulma.min.css',
        array(),
        '1.0.0'
    );
    wp_enqueue_style(
        'icefox-fancybox',
        get_template_directory_uri() . '/assets/css/fancybox.css',
        array('icefox-bulma'),
        '5.0.0'
    );
    wp_enqueue_style(
        'icefox-main',
        get_template_directory_uri() . '/assets/css/icefox.css',
        array('icefox-fancybox'),
        filemtime(get_template_directory() . '/assets/css/icefox.css')
    );

    wp_enqueue_script(
        'jquery',
        get_template_directory_uri() . '/assets/js/jquery.min.js',
        array(),
        '3.7.1',
        false
    );
    wp_enqueue_script(
        'icefox-alpine',
        get_template_directory_uri() . '/assets/js/alpinejs.js',
        array(),
        '3.14.0',
        false
    );
    wp_enqueue_script(
        'icefox-fancybox',
        get_template_directory_uri() . '/assets/js/fancybox.umd.js',
        array(),
        '5.0.0',
        false
    );
    wp_enqueue_script(
        'icefox-scrollload',
        get_template_directory_uri() . '/assets/js/scrollload.min.js',
        array(),
        '1.0.0',
        false
    );
    wp_enqueue_script(
        'icefox-music-player',
        get_template_directory_uri() . '/assets/js/music-player.js',
        array('jquery'),
        filemtime(get_template_directory() . '/assets/js/music-player.js'),
        false
    );
    wp_enqueue_script(
        'icefox-app',
        get_template_directory_uri() . '/assets/js/icefox.js',
        array('jquery', 'icefox-fancybox', 'icefox-scrollload', 'icefox-music-player'),
        filemtime(get_template_directory() . '/assets/js/icefox.js'),
        false
    );
}
add_action('wp_enqueue_scripts', 'icefox_enqueue_assets', 20);

function icefox_output_custom_head_code()
{
    $custom_css = (string) icefox_get_option('custom_css');
    $analytics = (string) icefox_get_option('analytics');

    if ($custom_css !== '') {
        echo "<style id=\"icefox-custom-css\">\n" . $custom_css . "\n</style>\n";
    }

    if ($analytics !== '') {
        echo $analytics . "\n";
    }
}
add_action('wp_head', 'icefox_output_custom_head_code', 99);

function icefox_output_custom_footer_code()
{
    $custom_js = (string) icefox_get_option('custom_js');

    if ($custom_js !== '') {
        echo "<script id=\"icefox-custom-js\">\n" . $custom_js . "\n</script>\n";
    }
}
add_action('wp_footer', 'icefox_output_custom_footer_code', 99);

function icefox_sanitize_raw_text($value)
{
    return is_string($value) ? trim($value) : '';
}

function icefox_register_customizer($wp_customize)
{
    $wp_customize->add_section(
        'icefox_theme_options',
        array(
            'title' => 'Icefox 主题设置',
            'priority' => 30,
        )
    );

    $media_fields = array(
        'top_video' => array('label' => '顶部背景视频', 'mime_type' => 'video'),
        'top_image' => array('label' => '顶部背景图片', 'mime_type' => 'image'),
    );

    foreach ($media_fields as $key => $field) {
        $wp_customize->add_setting(
            'icefox_' . $key,
            array(
                'default' => icefox_get_default_options()[$key],
                'sanitize_callback' => 'absint',
            )
        );

        $wp_customize->add_control(
            new WP_Customize_Media_Control(
                $wp_customize,
                'icefox_' . $key,
                array(
                    'section' => 'icefox_theme_options',
                    'label' => $field['label'],
                    'mime_type' => $field['mime_type'],
                )
            )
        );
    }

    $text_fields = array(
        'avatar_link' => array('label' => '头像点击跳转链接', 'type' => 'url', 'sanitize' => 'esc_url_raw'),
        'tencent_map_key' => array(
            'label' => '腾讯地图 API Key',
            'type' => 'text',
            'sanitize' => 'sanitize_text_field',
            'description' => '用于前端撰写中的“所在位置”地址获取，请在腾讯位置服务中启用 WebService API。',
        ),
        'beian_info' => array('label' => '备案信息', 'type' => 'text', 'sanitize' => 'sanitize_text_field'),
    );

    foreach ($text_fields as $key => $field) {
        $wp_customize->add_setting(
            'icefox_' . $key,
            array(
                'default' => icefox_get_default_options()[$key],
                'sanitize_callback' => $field['sanitize'],
            )
        );

        $wp_customize->add_control(
            'icefox_' . $key,
            array(
                'section' => 'icefox_theme_options',
                'label' => $field['label'],
                'type' => $field['type'],
                'description' => isset($field['description']) ? $field['description'] : '',
            )
        );
    }

    $wp_customize->add_setting(
        'icefox_auto_collapse',
        array(
            'default' => icefox_get_default_options()['auto_collapse'],
            'sanitize_callback' => function ($value) {
                return $value === '0' ? '0' : '1';
            },
        )
    );
    $wp_customize->add_control(
        'icefox_auto_collapse',
        array(
            'section' => 'icefox_theme_options',
            'label' => '列表页自动收起正文',
            'type' => 'radio',
            'choices' => array(
                '1' => '是',
                '0' => '否',
            ),
        )
    );

    $textarea_fields = array(
        'custom_css' => '自定义 CSS',
        'custom_js' => '自定义 JavaScript',
        'analytics' => '统计代码',
    );

    foreach ($textarea_fields as $key => $label) {
        $wp_customize->add_setting(
            'icefox_' . $key,
            array(
                'default' => icefox_get_default_options()[$key],
                'sanitize_callback' => 'icefox_sanitize_raw_text',
            )
        );

        $wp_customize->add_control(
            'icefox_' . $key,
            array(
                'section' => 'icefox_theme_options',
                'label' => $label,
                'type' => 'textarea',
            )
        );
    }
}
add_action('customize_register', 'icefox_register_customizer');

function icefox_register_post_meta_box()
{
    add_meta_box(
        'icefox-post-meta',
        'Icefox 文章设置',
        'icefox_render_post_meta_box',
        array('post', 'page'),
        'normal',
        'default'
    );
}
add_action('add_meta_boxes', 'icefox_register_post_meta_box');

function icefox_render_post_meta_box($post)
{
    wp_nonce_field('icefox_post_meta', 'icefox_post_meta_nonce');

    $position = get_post_meta($post->ID, '_icefox_position', true);
    $position_url = get_post_meta($post->ID, '_icefox_position_url', true);
    $is_advertise = get_post_meta($post->ID, '_icefox_is_advertise', true);
    ?>
    <p>
        <label for="icefox_position"><strong>发布定位</strong></label>
        <input type="text" class="widefat" id="icefox_position" name="icefox_position" value="<?php echo esc_attr($position); ?>">
    </p>
    <p>
        <label for="icefox_position_url"><strong>定位跳转地址</strong></label>
        <input type="url" class="widefat" id="icefox_position_url" name="icefox_position_url" value="<?php echo esc_attr($position_url); ?>">
    </p>
    <p>
        <label>
            <input type="checkbox" name="icefox_is_advertise" value="1" <?php checked($is_advertise, '1'); ?>>
            标记为广告
        </label>
    </p>
    <?php
}

function icefox_save_post_meta($post_id)
{
    if (
        !isset($_POST['icefox_post_meta_nonce']) ||
        !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['icefox_post_meta_nonce'])), 'icefox_post_meta')
    ) {
        return;
    }

    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }

    if (!current_user_can('edit_post', $post_id)) {
        return;
    }

    $position = isset($_POST['icefox_position']) ? sanitize_text_field(wp_unslash($_POST['icefox_position'])) : '';
    $position_url = isset($_POST['icefox_position_url']) ? esc_url_raw(wp_unslash($_POST['icefox_position_url'])) : '';
    $is_advertise = isset($_POST['icefox_is_advertise']) ? '1' : '0';

    update_post_meta($post_id, '_icefox_position', $position);
    update_post_meta($post_id, '_icefox_position_url', $position_url);
    update_post_meta($post_id, '_icefox_is_advertise', $is_advertise);
}
add_action('save_post', 'icefox_save_post_meta');

function icefox_current_url()
{
    $scheme = is_ssl() ? 'https://' : 'http://';
    $host = isset($_SERVER['HTTP_HOST']) ? wp_unslash($_SERVER['HTTP_HOST']) : wp_parse_url(home_url(), PHP_URL_HOST);
    $request_uri = isset($_SERVER['REQUEST_URI']) ? wp_unslash($_SERVER['REQUEST_URI']) : '/';

    return esc_url_raw($scheme . $host . $request_uri);
}

function icefox_get_edit_url()
{
    return admin_url('post-new.php');
}

function icefox_escape_img_src($url)
{
    return esc_url($url, array('http', 'https'));
}

function icefox_get_wp_avatar_url($email, $size = 64)
{
    return get_avatar_url($email, array('size' => $size));
}

function icefox_get_post_author_avatar_url($post = null, $size = 64)
{
    $post = get_post($post);

    if (!$post) {
        return icefox_get_wp_avatar_url((string) get_option('admin_email'), $size);
    }

    $author_id = (int) $post->post_author;
    $email = get_the_author_meta('user_email', $author_id);

    return icefox_get_wp_avatar_url($email, $size);
}

function icefox_get_site_avatar_data($size = 96)
{
    $admins = get_users(
        array(
            'role' => 'administrator',
            'number' => 1,
            'orderby' => 'ID',
            'order' => 'ASC',
        )
    );

    if (!empty($admins) && $admins[0] instanceof WP_User) {
        $admin = $admins[0];

        return array(
            'url' => icefox_get_wp_avatar_url($admin->user_email, $size),
            'name' => $admin->display_name,
        );
    }

    $site_name = get_bloginfo('name');
    $admin_email = (string) get_option('admin_email');

    return array(
        'url' => icefox_get_wp_avatar_url($admin_email, $size),
        'name' => $site_name,
    );
}

function icefox_extract_image_srcs($html)
{
    $srcs = array();
    preg_match_all('/<img[^>]+src=["\']([^"\']+)["\']/i', $html, $matches);

    if (!empty($matches[1])) {
        $srcs = $matches[1];
    }

    return $srcs;
}

function icefox_extract_video_src($html)
{
    if (preg_match('/<video[^>]+src=["\']([^"\']+)["\']/i', $html, $matches)) {
        return $matches[1];
    }

    if (preg_match('/<video[^>]*>.*?<source[^>]+src=["\']([^"\']+)["\']/is', $html, $matches)) {
        return $matches[1];
    }

    return null;
}

function icefox_filter_content($html)
{
    return strip_tags($html, '<p><a>');
}

function icefox_truncate_html_with_tags($html, $length)
{
    $text_length = 0;
    $output = '';
    $tag_stack = array();
    $i = 0;
    $html_length = mb_strlen($html, 'UTF-8');

    while ($i < $html_length && $text_length < $length) {
        $char = mb_substr($html, $i, 1, 'UTF-8');

        if ($char === '<') {
            $tag_end = mb_strpos($html, '>', $i);
            if ($tag_end !== false) {
                $tag_content = mb_substr($html, $i, $tag_end - $i + 1, 'UTF-8');
                $output .= $tag_content;

                if (preg_match('/<(\w+)(?:\s|>)/i', $tag_content, $matches)) {
                    $tag_name = $matches[1];
                    if (!preg_match('/<\w+[^>]*\/>/i', $tag_content) && !preg_match('/<\/\w+>/i', $tag_content)) {
                        $tag_stack[] = $tag_name;
                    }
                }

                if (preg_match('/<\/(\w+)>/i', $tag_content, $matches)) {
                    $tag_name = $matches[1];
                    $reversed = array_reverse($tag_stack, true);
                    $key = array_search($tag_name, $reversed, true);
                    if ($key !== false) {
                        array_splice($tag_stack, count($tag_stack) - 1 - $key, 1);
                    }
                }

                $i = $tag_end + 1;
                continue;
            }
        }

        $output .= $char;
        $text_length++;
        $i++;
    }

    while (!empty($tag_stack)) {
        $tag = array_pop($tag_stack);
        $output .= '</' . $tag . '>';
    }

    return preg_replace('/(<br\s*\/?>|\s|&nbsp;|<p>\s*<\/p>)+$/i', '', $output);
}

function icefox_generate_content_with_summary($full_content, $summary_length = 100)
{
    $plain_text = strip_tags($full_content);
    $plain_text = preg_replace('/\s+/', ' ', $plain_text);
    $plain_text = trim($plain_text);

    if (mb_strlen($plain_text, 'UTF-8') > $summary_length) {
        $summary = icefox_truncate_html_with_tags($full_content, $summary_length) . '...';
        $is_truncated = true;
    } else {
        $summary = $full_content;
        $is_truncated = false;
    }

    return array(
        'summary' => $summary,
        'full_content' => $full_content,
        'is_truncated' => $is_truncated,
    );
}

function icefox_render_music_card($url, $title, $artist = '', $cover = '')
{
    $title = (string) $title;
    $artist = $artist !== '' ? $artist : '未知艺术家';
    $cover = $cover !== '' ? $cover : get_template_directory_uri() . '/assets/images/default-music-cover.svg';

    ob_start();
    ?>
    <div class="music-card" data-music-player>
        <div class="media">
            <div class="media-left">
                <figure class="image is-64x64">
                    <img src="<?php echo esc_url($cover); ?>" alt="<?php echo esc_attr($title); ?>">
                </figure>
            </div>
            <div class="media-content">
                <p class="title is-6"><?php echo esc_html($title); ?></p>
                <p class="subtitle is-7"><?php echo esc_html($artist); ?></p>
                <div class="music-controls">
                    <button class="button is-small play-btn" aria-label="播放">
                        <span class="icon play-icon">
                            <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
                                <path d="M3 2l10 6-10 6z"/>
                            </svg>
                        </span>
                        <span class="icon pause-icon is-hidden">
                            <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
                                <path d="M5 3h2v10H5zM9 3h2v10H9z"/>
                            </svg>
                        </span>
                    </button>
                    <div class="progress-wrapper">
                        <div class="progress-bar">
                            <div class="progress-fill"></div>
                        </div>
                    </div>
                    <span class="time is-size-7">00:00 / 00:00</span>
                </div>
            </div>
        </div>
        <audio preload="metadata">
            <source src="<?php echo esc_url($url); ?>" type="audio/mpeg">
            您的浏览器不支持音频播放。
        </audio>
    </div>
    <?php

    return ob_get_clean();
}

function icefox_parse_music_shortcode_string($content)
{
    $pattern = '/\[music\s+url=["\']([^"\']+)["\']\s+title=["\']([^"\']+)["\'](?:\s+artist=["\']([^"\']*)["\'])?(?:\s+cover=["\']([^"\']*)["\'])?\]/';

    return preg_replace_callback(
        $pattern,
        function ($matches) {
            $url = $matches[1];
            $title = $matches[2];
            $artist = isset($matches[3]) ? $matches[3] : '';
            $cover = isset($matches[4]) ? $matches[4] : '';

            return icefox_render_music_card($url, $title, $artist, $cover);
        },
        $content
    );
}

function icefox_music_shortcode($atts)
{
    $atts = shortcode_atts(
        array(
            'url' => '',
            'title' => '',
            'artist' => '',
            'cover' => '',
        ),
        $atts,
        'music'
    );

    if ($atts['url'] === '' || $atts['title'] === '') {
        return '';
    }

    return icefox_render_music_card($atts['url'], $atts['title'], $atts['artist'], $atts['cover']);
}
add_shortcode('music', 'icefox_music_shortcode');

function icefox_extract_music_shortcodes($content)
{
    $shortcodes = array();
    $pattern = '/\[music\s+url=["\']([^"\']+)["\']\s+title=["\']([^"\']+)["\'](?:\s+artist=["\']([^"\']*)["\'])?(?:\s+cover=["\']([^"\']*)["\'])?\]/';

    preg_match_all($pattern, $content, $matches, PREG_SET_ORDER);

    foreach ($matches as $match) {
        $shortcodes[] = $match[0];
    }

    return array(
        'shortcodes' => $shortcodes,
        'content' => preg_replace($pattern, '', $content),
    );
}

function icefox_generate_content_with_summary_and_music($full_content, $summary_length = 100)
{
    $extracted = icefox_extract_music_shortcodes($full_content);
    $music_shortcodes = $extracted['shortcodes'];
    $content_without_music = $extracted['content'];
    $result = icefox_generate_content_with_summary($content_without_music, $summary_length);

    $result['music_shortcodes'] = !empty($music_shortcodes) ? implode("\n\n", $music_shortcodes) : '';

    return $result;
}

function icefox_get_post_rendered_content($post = null)
{
    $post = get_post($post);

    if (!$post) {
        return '';
    }

    return apply_filters('the_content', $post->post_content);
}

function icefox_get_post_position($post_id)
{
    return get_post_meta($post_id, '_icefox_position', true);
}

function icefox_get_post_position_url($post_id)
{
    return get_post_meta($post_id, '_icefox_position_url', true);
}

function icefox_is_post_ad($post_id)
{
    return get_post_meta($post_id, '_icefox_is_advertise', true) === '1';
}

function icefox_is_comment_related_to_top_comment($comment_id, $top_comment_id, $comment_map)
{
    if (!isset($comment_map[$comment_id])) {
        return false;
    }

    $comment = $comment_map[$comment_id];

    if ((int) $comment['parent'] === (int) $top_comment_id) {
        return true;
    }

    if ((int) $comment['parent'] === 0) {
        return false;
    }

    return icefox_is_comment_related_to_top_comment($comment['parent'], $top_comment_id, $comment_map);
}

function icefox_get_comment_user_group($comment)
{
    if (!empty($comment->user_id)) {
        $user = get_userdata((int) $comment->user_id);
        if ($user && in_array('administrator', (array) $user->roles, true)) {
            return 'administrator';
        }
    }

    return '';
}

function icefox_prepare_comment_payload($comment)
{
    $comment = get_comment($comment);

    if (!$comment) {
        return array();
    }

    return array(
        'coid' => (int) $comment->comment_ID,
        'id' => (int) $comment->comment_ID,
        'parent' => (int) $comment->comment_parent,
        'author' => $comment->comment_author,
        'url' => $comment->comment_author_url,
        'text' => wp_strip_all_tags($comment->comment_content),
        'userGroup' => icefox_get_comment_user_group($comment),
    );
}

function icefox_get_post_latest_comments_with_replies($post_id, $limit = 5)
{
    $top_comments = get_comments(
        array(
            'post_id' => $post_id,
            'status' => 'approve',
            'type' => 'comment',
            'parent' => 0,
            'orderby' => 'comment_date_gmt',
            'order' => 'DESC',
            'number' => $limit,
        )
    );

    if (empty($top_comments)) {
        return array();
    }

    $all_comments = get_comments(
        array(
            'post_id' => $post_id,
            'status' => 'approve',
            'type' => 'comment',
            'orderby' => 'comment_date_gmt',
            'order' => 'ASC',
            'number' => 0,
        )
    );

    $comment_map = array();

    foreach ($all_comments as $comment) {
        $comment_map[$comment->comment_ID] = array(
            'coid' => (int) $comment->comment_ID,
            'parent' => (int) $comment->comment_parent,
            'author' => $comment->comment_author,
            'url' => $comment->comment_author_url,
            'text' => wp_strip_all_tags($comment->comment_content),
            'userGroup' => icefox_get_comment_user_group($comment),
            'created' => mysql2date('U', $comment->comment_date_gmt),
        );
    }

    $comment_tree = array();

    foreach ($top_comments as $top_comment) {
        $item = icefox_prepare_comment_payload($top_comment);
        $item['replies'] = array();
        $item['level'] = 0;
        $related_replies = array();

        foreach ($all_comments as $child_comment) {
            if ((int) $child_comment->comment_parent === 0) {
                continue;
            }

            if (icefox_is_comment_related_to_top_comment($child_comment->comment_ID, $top_comment->comment_ID, $comment_map)) {
                $payload = icefox_prepare_comment_payload($child_comment);
                $parent_comment = isset($comment_map[$child_comment->comment_parent]) ? $comment_map[$child_comment->comment_parent] : null;

                $payload['parentAuthor'] = $parent_comment ? $parent_comment['author'] : '';
                $payload['parentUrl'] = $parent_comment ? $parent_comment['url'] : '';
                $payload['parentUserGroup'] = $parent_comment ? $parent_comment['userGroup'] : '';
                $payload['created'] = mysql2date('U', $child_comment->comment_date_gmt);
                $related_replies[] = $payload;
            }
        }

        usort(
            $related_replies,
            function ($a, $b) {
                return ((int) $a['created']) <=> ((int) $b['created']);
            }
        );

        $item['replies'] = $related_replies;
        $comment_tree[] = $item;
    }

    return $comment_tree;
}

function icefox_format_comment_time($timestamp)
{
    $now = current_time('timestamp');
    $diff = $now - (int) $timestamp;

    if ($diff < 60) {
        return '刚刚';
    }

    if ($diff < 3600) {
        return floor($diff / 60) . '分钟前';
    }

    if ($diff < 86400) {
        return floor($diff / 3600) . '小时前';
    }

    if ($diff < 2592000) {
        return floor($diff / 86400) . '天前';
    }

    return wp_date('Y年m月d日', (int) $timestamp);
}

function icefox_render_comment_items($post_id, $limit = 5)
{
    $comments = icefox_get_post_latest_comments_with_replies($post_id, $limit);

    foreach ($comments as $comment) {
        ?>
        <div class="pcc-comment-item" data-comment-id="<?php echo esc_attr($comment['coid']); ?>">
            <a href="<?php echo esc_url($comment['url'] ? $comment['url'] : '#'); ?>"><?php echo esc_html($comment['author']); ?></a>
            <?php if (!empty($comment['userGroup']) && $comment['userGroup'] === 'administrator') : ?>
                <span class="author-badge">作者</span>
            <?php endif; ?>
            <span>:</span>
            <span class="cursor-help pcc-comment-content"
                  @click="showReplyForm($event, '<?php echo esc_attr($post_id); ?>', '<?php echo esc_attr($comment['coid']); ?>', <?php echo esc_attr(wp_json_encode($comment['author'], JSON_UNESCAPED_UNICODE)); ?>)"><?php echo esc_html($comment['text']); ?></span>
        </div>
        <?php

        foreach ($comment['replies'] as $reply) {
            ?>
            <div class="pcc-comment-item" data-comment-id="<?php echo esc_attr($reply['coid']); ?>">
                <a href="<?php echo esc_url($reply['url'] ? $reply['url'] : '#'); ?>"><?php echo esc_html($reply['author']); ?></a>
                <?php if (!empty($reply['userGroup']) && $reply['userGroup'] === 'administrator') : ?>
                    <span class="author-badge">作者</span>
                <?php endif; ?>
                <span>回复</span>
                <a href="<?php echo esc_url($reply['parentUrl'] ? $reply['parentUrl'] : '#'); ?>"><?php echo esc_html($reply['parentAuthor']); ?></a>
                <?php if (!empty($reply['parentUserGroup']) && $reply['parentUserGroup'] === 'administrator') : ?>
                    <span class="author-badge">作者</span>
                <?php endif; ?>
                <span>:</span>
                <span class="cursor-help pcc-comment-content"
                      @click="showReplyForm($event, '<?php echo esc_attr($post_id); ?>', '<?php echo esc_attr($reply['coid']); ?>', <?php echo esc_attr(wp_json_encode($reply['author'], JSON_UNESCAPED_UNICODE)); ?>)"><?php echo esc_html($reply['text']); ?></span>
            </div>
            <?php
        }
    }
}

function icefox_render_post_action_block($post_id, $detail = false, $comment_limit = 5)
{
    $datetime = $detail ? get_the_date('Y年m月d日', $post_id) : icefox_format_comment_time(get_post_time('U', true, $post_id));
    ?>
    <div class="post-time">
        <time datetime="<?php echo esc_attr(get_the_date('Y年m月d日', $post_id)); ?>"><?php echo esc_html($datetime); ?></time>
        <div class="post-time-comment" x-data="{ptcmShow: false}" :id="'ptcm-' + <?php echo (int) $post_id; ?>">
            <div class="ptc-more" @click="togglePostTimeComment($event, <?php echo (int) $post_id; ?>)">
                <svg t="1709204592505" class="icon" viewBox="0 0 1024 1024" version="1.1"
                     xmlns="http://www.w3.org/2000/svg" p-id="16237" width="16" height="16">
                    <path d="M229.2 512m-140 0a140 140 0 1 0 280 0 140 140 0 1 0-280 0Z" p-id="16238" fill="#8a8a8a"></path>
                    <path d="M794.8 512m-140 0a140 140 0 1 0 280 0 140 140 0 1 0-280 0Z" p-id="16239" fill="#8a8a8a"></path>
                </svg>
            </div>
            <div class="post-time-comment-modal" x-show="ptcmShow" x-transition.in.duration.300ms.origin.top.right>
                <div class="ptcm-good like-menu-btn" data-cid="<?php echo (int) $post_id; ?>" @click="toggleLike($event, <?php echo (int) $post_id; ?>)">
                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" height="16" width="16"
                         stroke-width="1.5" stroke="currentColor" class="size-6 like-menu-icon">
                        <path stroke-linecap="round" stroke-linejoin="round"
                              d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z"/>
                    </svg>
                    <span class="like-menu-text">点赞</span>
                </div>
                <div class="ptcm-comment" @click="showPostReplyForm($event, <?php echo (int) $post_id; ?>)">
                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" height="16" width="16"
                         stroke-width="1.5" stroke="currentColor" class="size-6">
                        <path stroke-linecap="round" stroke-linejoin="round"
                              d="M2.25 12.76c0 1.6 1.123 2.994 2.707 3.227 1.087.16 2.185.283 3.293.369V21l4.076-4.076a1.526 1.526 0 0 1 1.037-.443 48.282 48.282 0 0 0 5.68-.494c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z"/>
                    </svg>
                    评论
                </div>
            </div>
        </div>
    </div>
    <div class="post-comment-container" data-cid="<?php echo (int) $post_id; ?>">
        <div class="pcc-like-list" data-cid="<?php echo (int) $post_id; ?>">
            <div class="pcc-like-summary">
                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" height="16" width="16"
                     stroke-width="1.5" stroke="currentColor" class="like-icon">
                    <path stroke-linecap="round" stroke-linejoin="round"
                          d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z"/>
                </svg>
                <span class="like-users-text"></span>
            </div>
        </div>
        <div class="pcc-comment-list">
            <?php icefox_render_comment_items($post_id, $comment_limit); ?>
        </div>
    </div>
    <?php
}

function icefox_render_post_article($post = null, $args = array())
{
    $post = get_post($post);

    if (!$post) {
        return;
    }

    $args = wp_parse_args(
        $args,
        array(
            'detail' => false,
            'page' => false,
            'comment_limit' => 5,
        )
    );

    $author_id = (int) $post->post_author;
    $author_name = get_the_author_meta('display_name', $author_id);
    $author_url = get_author_posts_url($author_id);
    $avatar_url = icefox_get_post_author_avatar_url($post, 64);
    $filtered_content = icefox_filter_content($post->post_content);
    $content_with_summary = icefox_generate_content_with_summary_and_music($filtered_content, 100);
    $music_html = $content_with_summary['music_shortcodes'] !== '' ? icefox_parse_music_shortcode_string($content_with_summary['music_shortcodes']) : '';
    $auto_collapse = icefox_get_option('auto_collapse') !== '0';
    $video_src = icefox_extract_video_src($post->post_content);
    $images = $video_src ? array() : icefox_extract_image_srcs($post->post_content);
    ?>
    <article class="post-item<?php echo $args['detail'] ? ' post-detail-item' : ''; ?>">
        <div class="post-item-left">
            <a href="<?php echo esc_url($author_url); ?>">
                <img alt="<?php echo esc_attr($author_name); ?>" src="<?php echo icefox_escape_img_src($avatar_url); ?>">
            </a>
        </div>
        <div class="post-item-right">
            <h2 class="post-title">
                <a href="<?php echo esc_url($author_url); ?>"><?php echo esc_html($author_name); ?></a>
                <?php if ($args['page']) : ?>
                    <span class="page-badge">页面</span>
                <?php else : ?>
                    <?php if (is_sticky($post->ID)) : ?>
                        <span class="top-badge">置顶</span>
                    <?php endif; ?>
                    <?php if (icefox_is_post_ad($post->ID)) : ?>
                        <span class="ad-badge">广告</span>
                    <?php endif; ?>
                <?php endif; ?>
            </h2>

            <div class="post-content">
                <?php if ($args['detail']) : ?>
                    <?php echo icefox_get_post_rendered_content($post); ?>
                <?php else : ?>
                    <?php
                    if ($auto_collapse) {
                        if ($content_with_summary['is_truncated']) {
                            echo '<div class="summary-' . esc_attr($post->ID) . '">' . $content_with_summary['summary'] . '<span class="show_all_btn cursor-pointer" data-cid="' . esc_attr($post->ID) . '">全文</span></div>';
                            echo '<div class="hidden full_content-' . esc_attr($post->ID) . '">' . $content_with_summary['full_content'] . '<div><span class="hide_all_btn cursor-pointer" data-cid="' . esc_attr($post->ID) . '">收起</span></div></div>';
                        } else {
                            echo '<div>' . $content_with_summary['full_content'] . '</div>';
                        }

                        echo $music_html;
                    } else {
                        echo '<div class="full-content-display">' . $content_with_summary['full_content'] . '</div>';
                        echo $music_html;
                    }
                    ?>
                <?php endif; ?>
            </div>

            <?php if (!$args['detail']) : ?>
                <?php
                if ($video_src) {
                    get_template_part('components/post/post-video', null, array(
                        'video_url' => $video_src,
                    ));
                } else {
                    get_template_part('components/post/post-images', null, array(
                        'images' => $images,
                        'post_id' => $post->ID,
                    ));
                }
                ?>
            <?php endif; ?>

            <?php
            get_template_part('components/post/post-position', null, array(
                'post_id' => $post->ID,
            ));

            icefox_render_post_action_block($post->ID, $args['detail'], (int) $args['comment_limit']);
            ?>
        </div>
    </article>
    <?php
}

function icefox_render_pagination_state($query = null)
{
    $query = $query instanceof WP_Query ? $query : $GLOBALS['wp_query'];
    $current_page = max(1, (int) get_query_var('paged'), (int) get_query_var('page'));
    $total_pages = max(1, (int) $query->max_num_pages);
    $next_url = $total_pages > $current_page ? get_next_posts_page_link($total_pages) : '';
    ?>
    <div class="pagination" style="display: none;">
        <span class="current-page" data-page="<?php echo esc_attr($current_page); ?>"></span>
        <span class="total-pages" data-total="<?php echo esc_attr($total_pages); ?>"></span>
        <span class="next-page-url" data-url="<?php echo esc_url($next_url); ?>"></span>
    </div>
    <?php
}

function icefox_get_archive_heading()
{
    if (is_category()) {
        return sprintf('分类 %s 下的文章', single_cat_title('', false));
    }

    if (is_search()) {
        return sprintf('包含关键字 %s 的文章', get_search_query());
    }

    if (is_tag()) {
        return sprintf('标签 %s 下的文章', single_tag_title('', false));
    }

    if (is_author()) {
        $author = get_queried_object();
        return sprintf('%s 发布的文章', $author ? $author->display_name : '');
    }

    $title = get_the_archive_title();
    return wp_strip_all_tags($title);
}

function icefox_get_friend_links()
{
    $bookmarks = get_bookmarks(
        array(
            'orderby' => 'name',
            'order' => 'ASC',
            'limit' => -1,
            'hide_invisible' => 1,
        )
    );

    if (empty($bookmarks)) {
        return array();
    }

    $links = array();
    $default_avatar = get_template_directory_uri() . '/assets/images/default-avatar.svg';

    foreach ($bookmarks as $bookmark) {
        $avatar = '';

        if (!empty($bookmark->link_image)) {
            if (is_numeric($bookmark->link_image)) {
                $attachment_url = wp_get_attachment_url((int) $bookmark->link_image);
                $avatar = $attachment_url ? $attachment_url : '';
            } else {
                $avatar = esc_url_raw($bookmark->link_image);
            }
        }

        $description = '';

        if (!empty($bookmark->link_description)) {
            $description = sanitize_text_field($bookmark->link_description);
        } elseif (!empty($bookmark->link_notes)) {
            $description = sanitize_text_field($bookmark->link_notes);
        }

        $links[] = array(
            'id' => (int) $bookmark->link_id,
            'name' => sanitize_text_field($bookmark->link_name),
            'url' => esc_url_raw($bookmark->link_url),
            'description' => $description,
            'avatar' => $avatar !== '' ? esc_url_raw($avatar) : $default_avatar,
        );
    }

    return $links;
}

function icefox_get_likes_table_name()
{
    global $wpdb;

    return $wpdb->prefix . 'icefox_likes';
}

function icefox_install_theme_data()
{
    global $wpdb;

    require_once ABSPATH . 'wp-admin/includes/upgrade.php';

    $table = icefox_get_likes_table_name();
    $charset_collate = $wpdb->get_charset_collate();
    $sql = "CREATE TABLE {$table} (
        id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        post_id bigint(20) unsigned NOT NULL,
        actor_key varchar(191) NOT NULL,
        author_name varchar(191) NOT NULL DEFAULT '',
        author_email varchar(191) NOT NULL DEFAULT '',
        created_at datetime NOT NULL,
        PRIMARY KEY  (id),
        UNIQUE KEY post_actor (post_id, actor_key),
        KEY post_id (post_id)
    ) {$charset_collate};";

    dbDelta($sql);
    update_option('icefox_db_version', ICEFOX_DB_VERSION);
}
add_action('after_switch_theme', 'icefox_install_theme_data');

function icefox_maybe_install_theme_data()
{
    if (get_option('icefox_db_version') !== ICEFOX_DB_VERSION) {
        icefox_install_theme_data();
    }
}
add_action('init', 'icefox_maybe_install_theme_data');

function icefox_resolve_like_actor(WP_REST_Request $request)
{
    if (is_user_logged_in()) {
        $user = wp_get_current_user();

        return array(
            'key' => 'user:' . $user->ID,
            'author' => $user->display_name,
            'email' => $user->user_email,
        );
    }

    $comment_author = (string) $request->get_param('comment_author');
    $comment_email = (string) $request->get_param('comment_email');
    $anonymous_id = (string) $request->get_param('anonymous_id');

    if ($comment_email !== '') {
        return array(
            'key' => 'comment:' . sha1(strtolower(trim($comment_email)) . '|' . trim($comment_author)),
            'author' => $comment_author !== '' ? $comment_author : '匿名用户',
            'email' => sanitize_email($comment_email),
        );
    }

    if ($anonymous_id !== '') {
        return array(
            'key' => 'anon:' . sanitize_key($anonymous_id),
            'author' => '匿名用户',
            'email' => '',
        );
    }

    return array(
        'key' => '',
        'author' => '匿名用户',
        'email' => '',
    );
}

function icefox_get_like_rows($post_id)
{
    global $wpdb;
    $table = icefox_get_likes_table_name();

    return $wpdb->get_results(
        $wpdb->prepare(
            "SELECT * FROM {$table} WHERE post_id = %d ORDER BY id ASC",
            $post_id
        ),
        ARRAY_A
    );
}

function icefox_prepare_like_response($post_id, $actor_key = '')
{
    $rows = icefox_get_like_rows($post_id);
    $like_users = array();

    foreach ($rows as $row) {
        $like_users[] = array(
            'author' => $row['author_name'] !== '' ? $row['author_name'] : '匿名用户',
        );
    }

    $liked = false;

    if ($actor_key !== '') {
        foreach ($rows as $row) {
            if ($row['actor_key'] === $actor_key) {
                $liked = true;
                break;
            }
        }
    }

    return array(
        'success' => true,
        'likes' => count($rows),
        'isLiked' => $liked,
        'likeUsers' => $like_users,
    );
}

function icefox_handle_get_likes(WP_REST_Request $request)
{
    $post_id = (int) $request->get_param('cid');
    $actor = icefox_resolve_like_actor($request);

    return icefox_prepare_like_response($post_id, $actor['key']);
}

function icefox_handle_toggle_like(WP_REST_Request $request)
{
    global $wpdb;

    $post_id = (int) $request->get_param('cid');
    $actor = icefox_resolve_like_actor($request);

    if ($post_id <= 0 || $actor['key'] === '') {
        return array(
            'success' => false,
            'message' => '点赞参数无效',
        );
    }

    $table = icefox_get_likes_table_name();
    $existing = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT id FROM {$table} WHERE post_id = %d AND actor_key = %s",
            $post_id,
            $actor['key']
        )
    );

    if ($existing) {
        $wpdb->delete(
            $table,
            array(
                'post_id' => $post_id,
                'actor_key' => $actor['key'],
            ),
            array('%d', '%s')
        );
    } else {
        $wpdb->insert(
            $table,
            array(
                'post_id' => $post_id,
                'actor_key' => $actor['key'],
                'author_name' => $actor['author'],
                'author_email' => $actor['email'],
                'created_at' => current_time('mysql'),
            ),
            array('%d', '%s', '%s', '%s', '%s')
        );
    }

    return icefox_prepare_like_response($post_id, $actor['key']);
}

function icefox_user_can_frontend_post()
{
    return is_user_logged_in() && current_user_can('edit_posts');
}

function icefox_collect_frontend_media_files($file_params)
{
    $media_files = array();

    if (!is_array($file_params)) {
        return $media_files;
    }

    foreach ($file_params as $key => $file) {
        if (strpos((string) $key, 'media_') !== 0) {
            continue;
        }

        if (!is_array($file)) {
            continue;
        }

        $media_files[$key] = $file;
    }

    uksort(
        $media_files,
        function ($left, $right) {
            $left_index = (int) preg_replace('/\D+/', '', (string) $left);
            $right_index = (int) preg_replace('/\D+/', '', (string) $right);

            return $left_index <=> $right_index;
        }
    );

    return $media_files;
}

function icefox_collect_frontend_attachment_ids(WP_REST_Request $request)
{
    $raw_ids = $request->get_param('attachment_ids');

    if (is_array($raw_ids)) {
        return array_values(array_unique(array_filter(array_map('absint', $raw_ids))));
    }

    if (!is_string($raw_ids) || trim($raw_ids) === '') {
        return array();
    }

    $decoded = json_decode(wp_unslash($raw_ids), true);

    if (is_array($decoded)) {
        return array_values(array_unique(array_filter(array_map('absint', $decoded))));
    }

    $parts = array_map('trim', explode(',', $raw_ids));

    return array_values(array_unique(array_filter(array_map('absint', $parts))));
}

function icefox_cleanup_uploaded_attachments($attachment_ids)
{
    foreach ((array) $attachment_ids as $attachment_id) {
        $attachment_id = (int) $attachment_id;

        if ($attachment_id > 0) {
            wp_delete_attachment($attachment_id, true);
        }
    }
}

function icefox_resolve_frontend_post_status($visibility)
{
    if ($visibility === 'private') {
        if (!current_user_can('publish_posts') || !current_user_can('edit_private_posts')) {
            return new WP_Error('icefox_private_forbidden', '当前账号无权发布私密内容');
        }

        return 'private';
    }

    return current_user_can('publish_posts') ? 'publish' : 'pending';
}

function icefox_upload_frontend_media($media_files, $post_id)
{
    require_once ABSPATH . 'wp-admin/includes/file.php';
    require_once ABSPATH . 'wp-admin/includes/media.php';
    require_once ABSPATH . 'wp-admin/includes/image.php';

    $images = array();
    $video = null;
    $attachment_ids = array();

    foreach ($media_files as $file) {
        if (empty($file['name']) || (isset($file['error']) && (int) $file['error'] === UPLOAD_ERR_NO_FILE)) {
            continue;
        }

        if (!isset($file['tmp_name']) || !file_exists($file['tmp_name'])) {
            icefox_cleanup_uploaded_attachments($attachment_ids);

            return new WP_Error('icefox_media_missing', '上传文件不存在');
        }

        if (isset($file['error']) && (int) $file['error'] !== UPLOAD_ERR_OK) {
            icefox_cleanup_uploaded_attachments($attachment_ids);

            return new WP_Error('icefox_media_error', '媒体上传失败，请重试');
        }

        $file_name = isset($file['name']) ? (string) $file['name'] : '';
        $file_type = isset($file['type']) ? (string) $file['type'] : '';
        $detected_type = wp_check_filetype($file_name);
        $mime_type = $file_type !== '' ? $file_type : (isset($detected_type['type']) ? (string) $detected_type['type'] : '');
        $is_image = strpos($mime_type, 'image/') === 0;
        $is_video = strpos($mime_type, 'video/') === 0;

        if (!$is_image && !$is_video) {
            icefox_cleanup_uploaded_attachments($attachment_ids);

            return new WP_Error('icefox_media_invalid', '仅支持上传图片或视频');
        }

        if ($is_video && ($video !== null || !empty($images))) {
            icefox_cleanup_uploaded_attachments($attachment_ids);

            return new WP_Error('icefox_video_limit', '只能上传 1 个视频，且不能与图片混传');
        }

        if ($is_image && $video !== null) {
            icefox_cleanup_uploaded_attachments($attachment_ids);

            return new WP_Error('icefox_image_mix', '上传视频后不能继续上传图片');
        }

        if ($is_image && count($images) >= 9) {
            icefox_cleanup_uploaded_attachments($attachment_ids);

            return new WP_Error('icefox_image_limit', '最多只能上传 9 张图片');
        }

        $attachment_id = media_handle_sideload($file, $post_id);

        if (is_wp_error($attachment_id)) {
            icefox_cleanup_uploaded_attachments($attachment_ids);

            return $attachment_id;
        }

        $attachment_url = wp_get_attachment_url($attachment_id);

        if (!$attachment_url) {
            $attachment_ids[] = $attachment_id;
            icefox_cleanup_uploaded_attachments($attachment_ids);

            return new WP_Error('icefox_media_url', '媒体保存失败，请重试');
        }

        $attachment_ids[] = $attachment_id;

        if ($is_video) {
            $video = array(
                'id' => $attachment_id,
                'url' => $attachment_url,
            );
            continue;
        }

        $images[] = array(
            'id' => $attachment_id,
            'url' => $attachment_url,
        );
    }

    return array(
        'images' => $images,
        'video' => $video,
        'attachment_ids' => $attachment_ids,
        'cleanup_attachment_ids' => $attachment_ids,
    );
}

function icefox_prepare_frontend_library_media($attachment_ids)
{
    $images = array();
    $video = null;
    $validated_attachment_ids = array();

    foreach ((array) $attachment_ids as $attachment_id) {
        $attachment_id = (int) $attachment_id;

        if ($attachment_id <= 0) {
            continue;
        }

        $attachment = get_post($attachment_id);

        if (!$attachment || $attachment->post_type !== 'attachment') {
            return new WP_Error('icefox_attachment_invalid', '所选媒体不存在或已被删除');
        }

        if (!current_user_can('edit_post', $attachment_id)) {
            return new WP_Error('icefox_attachment_forbidden', '没有权限使用所选媒体');
        }

        $mime_type = (string) get_post_mime_type($attachment_id);
        $is_image = strpos($mime_type, 'image/') === 0;
        $is_video = strpos($mime_type, 'video/') === 0;

        if (!$is_image && !$is_video) {
            return new WP_Error('icefox_attachment_type', '媒体库中仅支持图片和视频');
        }

        if ($is_video && ($video !== null || !empty($images))) {
            return new WP_Error('icefox_attachment_video_limit', '只能选择 1 个视频，且不能与图片混选');
        }

        if ($is_image && $video !== null) {
            return new WP_Error('icefox_attachment_mix', '选择视频后不能再添加图片');
        }

        if ($is_image && count($images) >= 9) {
            return new WP_Error('icefox_attachment_image_limit', '最多只能选择 9 张图片');
        }

        $attachment_url = wp_get_attachment_url($attachment_id);

        if (!$attachment_url) {
            return new WP_Error('icefox_attachment_url', '所选媒体地址无效');
        }

        $validated_attachment_ids[] = $attachment_id;

        if ($is_video) {
            $video = array(
                'id' => $attachment_id,
                'url' => $attachment_url,
            );
            continue;
        }

        $images[] = array(
            'id' => $attachment_id,
            'url' => $attachment_url,
        );
    }

    return array(
        'images' => $images,
        'video' => $video,
        'attachment_ids' => $validated_attachment_ids,
        'cleanup_attachment_ids' => array(),
    );
}

function icefox_attach_media_to_post($attachment_ids, $post_id)
{
    foreach ((array) $attachment_ids as $attachment_id) {
        $attachment_id = (int) $attachment_id;

        if ($attachment_id <= 0) {
            continue;
        }

        wp_update_post(
            array(
                'ID' => $attachment_id,
                'post_parent' => (int) $post_id,
            )
        );
    }
}

function icefox_build_frontend_post_content($text, $media)
{
    $parts = array();
    $text = trim((string) $text);

    if ($text !== '') {
        $parts[] = wpautop(esc_html($text));
    }

    if (!empty($media['video']['url'])) {
        $parts[] = '<p><video controls controlsList="nodownload" preload="metadata" src="' . esc_url($media['video']['url']) . '"></video></p>';
    }

    if (!empty($media['images']) && is_array($media['images'])) {
        foreach ($media['images'] as $image) {
            if (empty($image['url'])) {
                continue;
            }

            $parts[] = '<p><img src="' . esc_url($image['url']) . '" alt=""></p>';
        }
    }

    return implode("\n\n", $parts);
}

function icefox_generate_frontend_post_title($text)
{
    $plain_text = trim(preg_replace('/\s+/u', ' ', wp_strip_all_tags((string) $text)));

    if ($plain_text === '') {
        return '动态 ' . wp_date('Y-m-d H:i');
    }

    $title = mb_substr($plain_text, 0, 30, 'UTF-8');

    if (mb_strlen($plain_text, 'UTF-8') > 30) {
        $title .= '...';
    }

    return $title;
}

function icefox_get_frontend_post_success_message($status)
{
    switch ($status) {
        case 'private':
            return '已保存为私密内容';

        case 'pending':
            return '内容已提交，等待审核';

        default:
            return '发布成功';
    }
}

function icefox_handle_create_post(WP_REST_Request $request)
{
    if (!icefox_user_can_frontend_post()) {
        return array(
            'success' => false,
            'message' => '请先登录具有发布权限的账号',
        );
    }

    $content = sanitize_textarea_field((string) $request->get_param('content'));
    $position = sanitize_text_field((string) $request->get_param('position'));
    $position_url = esc_url_raw((string) $request->get_param('positionUrl'));
    $visibility = sanitize_key((string) $request->get_param('visibility'));
    $is_advertise = (string) $request->get_param('isAdvertise') === '1' ? '1' : '0';
    $attachment_ids = icefox_collect_frontend_attachment_ids($request);
    $media_files = icefox_collect_frontend_media_files($request->get_file_params());

    if ($content === '' && empty($media_files) && empty($attachment_ids)) {
        return array(
            'success' => false,
            'message' => '请输入内容或选择图片/视频',
        );
    }

    $status = icefox_resolve_frontend_post_status($visibility === 'private' ? 'private' : 'public');

    if (is_wp_error($status)) {
        return array(
            'success' => false,
            'message' => $status->get_error_message(),
        );
    }

    $title = icefox_generate_frontend_post_title($content);
    $post_id = wp_insert_post(
        array(
            'post_type' => 'post',
            'post_status' => 'draft',
            'post_title' => $title,
            'post_content' => '',
            'post_author' => get_current_user_id(),
            'comment_status' => 'open',
        ),
        true
    );

    if (is_wp_error($post_id)) {
        return array(
            'success' => false,
            'message' => $post_id->get_error_message(),
        );
    }

    if (!empty($attachment_ids)) {
        $media = icefox_prepare_frontend_library_media($attachment_ids);
    } else {
        $media = icefox_upload_frontend_media($media_files, (int) $post_id);
    }

    if (is_wp_error($media)) {
        wp_delete_post((int) $post_id, true);

        return array(
            'success' => false,
            'message' => $media->get_error_message(),
        );
    }

    $post_content = icefox_build_frontend_post_content($content, $media);
    $updated_post = wp_update_post(
        array(
            'ID' => (int) $post_id,
            'post_status' => $status,
            'post_title' => $title,
            'post_content' => $post_content,
        ),
        true
    );

    if (is_wp_error($updated_post)) {
        icefox_cleanup_uploaded_attachments($media['cleanup_attachment_ids']);
        wp_delete_post((int) $post_id, true);

        return array(
            'success' => false,
            'message' => $updated_post->get_error_message(),
        );
    }

    update_post_meta((int) $post_id, '_icefox_position', $position);
    update_post_meta((int) $post_id, '_icefox_position_url', $position_url);
    update_post_meta((int) $post_id, '_icefox_is_advertise', $is_advertise);
    icefox_attach_media_to_post($media['attachment_ids'], (int) $post_id);

    if (!empty($media['images'][0]['id'])) {
        set_post_thumbnail((int) $post_id, (int) $media['images'][0]['id']);
    }

    $redirect = home_url('/');

    if ($status === 'private') {
        $private_url = get_permalink((int) $post_id);

        if ($private_url) {
            $redirect = $private_url;
        }
    }

    return array(
        'success' => true,
        'message' => icefox_get_frontend_post_success_message($status),
        'postId' => (int) $post_id,
        'status' => $status,
        'redirect' => esc_url_raw($redirect),
    );
}

function icefox_handle_add_comment(WP_REST_Request $request)
{
    $payload = $request->get_json_params();

    if (!is_array($payload)) {
        return array(
            'success' => false,
            'message' => '评论数据格式错误',
        );
    }

    $post_id = isset($payload['cid']) ? (int) $payload['cid'] : 0;
    $parent = isset($payload['coid']) ? (int) $payload['coid'] : 0;
    $author = isset($payload['author']) ? sanitize_text_field($payload['author']) : '';
    $email = isset($payload['mail']) ? sanitize_email($payload['mail']) : '';
    $url = isset($payload['url']) ? esc_url_raw($payload['url']) : '';
    $text = isset($payload['text']) ? wp_kses_post($payload['text']) : '';

    if ($post_id <= 0 || $author === '' || $email === '' || trim(wp_strip_all_tags($text)) === '') {
        return array(
            'success' => false,
            'message' => '请填写必要信息',
        );
    }

    if (!comments_open($post_id)) {
        return array(
            'success' => false,
            'message' => '评论已关闭',
        );
    }

    if (get_option('comment_registration') && !is_user_logged_in()) {
        return array(
            'success' => false,
            'message' => '当前站点需要登录后才可评论',
        );
    }

    $commentdata = array(
        'comment_post_ID' => $post_id,
        'comment_parent' => $parent,
        'comment_author' => $author,
        'comment_author_email' => $email,
        'comment_author_url' => $url,
        'comment_content' => $text,
        'user_id' => get_current_user_id(),
        'comment_type' => 'comment',
    );

    $comment_id = wp_new_comment(wp_slash($commentdata), true);

    if (is_wp_error($comment_id)) {
        return array(
            'success' => false,
            'message' => $comment_id->get_error_message(),
        );
    }

    $comment = get_comment($comment_id);

    if (!$comment) {
        return array(
            'success' => false,
            'message' => '评论发表失败',
        );
    }

    if ((string) $comment->comment_approved !== '1') {
        return array(
            'success' => false,
            'message' => '评论已提交，待审核后显示',
        );
    }

    return array(
        'success' => true,
        'comment' => icefox_prepare_comment_payload($comment),
    );
}

function icefox_handle_friend_links()
{
    return array(
        'success' => true,
        'data' => icefox_get_friend_links(),
    );
}

function icefox_register_rest_routes()
{
    register_rest_route(
        'icefox/v1',
        '/action',
        array(
            'methods' => WP_REST_Server::ALLMETHODS,
            'callback' => 'icefox_rest_action_handler',
            'permission_callback' => '__return_true',
        )
    );
}
add_action('rest_api_init', 'icefox_register_rest_routes');

function icefox_rest_action_handler(WP_REST_Request $request)
{
    $action = sanitize_key((string) $request->get_param('do'));

    switch ($action) {
        case 'getlikes':
            return rest_ensure_response(icefox_handle_get_likes($request));

        case 'like':
            return rest_ensure_response(icefox_handle_toggle_like($request));

        case 'addcomment':
            return rest_ensure_response(icefox_handle_add_comment($request));

        case 'createpost':
            return rest_ensure_response(icefox_handle_create_post($request));

        case 'getfriendlinks':
            return rest_ensure_response(icefox_handle_friend_links());

        default:
            return rest_ensure_response(
                array(
                    'success' => false,
                    'message' => '未知操作',
                )
            );
    }
}

function icefox_login_failed_redirect($username)
{
    $referrer = wp_get_referer();

    if (!$referrer || strpos($referrer, 'wp-login.php') !== false || strpos($referrer, 'wp-admin') !== false) {
        return;
    }

    $redirect = add_query_arg('login_error', 'invalid', remove_query_arg(array('login_error', 'loggedout'), $referrer));
    wp_safe_redirect($redirect);
    exit;
}
add_action('wp_login_failed', 'icefox_login_failed_redirect');

function icefox_empty_login_redirect($user, $username, $password)
{
    if (!empty($username) && !empty($password)) {
        return $user;
    }

    $referrer = wp_get_referer();

    if (!$referrer || strpos($referrer, 'wp-login.php') !== false || strpos($referrer, 'wp-admin') !== false) {
        return $user;
    }

    wp_safe_redirect(add_query_arg('login_error', 'empty', remove_query_arg(array('login_error', 'loggedout'), $referrer)));
    exit;
}
add_filter('authenticate', 'icefox_empty_login_redirect', 30, 3);
