<?php
/**
 * HuSNS - 一款免费开源的社交平台
 * 
 * @author  HYR
 * @QQ      281900864
 * @website https://huyourui.com
 * @license MIT
 * @声明    严禁用于违法违规用途
 */
class PostModel extends Model
{
    protected $table = 'posts';

    public function getTimeline($page = 1, $pageSize = 10, $userId = null, $tab = 'all', $excludePinned = true)
    {
        $offset = ($page - 1) * $pageSize;
        $pinnedCondition = $excludePinned ? 'AND (p.is_pinned = 0 OR p.is_pinned IS NULL)' : '';
        
        // 确保tab参数有效
        if (empty($tab)) {
            $tab = 'all';
        }
        
        if ($tab === 'following' && $userId) {
            $sql = "SELECT p.*, u.username, u.avatar, u.last_activity,
                           c.id as circle_id, c.name as circle_name
                    FROM __PREFIX__posts p 
                    INNER JOIN __PREFIX__users u ON p.user_id = u.id 
                    INNER JOIN __PREFIX__follows f ON p.user_id = f.follow_id AND f.user_id = ?
                    LEFT JOIN __PREFIX__circle_posts cp ON p.id = cp.post_id
                    LEFT JOIN __PREFIX__circles c ON cp.circle_id = c.id
                    WHERE p.status = 1
                    AND (u.ban_type = 0 OR u.ban_type = 1 OR u.ban_type IS NULL OR (u.ban_type = 1 AND u.ban_until > ?))
                    {$pinnedCondition}
                    ORDER BY p.created_at DESC 
                    LIMIT {$offset}, {$pageSize}";
            $posts = $this->db->fetchAll($sql, [$userId, time()]);
        } else {
            $sql = "SELECT p.*, u.username, u.avatar, u.last_activity,
                           c.id as circle_id, c.name as circle_name
                    FROM __PREFIX__posts p 
                    INNER JOIN __PREFIX__users u ON p.user_id = u.id 
                    LEFT JOIN __PREFIX__circle_posts cp ON p.id = cp.post_id
                    LEFT JOIN __PREFIX__circles c ON cp.circle_id = c.id
                    WHERE p.status = 1
                    AND (u.ban_type = 0 OR u.ban_type = 1 OR u.ban_type IS NULL OR (u.ban_type = 1 AND u.ban_until > ?))
                    {$pinnedCondition}
                    ORDER BY p.created_at DESC 
                    LIMIT {$offset}, {$pageSize}";
            $posts = $this->db->fetchAll($sql, [time()]);
        }

        return $this->formatPosts($posts);
    }

    public function getTimelineCount($userId = null, $tab = 'all', $excludePinned = true)
    {
        $pinnedCondition = $excludePinned ? 'AND (p.is_pinned = 0 OR p.is_pinned IS NULL)' : '';
        
        if ($tab === 'following' && $userId) {
            $sql = "SELECT COUNT(*) FROM __PREFIX__posts p 
                    INNER JOIN __PREFIX__follows f ON p.user_id = f.follow_id AND f.user_id = ?
                    INNER JOIN __PREFIX__users u ON p.user_id = u.id
                    WHERE p.status = 1
                    AND (u.ban_type = 0 OR u.ban_type = 1 OR u.ban_type IS NULL OR (u.ban_type = 1 AND u.ban_until > ?))
                    {$pinnedCondition}";
            return (int)$this->db->fetchColumn($sql, [$userId, time()]);
        }
        
        $sql = "SELECT COUNT(*) FROM __PREFIX__posts p 
                INNER JOIN __PREFIX__users u ON p.user_id = u.id
                WHERE p.status = 1
                AND (u.ban_type = 0 OR u.ban_type = 1 OR u.ban_type IS NULL OR (u.ban_type = 1 AND u.ban_until > ?))
                {$pinnedCondition}";
        return (int)$this->db->fetchColumn($sql, [time()]);
    }

    public function getPinnedPosts($currentUserId = 0)
    {
        try {
            $sql = "SELECT p.*, u.username, u.avatar, u.last_activity,
                           c.id as circle_id, c.name as circle_name
                    FROM __PREFIX__posts p 
                    INNER JOIN __PREFIX__users u ON p.user_id = u.id 
                    LEFT JOIN __PREFIX__circle_posts cp ON p.id = cp.post_id
                    LEFT JOIN __PREFIX__circles c ON cp.circle_id = c.id
                    WHERE p.status = 1 AND p.is_pinned = 1 
                    ORDER BY p.created_at DESC";
            $posts = $this->db->fetchAll($sql);
            return $this->formatPosts($posts);
        } catch (Exception $e) {
            return [];
        }
    }

    public function getPinnedPostForDisplay($currentUserId = 0)
    {
        $pinnedPosts = $this->getPinnedPosts($currentUserId);
        
        if (empty($pinnedPosts)) {
            return null;
        }
        
        if (count($pinnedPosts) == 1) {
            return $pinnedPosts[0];
        }
        
        $index = array_rand($pinnedPosts);
        return $pinnedPosts[$index];
    }

    public function getPinnedPostIds()
    {
        try {
            $sql = "SELECT id FROM __PREFIX__posts WHERE status = 1 AND is_pinned = 1";
            $results = $this->db->fetchAll($sql);
            return array_column($results, 'id');
        } catch (Exception $e) {
            return [];
        }
    }

    public function getFeaturedPosts($page = 1, $pageSize = 10)
    {
        $offset = ($page - 1) * $pageSize;
        
        $sql = "SELECT p.*, u.username, u.avatar, u.last_activity
                FROM __PREFIX__posts p 
                INNER JOIN __PREFIX__users u ON p.user_id = u.id 
                WHERE p.status = 1 AND p.is_featured = 1
                AND (u.ban_type = 0 OR u.ban_type = 1 OR u.ban_type IS NULL OR (u.ban_type = 1 AND u.ban_until > ?))
                ORDER BY p.created_at DESC 
                LIMIT {$offset}, {$pageSize}";
        $posts = $this->db->fetchAll($sql, [time()]);
        
        return $this->formatPosts($posts);
    }

    public function countFeaturedPosts()
    {
        $sql = "SELECT COUNT(*) FROM __PREFIX__posts p 
                INNER JOIN __PREFIX__users u ON p.user_id = u.id
                WHERE p.status = 1 AND p.is_featured = 1
                AND (u.ban_type = 0 OR u.ban_type = 1 OR u.ban_type IS NULL OR (u.ban_type = 1 AND u.ban_until > ?))";
        return (int)$this->db->fetchColumn($sql, [time()]);
    }

    public function togglePin($postId)
    {
        $post = $this->find($postId);
        if (!$post) {
            return false;
        }
        
        $newStatus = isset($post['is_pinned']) && $post['is_pinned'] ? 0 : 1;
        return $this->update($postId, ['is_pinned' => $newStatus]);
    }

    public function toggleFeature($postId)
    {
        $post = $this->find($postId);
        if (!$post) {
            return false;
        }
        
        $newStatus = isset($post['is_featured']) && $post['is_featured'] ? 0 : 1;
        return $this->update($postId, ['is_featured' => $newStatus]);
    }

    public function getUserPosts($userId, $page = 1, $pageSize = 10)
    {
        $offset = ($page - 1) * $pageSize;
        
        $sql = "SELECT p.*, u.username, u.avatar, u.last_activity
                FROM __PREFIX__posts p 
                INNER JOIN __PREFIX__users u ON p.user_id = u.id 
                WHERE p.user_id = ? AND p.status = 1 
                ORDER BY p.created_at DESC 
                LIMIT {$offset}, {$pageSize}";
        
        $posts = $this->db->fetchAll($sql, [$userId]);
        $posts = $this->formatPosts($posts);
        
        $total = $this->count('user_id = ? AND status = 1', [$userId]);
        $totalPages = ceil($total / $pageSize);
        
        return [
            'items' => $posts,
            'total' => $total,
            'page' => $page,
            'pageSize' => $pageSize,
            'totalPages' => $totalPages
        ];
    }

    public function getPost($id, $currentUserId = 0, $incrementViews = true)
    {
        $sql = "SELECT p.*, u.username, u.avatar, u.last_activity,
                       c.id as circle_id, c.name as circle_name
                FROM __PREFIX__posts p 
                INNER JOIN __PREFIX__users u ON p.user_id = u.id 
                LEFT JOIN __PREFIX__circle_posts cp ON p.id = cp.post_id
                LEFT JOIN __PREFIX__circles c ON cp.circle_id = c.id
                WHERE p.id = ?";
        
        $post = $this->db->fetch($sql, [$id]);
        
        if ($post) {
            // 增加阅读量（排除自己查看自己的帖子）
            if ($incrementViews && $currentUserId != $post['user_id']) {
                $this->db->query("UPDATE __PREFIX__posts SET views = views + 1 WHERE id = ?", [$id]);
            }
            
            $post['images'] = is_array($post['images']) ? $post['images'] : ($post['images'] ? json_decode($post['images'], true) : []);
            $post['attachments'] = is_array($post['attachments']) ? $post['attachments'] : ($post['attachments'] ? json_decode($post['attachments'], true) : []);
            $post['videos'] = is_array($post['videos']) ? $post['videos'] : ($post['videos'] ? json_decode($post['videos'], true) : []);
            $post['time_ago'] = Helper::formatTime($post['created_at']);
            
            if (!empty($post['repost_id'])) {
                $post['original_post'] = $this->getOriginalPost($post['repost_id'], $currentUserId);
            }
        }
        
        return $post;
    }

    public function getOriginalPost($id, $currentUserId = 0)
    {
        $sql = "SELECT p.*, u.username, u.avatar, u.last_activity
                FROM __PREFIX__posts p 
                INNER JOIN __PREFIX__users u ON p.user_id = u.id 
                WHERE p.id = ? AND p.status = 1";
        
        $post = $this->db->fetch($sql, [$id]);
        
        if ($post) {
            $post['images'] = is_array($post['images']) ? $post['images'] : ($post['images'] ? json_decode($post['images'], true) : []);
            $post['attachments'] = is_array($post['attachments']) ? $post['attachments'] : ($post['attachments'] ? json_decode($post['attachments'], true) : []);
            $post['videos'] = is_array($post['videos']) ? $post['videos'] : ($post['videos'] ? json_decode($post['videos'], true) : []);
            $post['time_ago'] = Helper::formatTime($post['created_at']);
            // 注意：内容解析在控制器中进行，Model层只返回原始内容
            $post['content'] = $this->parseHideContent($post['content'], $id, $currentUserId, $post['user_id']);
        } else {
            $post = ['deleted' => true];
        }
        
        return $post;
    }

    public function publish($data)
    {
        $data['created_at'] = time();
        $data['updated_at'] = time();
        $data['status'] = 1;
        $data['ip'] = Helper::getIp();
        
        // 处理匿名发布，默认关闭
        $data['is_anonymous'] = !empty($data['is_anonymous']) ? 1 : 0;
        
        // 处理位置信息
        // 只有当用户主动提供经纬度时才保存精准定位信息
        $hasPreciseLocation = false;
        if (!empty($data['location_latlng'])) {
            // 用户主动提供了经纬度 - 精准定位
            list($lat, $lng) = explode(',', $data['location_latlng']);
            $lat = trim($lat);
            $lng = trim($lng);
            
            // 验证经纬度格式
            if (is_numeric($lat) && is_numeric($lng) && $lat >= -90 && $lat <= 90 && $lng >= -180 && $lng <= 180) {
                $data['location_lat'] = $lat;
                $data['location_lng'] = $lng;
                
                // 通过经纬度获取位置名称
                $locationName = self::getLocationName($lat, $lng);
                $data['location_name'] = $locationName;
                $hasPreciseLocation = true;
            }
            unset($data['location_latlng']);
        }
        
        // 如果没有精准定位，使用IP获取粗略位置（仅保存位置名称，用于显示在用户名后面）
        if (!$hasPreciseLocation && !empty($data['ip'])) {
            require_once ROOT_PATH . 'core/IpLocation.php';
            $locationName = IpLocation::getLocation($data['ip']);
            $data['location_name'] = $locationName;
        }
        
        // 强制确保没有精准定位时不保存经纬度字段
        if (!$hasPreciseLocation) {
            unset($data['location_lat']);
            unset($data['location_lng']);
        }
        
        // 移除内容中的位置标记，因为位置卡片会单独显示位置信息
        if (!empty($data['content']) && strpos($data['content'], '[位置]') !== false) {
            $data['content'] = str_replace(['📍[位置]', '[位置]'], '', $data['content']);
        }
        
        if (isset($data['images']) && is_array($data['images'])) {
            $data['images'] = json_encode($data['images']);
        }
        
        if (isset($data['attachments']) && is_array($data['attachments'])) {
            $data['attachments'] = json_encode($data['attachments']);
        }
        
        // 处理视频字段，支持单个视频字符串和数组两种格式
        if (isset($data['video']) && !empty($data['video']) && is_string($data['video'])) {
            $data['videos'] = json_encode([$data['video']]);
            unset($data['video']);
        } elseif (isset($data['videos']) && is_array($data['videos'])) {
            $data['videos'] = json_encode($data['videos']);
        }
        
        // 处理圈子信息
        if (isset($data['circle_id'])) {
            $data['circle_id'] = (int)$data['circle_id'];
        }
        if (isset($data['circle_name'])) {
            $data['circle_name'] = trim($data['circle_name']);
        }
        
        $data = Hook::trigger('post_before_publish', $data);
        
        // 确保移除临时字段 location_latlng
        if (isset($data['location_latlng'])) {
            unset($data['location_latlng']);
        }
        
        // 保存圈子信息用于后续关联
        $circleId = isset($data['circle_id']) ? (int)$data['circle_id'] : 0;
        $circleName = isset($data['circle_name']) ? $data['circle_name'] : '';
        
        // 尝试插入数据，如果失败则移除圈子字段重试
        try {
            $postId = $this->insert($data);
        } catch (Exception $e) {
            // 如果是字段不存在的错误，移除圈子字段后重试
            if (strpos($e->getMessage(), 'Unknown column') !== false) {
                unset($data['circle_id']);
                unset($data['circle_name']);
                $postId = $this->insert($data);
            } else {
                throw $e;
            }
        }
        
        // 如果发布到圈子，添加关联记录
        if ($postId && $circleId > 0) {
            try {
                require_once ROOT_PATH . 'content/circle/CircleModel.php';
                $circleModel = new CircleModel();
                $circleModel->addPost($circleId, $postId);
            } catch (Exception $e) {
                // 忽略错误，不影响帖子发布
            }
        }
        
        return $postId;
    }
    
    /**
     * 获取指定圈子的动态列表
     */
    public function getPostsByCircle($circleId, $offset = 0, $limit = 10)
    {
        $sql = "SELECT p.*, u.username as user_name, u.avatar as user_avatar,
                       c.name as circle_name
                FROM __PREFIX__circle_posts cp
                INNER JOIN __PREFIX__posts p ON cp.post_id = p.id
                INNER JOIN __PREFIX__users u ON p.user_id = u.id
                LEFT JOIN __PREFIX__circles c ON cp.circle_id = c.id
                WHERE cp.circle_id = ?
                AND p.status = 1
                AND (u.ban_type = 0 OR u.ban_type = 1 OR u.ban_type IS NULL OR (u.ban_type = 1 AND u.ban_until > ?))
                ORDER BY p.created_at DESC
                LIMIT {$offset}, {$limit}";
        
        return $this->db->fetchAll($sql, [$circleId, time()]);
    }

    /**
     * 通过经纬度获取位置名称（使用免费服务，无需 API Key）
     */
    private static function getLocationName($lat, $lng)
    {
        // 优先使用 OpenStreetMap 的 Nominatim 服务（免费，无需 API Key）
        $url = 'https://nominatim.openstreetmap.org/reverse?lat=' . $lat . '&lon=' . $lng . '&format=json&accept-language=zh-CN';
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
        curl_setopt($ch, CURLOPT_USERAGENT, 'HuSNS/1.0'); // 添加 User-Agent
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($httpCode === 200 && !empty($response)) {
            $data = json_decode($response, true);
            if ($data && !empty($data['display_name'])) {
                // 返回简短的位置名称
                $address = $data['display_name'];
                // 提取省市信息
                $parts = [];
                if (!empty($data['address']['country'])) $parts[] = $data['address']['country'];
                if (!empty($data['address']['state'])) $parts[] = $data['address']['state'];
                if (!empty($data['address']['city'])) $parts[] = $data['address']['city'];
                if (!empty($data['address']['town'])) $parts[] = $data['address']['town'];
                if (!empty($data['address']['village'])) $parts[] = $data['address']['village'];
                if (!empty($parts)) {
                    return implode(' ', $parts);
                }
                // 如果没有结构化数据，返回完整名称的前50个字符
                return mb_substr($address, 0, 50, 'UTF-8');
            }
        }
        
        // 降级使用 ip-api（免费地理编码服务）
        $url = 'http://ip-api.com/json/' . $lat . ',' . $lng . '?lang=zh-CN&fields=status,regionName,city,district';
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($httpCode === 200 && !empty($response)) {
            $data = json_decode($response, true);
            if ($data && ($data['status'] ?? '') === 'success') {
                $parts = [];
                if (!empty($data['regionName'])) $parts[] = $data['regionName'];
                if (!empty($data['city']) && $data['city'] !== $data['regionName']) $parts[] = $data['city'];
                if (!empty($data['district']) && !in_array($data['district'], $parts)) $parts[] = $data['district'];
                return implode(' ', $parts);
            }
        }
        
        return '';
    }

    public function repost($userId, $originalPostId, $content = '', $alsoComment = false)
    {
        $originalPost = $this->getPost($originalPostId, $userId);
        if (!$originalPost || $originalPost['status'] != 1) {
            return false;
        }

        $finalOriginalId = $originalPostId;
        $repostUserId = $originalPost['user_id'];
        $originalContent = $content; // 保存原始内容用于评论
        
        if (!empty($originalPost['repost_id'])) {
            $finalOriginalId = $originalPost['repost_id'];
            $repostUserId = $originalPost['repost_user_id'];
            
            $chainContent = '@' . $originalPost['username'] . ': ' . strip_tags($originalPost['content']);
            if (!empty($content)) {
                $content = $content . ' // ' . $chainContent;
            } else {
                $content = $chainContent;
            }
        }

        $postId = $this->insert([
            'user_id' => $userId,
            'content' => $content,
            'repost_id' => $finalOriginalId,
            'repost_user_id' => $repostUserId,
            'created_at' => time(),
            'updated_at' => time(),
            'status' => 1,
            'ip' => Helper::getIp()
        ]);

        if ($postId) {
            $this->db->query(
                "UPDATE __PREFIX__posts SET reposts = reposts + 1 WHERE id = ?",
                [$originalPostId]
            );

            if ($alsoComment) {
                $this->addComment($originalPostId, $userId, $originalContent);
            }
        }

        return $postId;
    }

    public function deletePost($id, $userId, $isAdmin = false)
    {
        $post = $this->find($id);
        
        if (!$post) {
            return false;
        }
        
        if (!$isAdmin && $post['user_id'] != $userId) {
            return false;
        }
        
        Hook::trigger('post_before_delete', $post);

        $this->deletePostFiles($post);

        if (!empty($post['repost_id'])) {
            $this->db->query(
                "UPDATE __PREFIX__posts SET reposts = GREATEST(0, reposts - 1) WHERE id = ?",
                [$post['repost_id']]
            );
        }
        
        return $this->update($id, ['status' => 0, 'updated_at' => time()]);
    }

    private function deletePostFiles($post)
    {
        if (!empty($post['images'])) {
            $images = is_array($post['images']) ? $post['images'] : json_decode($post['images'], true);
            if (is_array($images)) {
                foreach ($images as $image) {
                    $filePath = UPLOAD_PATH . $image;
                    if (file_exists($filePath)) {
                        @unlink($filePath);
                    }
                }
            }
        }

        if (!empty($post['attachments'])) {
            $attachments = is_array($post['attachments']) ? $post['attachments'] : json_decode($post['attachments'], true);
            if (is_array($attachments)) {
                foreach ($attachments as $attachment) {
                    if (isset($attachment['path'])) {
                        $filePath = UPLOAD_PATH . $attachment['path'];
                        if (file_exists($filePath)) {
                            @unlink($filePath);
                        }
                    }
                }
            }
        }
    }

    public function like($postId, $userId)
    {
        $exists = $this->db->fetch(
            "SELECT * FROM __PREFIX__likes WHERE post_id = ? AND user_id = ?",
            [$postId, $userId]
        );
        
        if ($exists) {
            return false;
        }
        
        $this->db->insert('likes', [
            'post_id' => $postId,
            'user_id' => $userId,
            'created_at' => time()
        ]);
        
        $this->db->query(
            "UPDATE __PREFIX__posts SET likes = likes + 1 WHERE id = ?",
            [$postId]
        );
        
        return true;
    }

    public function unlike($postId, $userId)
    {
        $result = $this->db->delete('likes', 'post_id = ? AND user_id = ?', [$postId, $userId]);
        
        if ($result) {
            $this->db->query(
                "UPDATE __PREFIX__posts SET likes = GREATEST(0, likes - 1) WHERE id = ?",
                [$postId]
            );
        }
        
        return $result;
    }

    public function isLiked($postId, $userId)
    {
        return $this->db->count('likes', 'post_id = ? AND user_id = ?', [$postId, $userId]) > 0;
    }

    public function isReposted($postId, $userId)
    {
        return $this->db->count('posts', 'repost_id = ? AND user_id = ? AND status = 1', [$postId, $userId]) > 0;
    }
    
    /**
     * 评论点赞
     */
    public function likeComment($commentId, $userId)
    {
        // 检查是否已经点赞
        if ($this->db->count('comment_likes', 'comment_id = ? AND user_id = ?', [$commentId, $userId]) > 0) {
            return false;
        }
        
        // 添加点赞记录
        $this->db->insert('comment_likes', [
            'comment_id' => $commentId,
            'user_id' => $userId,
            'created_at' => time()
        ]);
        
        // 更新评论点赞数
        $this->db->query("UPDATE __PREFIX__comments SET likes = likes + 1 WHERE id = ?", [$commentId]);
        
        return true;
    }
    
    /**
     * 取消评论点赞
     */
    public function unlikeComment($commentId, $userId)
    {
        // 先检查记录是否存在
        $exists = $this->db->count('comment_likes', 'comment_id = ? AND user_id = ?', [$commentId, $userId]);
        if (!$exists) {
            return false;
        }
        
        // 删除记录
        $this->db->delete('comment_likes', 'comment_id = ? AND user_id = ?', [$commentId, $userId]);
        
        // 更新评论点赞数
        $this->db->query("UPDATE __PREFIX__comments SET likes = GREATEST(0, likes - 1) WHERE id = ?", [$commentId]);
        
        return true;
    }
    
    /**
     * 检查用户是否点赞过评论
     */
    public function isCommentLiked($commentId, $userId)
    {
        return $this->db->count('comment_likes', 'comment_id = ? AND user_id = ?', [$commentId, $userId]) > 0;
    }
    
    /**
     * 获取评论点赞数
     */
    public function getCommentLikes($commentId)
    {
        return (int)$this->db->fetchColumn("SELECT likes FROM __PREFIX__comments WHERE id = ?", [$commentId]);
    }
    
    public function getComments($postId, $page = 1, $pageSize = 20)
    {
        $offset = ($page - 1) * $pageSize;
        
        $sql = "SELECT c.*, u.username, u.avatar, u.last_activity
                FROM __PREFIX__comments c 
                INNER JOIN __PREFIX__users u ON c.user_id = u.id 
                WHERE c.post_id = ? AND c.status = 1 AND c.parent_id = 0 
                AND (u.ban_type = 0 OR u.ban_type = 1 OR u.ban_type IS NULL OR (u.ban_type = 1 AND u.ban_until > ?))
                ORDER BY c.created_at DESC 
                LIMIT {$offset}, {$pageSize}";
        
        $comments = $this->db->fetchAll($sql, [$postId, time()]);
        
        foreach ($comments as &$comment) {
            $comment['time_ago'] = Helper::formatTime($comment['created_at']);
            $comment['replies'] = $this->getReplies($comment['id']);
            $comment['reply_count'] = $this->countReplies($comment['id']);
        }
        
        return $comments;
    }
    
    /**
     * 获取热门评论
     * @param int $limit 返回数量
     * @return array
     */
    public function getHotComments($limit = 10)
    {
        $sql = "SELECT c.*, u.username, u.avatar 
                FROM __PREFIX__comments c 
                INNER JOIN __PREFIX__users u ON c.user_id = u.id 
                WHERE c.status = 1 AND c.parent_id = 0
                ORDER BY c.likes DESC, c.created_at DESC
                LIMIT ?";
        
        return $this->db->fetchAll($sql, [$limit]);
    }

    
    public function getReplies($parentId, $limit = 3)
    {
        $sql = "SELECT c.*, u.username, u.avatar, u.last_activity, ru.username as reply_to_username
                FROM __PREFIX__comments c 
                INNER JOIN __PREFIX__users u ON c.user_id = u.id 
                LEFT JOIN __PREFIX__users ru ON c.reply_to_user_id = ru.id 
                WHERE c.parent_id = ? AND c.status = 1 
                AND (u.ban_type = 0 OR u.ban_type = 1 OR u.ban_type IS NULL OR (u.ban_type = 1 AND u.ban_until > ?))
                ORDER BY c.created_at ASC 
                LIMIT {$limit}";
        
        $replies = $this->db->fetchAll($sql, [$parentId, time()]);
        
        foreach ($replies as &$reply) {
            $reply['time_ago'] = Helper::formatTime($reply['created_at']);
        }
        
        return $replies;
    }

    public function countReplies($parentId)
    {
        $sql = "SELECT COUNT(*) FROM __PREFIX__comments c 
                INNER JOIN __PREFIX__users u ON c.user_id = u.id 
                WHERE c.parent_id = ? AND c.status = 1 
                AND (u.ban_type = 0 OR u.ban_type = 1 OR u.ban_type IS NULL OR (u.ban_type = 1 AND u.ban_until > ?))";
        return (int)$this->db->fetchColumn($sql, [$parentId, time()]);
    }

    public function addComment($postId, $userId, $content, $parentId = 0, $replyToUserId = 0)
    {
        $content = Security::xssClean($content);
        $content = Hook::trigger('comment_before_add', $content);
        
        $this->db->insert('comments', [
            'post_id' => $postId,
            'user_id' => $userId,
            'content' => $content,
            'parent_id' => $parentId,
            'reply_to_user_id' => $replyToUserId,
            'status' => 1,
            'ip' => Helper::getIp(),
            'created_at' => time()
        ]);
        
        $this->db->query(
            "UPDATE __PREFIX__posts SET comments = comments + 1 WHERE id = ?",
            [$postId]
        );
        
        return $this->db->lastInsertId();
    }

    public function countUserPosts($userId)
    {
        return $this->count('user_id = ? AND status = 1', [$userId]);
    }

    public function getPostsByTopic($topic, $page = 1, $pageSize = 10, $tab = 'latest')
    {
        $offset = ($page - 1) * $pageSize;
        
        // 根据 tab 选择排序方式
        if ($tab === 'hot') {
            // 热门：按点赞数+评论数排序
            $orderBy = 'ORDER BY (p.likes + p.comments) DESC, p.created_at DESC';
        } else {
            // 最新：按创建时间排序
            $orderBy = 'ORDER BY p.created_at DESC';
        }
        
        $sql = "SELECT p.*, u.username, u.avatar, u.last_activity
                FROM __PREFIX__posts p 
                INNER JOIN __PREFIX__users u ON p.user_id = u.id 
                WHERE p.content LIKE ? AND p.status = 1 
                {$orderBy}
                LIMIT {$offset}, {$pageSize}";
        
        $posts = $this->db->fetchAll($sql, ['%#' . $topic . '#%']);
        return $this->formatPosts($posts);
    }

    public function countPostsByTopic($topic)
    {
        return $this->db->count('posts', 'content LIKE ? AND status = 1', ['%#' . $topic . '#%']);
    }

    public function getHotTopics($limit = 10)
    {
        $statDays = (int)Setting::get('topic_stat_days', 7);
        $startTime = time() - ($statDays * 86400);
        
        $sql = "SELECT content, likes, comments, reposts FROM __PREFIX__posts WHERE status = 1 AND created_at >= ?";
        $posts = $this->db->fetchAll($sql, [$startTime]);
        
        $topics = [];
        foreach ($posts as $post) {
            preg_match_all('/#([^#]+)#/', $post['content'], $matches);
            if (!empty($matches[1])) {
                foreach ($matches[1] as $topic) {
                    $topic = trim($topic);
                    if ($topic) {
                        if (!isset($topics[$topic])) {
                            $topics[$topic] = [
                                'count' => 0,
                                'engagement' => 0
                            ];
                        }
                        $topics[$topic]['count']++;
                        $topics[$topic]['engagement'] += (int)$post['likes'] + (int)$post['comments'] + (int)$post['reposts'];
                    }
                }
            }
        }
        
        $blockedTopics = $this->db->fetchAll("SELECT name FROM __PREFIX__topics WHERE is_blocked = 1");
        $blockedNames = array_column($blockedTopics, 'name');
        
        foreach ($blockedNames as $blockedName) {
            unset($topics[$blockedName]);
        }
        
        uasort($topics, function($a, $b) {
            return $b['engagement'] - $a['engagement'];
        });
        
        $autoTopics = [];
        foreach ($topics as $topic => $data) {
            $autoTopics[] = [
                'name' => $topic,
                'count' => $data['count'],
                'engagement' => $data['engagement'],
                'is_pinned' => false
            ];
        }
        
        $pinnedTopics = $this->db->fetchAll(
            "SELECT name, sort_order FROM __PREFIX__topics WHERE is_pinned = 1 AND is_blocked = 0 ORDER BY sort_order ASC"
        );
        
        $pinnedNames = array_column($pinnedTopics, 'name');
        $autoTopics = array_filter($autoTopics, function($topic) use ($pinnedNames) {
            return !in_array($topic['name'], $pinnedNames);
        });
        $autoTopics = array_values($autoTopics);
        
        $result = [];
        foreach ($pinnedTopics as $pinned) {
            $topicName = $pinned['name'];
            $count = isset($topics[$topicName]) ? $topics[$topicName]['count'] : 0;
            $engagement = isset($topics[$topicName]) ? $topics[$topicName]['engagement'] : 0;
            $result[] = [
                'name' => $topicName,
                'count' => $count,
                'engagement' => $engagement,
                'is_pinned' => true
            ];
        }
        
        $remainingSlots = $limit - count($result);
        if ($remainingSlots > 0) {
            $autoTopicsSlice = array_slice($autoTopics, 0, $remainingSlots);
            $result = array_merge($result, $autoTopicsSlice);
        }
        
        return array_slice($result, 0, $limit);
    }

    private function formatPosts($posts)
    {
        $userId = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0;
        $hideTagAdminOnly = Setting::isHideTagAdminOnly();
        
        $formattedPosts = [];
        foreach ($posts as $post) {
            $post['images'] = is_array($post['images']) ? $post['images'] : ($post['images'] ? json_decode($post['images'], true) : []);
            $post['time_ago'] = Helper::formatTime($post['created_at']);
            $post['content'] = ltrim($post['content']);
            // 注意：内容解析在控制器中进行，Model层只返回原始内容
            // 这样可以支持不同端使用不同的链接格式
            
            $post['attachments'] = is_array($post['attachments']) ? $post['attachments'] : ($post['attachments'] ? json_decode($post['attachments'], true) : []);
            $post['videos'] = is_array($post['videos']) ? $post['videos'] : ($post['videos'] ? json_decode($post['videos'], true) : []);
            
            $parseHide = true;
            if ($hideTagAdminOnly) {
                $authorIsAdmin = $this->isUserAdmin($post['user_id']);
                if (!$authorIsAdmin) {
                    $parseHide = false;
                    $post['content'] = str_replace(['[hide]', '[/hide]'], ['&#91;hide&#93;', '&#91;/hide&#93;'], $post['content']);
                }
            }
            
            if ($parseHide) {
                $post['content'] = $this->parseHideContent($post['content'], $post['id'], $userId, $post['user_id']);
            }
            
            if (!empty($post['repost_id'])) {
                $post['original_post'] = $this->getOriginalPost($post['repost_id'], $userId);
            }
            
            $formattedPosts[] = $post;
        }
        
        return $formattedPosts;
    }
    
    private function isUserAdmin($userId)
    {
        $sql = "SELECT is_admin FROM __PREFIX__users WHERE id = ?";
        $result = $this->db->fetch($sql, [$userId]);
        return $result && (int)$result['is_admin'] === 1;
    }
    
    public function hasUserCommented($postId, $userId)
    {
        if (!$userId) {
            return false;
        }
        
        $sql = "SELECT COUNT(*) as count FROM __PREFIX__comments 
                WHERE post_id = ? AND user_id = ? AND status = 1";
        
        $result = $this->db->fetch($sql, [$postId, $userId]);
        
        return $result['count'] > 0;
    }
    
    public function parseHideContent($content, $postId, $userId, $postAuthorId)
    {
        $hasHide = preg_match('/\[hide\](.*?)\[\/hide\]/is', $content);
        
        if (!$hasHide) {
            return $content;
        }
        
        $hasCommented = $this->hasUserCommented($postId, $userId);
        
        if ($hasCommented || ($userId && $userId == $postAuthorId)) {
            $content = preg_replace('/\[hide\](.*?)\[\/hide\]/is', '<div class="hide-content-revealed">$1</div>', $content);
        } else {
            $content = preg_replace('/\[hide\].*?\[\/hide\]/is', '<div class="hide-content-locked">🔒 此内容需要评论后才能查看</div>', $content);
        }
        
        return $content;
    }
}
