<?php
require_once 'config?';

// 检查是否是 AJAX 请求
$is_ajax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 
           strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';

if (!isset($_GET['id'])) {
    header('Location: models?');
    exit;
}

$model_id = intval($_GET['id']);

// 处理 AJAX 操作
if ($is_ajax && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = $_POST['action'] ?? '';
    
    header('Content-Type: application/json');
    
    switch ($action) {
        case 'like_comment':
            $comment_id = intval($_POST['comment_id'] ?? 0);
            if ($comment_id && isLoggedIn()) {
                $result = toggleCommentLike($comment_id, $_SESSION['user_id']);
                echo json_encode($result);
            } else {
                echo json_encode(['success' => false, 'message' => '评论ID无效或未登录']);
            }
            break;
            
        case 'comment':
            if (!isLoggedIn()) {
                echo json_encode(['success' => false, 'message' => '请先登录']);
                break;
            }
            
            $content = trim($_POST['content'] ?? '');
            $parent_id = isset($_POST['parent_id']) ? intval($_POST['parent_id']) : null;
            
            if (empty($content)) {
                echo json_encode(['success' => false, 'message' => '评论内容不能为空']);
                break;
            }
            
            if (strlen($content) > 1000) {
                echo json_encode(['success' => false, 'message' => '评论内容不能超过1000字']);
                break;
            }
            
            try {
                $pdo->beginTransaction();
                
                // 1. 先在comments表中插入记录
                $stmt = $pdo->prepare("INSERT INTO comments (user_id, content, parent_id, post_id) VALUES (?, ?, ?, NULL)");
                $stmt->execute([$_SESSION['user_id'], $content, $parent_id]);
                $comment_id = $pdo->lastInsertId();
                
                // 2. 然后在model_comments表中插入记录
                $stmt = $pdo->prepare("INSERT INTO model_comments (comment_id, model_id, parent_id, user_id, content) VALUES (?, ?, ?, ?, ?)");
                $stmt->execute([$comment_id, $model_id, $parent_id, $_SESSION['user_id'], $content]);
                
                // 3. 处理评论图片
                $comment_images = [];
                if (!empty($_FILES['comment_image']) && $_FILES['comment_image']['error'] === UPLOAD_ERR_OK) {
                    $result = uploadFile($_FILES['comment_image'], 'image');
                    if ($result['success']) {
                        $stmt = $pdo->prepare("INSERT INTO model_comment_media (comment_id, url, local_path) VALUES (?, ?, ?)");
                        $stmt->execute([$comment_id, $result['url'], $result['path']]);
                        $comment_images[] = $result['url'];
                    }
                }
                
                // 4. 获取模型信息用于通知
                $stmt = $pdo->prepare("SELECT user_id, title FROM models WHERE id = ?");
                $stmt->execute([$model_id]);
                $model_info = $stmt->fetch();
                
                // 5. 处理通知逻辑（避免重复发送）
                if ($parent_id) {
                    // 如果是回复，通知被回复的用户
                    $stmt = $pdo->prepare("SELECT user_id FROM comments WHERE id = ?");
                    $stmt->execute([$parent_id]);
                    $parent_comment = $stmt->fetch();
                    
                    if ($parent_comment && $_SESSION['user_id'] != $parent_comment['user_id']) {
                        // 检查是否已经有相同的通知（避免重复）
                        $stmt = $pdo->prepare("
                            SELECT COUNT(*) FROM notifications 
                            WHERE user_id = ? AND sender_id = ? AND type = 'model_comment' 
                            AND related_id = ? AND created_at > DATE_SUB(NOW(), INTERVAL 1 MINUTE)
                        ");
                        $stmt->execute([$parent_comment['user_id'], $_SESSION['user_id'], $model_id]);
                        $recent_notifications = $stmt->fetchColumn();
                        
                        if ($recent_notifications == 0) {
                            $content = $_SESSION['username'] . " 回复了你的评论";
                            sendNotification($parent_comment['user_id'], $_SESSION['user_id'], 'model_comment', $model_id, $content);
                        }
                    }
                } else {
                    // 新评论时通知模型作者（排除自己评论自己的情况）
                    if ($model_info && $_SESSION['user_id'] != $model_info['user_id']) {
                        // 检查是否已经有相同的通知（避免重复）
                        $stmt = $pdo->prepare("
                            SELECT COUNT(*) FROM notifications 
                            WHERE user_id = ? AND sender_id = ? AND type = 'model_comment' 
                            AND related_id = ? AND created_at > DATE_SUB(NOW(), INTERVAL 1 MINUTE)
                        ");
                        $stmt->execute([$model_info['user_id'], $_SESSION['user_id'], $model_id]);
                        $recent_notifications = $stmt->fetchColumn();
                        
                        if ($recent_notifications == 0) {
                            $content = $_SESSION['username'] . " 评论了你的模型: " . $model_info['title'];
                            sendNotification($model_info['user_id'], $_SESSION['user_id'], 'model_comment', $model_id, $content);
                        }
                    }
                }
                
                // 6. 获取新评论的完整信息
                $stmt = $pdo->prepare("
                    SELECT c.*, u.username, u.avatar, 
                           0 as like_count, 
                           0 as is_liked,
                           NULL as parent_username,
                           NULL as parent_content,
                           NULL as parent_parent_id,
                           NULL as grandparent_username
                    FROM comments c
                    JOIN users u ON c.user_id = u.id
                    WHERE c.id = ?
                ");
                $stmt->execute([$comment_id]);
                $new_comment = $stmt->fetch();
                $new_comment['comment_images'] = $comment_images;
                
                // 7. 获取评论总数
                $stmt = $pdo->prepare("SELECT COUNT(*) as comment_count FROM comments c JOIN model_comments mc ON c.id = mc.comment_id WHERE mc.model_id = ?");
                $stmt->execute([$model_id]);
                $comment_count_data = $stmt->fetch();
                $comment_count = $comment_count_data['comment_count'];
                
                $pdo->commit();
                
                echo json_encode([
                    'success' => true,
                    'comment' => $new_comment,
                    'comment_count' => $comment_count,
                    'message' => '评论成功'
                ]);
                
            } catch (Exception $e) {
                if ($pdo->inTransaction()) { $pdo->rollBack(); }
                error_log("评论提交失败: " . $e->getMessage());
                echo json_encode(['success' => false, 'message' => '评论失败: ' . $e->getMessage()]);
            }
            break;
            
        case 'delete_comment':
            if (!isLoggedIn()) {
                echo json_encode(['success' => false, 'message' => '请先登录']);
                break;
            }
            
            $comment_id = intval($_POST['comment_id'] ?? 0);
            
            if (!$comment_id) {
                echo json_encode(['success' => false, 'message' => '评论ID无效']);
                break;
            }
            
            try {
                // 获取评论信息
                $stmt = $pdo->prepare("SELECT c.*, m.user_id as model_user_id FROM comments c JOIN model_comments mc ON c.id = mc.comment_id JOIN models m ON mc.model_id = m.id WHERE c.id = ?");
                $stmt->execute([$comment_id]);
                $comment = $stmt->fetch();
                
                if (!$comment) {
                    echo json_encode(['success' => false, 'message' => '评论不存在']);
                    break;
                }
                
                // 检查权限：评论作者、模型作者或管理员
                $can_delete_comment = false;
                if (isLoggedIn()) {
                    $can_delete_comment = 
                        $comment['user_id'] == $_SESSION['user_id'] || 
                        $comment['model_user_id'] == $_SESSION['user_id'] || 
                        (isset($_SESSION['role']) && $_SESSION['role'] === 'admin');
                }
                
                if (!$can_delete_comment) {
                    echo json_encode(['success' => false, 'message' => '没有权限删除该评论']);
                    break;
                }
                
                $pdo->beginTransaction();
                
                // 删除评论点赞
                $stmt = $pdo->prepare("DELETE FROM comment_likes WHERE comment_id = ?");
                $stmt->execute([$comment_id]);
                
                // 删除评论媒体
                $stmt = $pdo->prepare("DELETE FROM model_comment_media WHERE comment_id = ?");
                $stmt->execute([$comment_id]);
                
                // 删除 model_comments 记录
                $stmt = $pdo->prepare("DELETE FROM model_comments WHERE comment_id = ?");
                $stmt->execute([$comment_id]);
                
                // 删除 comments 记录
                $stmt = $pdo->prepare("DELETE FROM comments WHERE id = ?");
                $stmt->execute([$comment_id]);
                
                $pdo->commit();
                
                // 获取更新后的评论数
                $stmt = $pdo->prepare("SELECT COUNT(*) as comment_count FROM comments c JOIN model_comments mc ON c.id = mc.comment_id WHERE mc.model_id = ?");
                $stmt->execute([$model_id]);
                $comment_count_data = $stmt->fetch();
                $comment_count = $comment_count_data['comment_count'];
                
                echo json_encode([
                    'success' => true,
                    'message' => '评论已删除',
                    'comment_count' => $comment_count
                ]);
                
            } catch (Exception $e) {
                if ($pdo->inTransaction()) { $pdo->rollBack(); }
                echo json_encode(['success' => false, 'message' => '删除失败: ' . $e->getMessage()]);
            }
            break;
            
        case 'record_download':
            if (!isLoggedIn()) {
                echo json_encode(['success' => false, 'message' => '请先登录']);
                break;
            }
            
            $file_id = intval($_POST['file_id'] ?? 0);
            $is_primary = intval($_POST['is_primary'] ?? 0);
            
            try {
                $pdo->beginTransaction();
                
                // 更新下载计数（如果是主文件）
                if ($is_primary) {
                    // 更新模型下载计数
                    $stmt = $pdo->prepare("UPDATE models SET downloads = downloads + 1 WHERE id = ?");
                    $stmt->execute([$model_id]);
                    
                    // 记录下载历史
                    $stmt = $pdo->prepare("INSERT INTO model_downloads (model_id, user_id) VALUES (?, ?)");
                    $stmt->execute([$model_id, $_SESSION['user_id']]);
                    
                    // 获取模型信息用于通知
                    $stmt = $pdo->prepare("SELECT user_id, title FROM models WHERE id = ?");
                    $stmt->execute([$model_id]);
                    $model_info = $stmt->fetch();
                    
                    // 发送通知给模型作者（如果不是自己下载的）
                    if ($model_info && $model_info['user_id'] != $_SESSION['user_id']) {
                        $content = $_SESSION['username'] . " 下载了你的模型: " . $model_info['title'];
                        sendNotification($model_info['user_id'], $_SESSION['user_id'], 'download', $model_id, $content);
                    }
                    
                    // 获取更新后的下载次数
                    $stmt = $pdo->prepare("SELECT downloads FROM models WHERE id = ?");
                    $stmt->execute([$model_id]);
                    $download_data = $stmt->fetch();
                    $download_count = $download_data['downloads'];
                } else {
                    $download_count = null;
                }
                
                $pdo->commit();
                
                echo json_encode([
                    'success' => true,
                    'download_count' => $download_count,
                    'message' => '下载记录已更新'
                ]);
                
            } catch (Exception $e) {
                if ($pdo->inTransaction()) { $pdo->rollBack(); }
                echo json_encode(['success' => false, 'message' => '记录下载失败: ' . $e->getMessage()]);
            }
            break;
            
        default:
            echo json_encode(['success' => false, 'message' => '未知操作']);
    }
    exit;
}

// 正常页面请求
// 获取模型信息
$stmt = $pdo->prepare("
    SELECT m.*, u.username, u.avatar, u.id as user_id, c.name as category_name, c.slug as category_slug 
    FROM models m 
    JOIN users u ON m.user_id = u.id 
    LEFT JOIN categories c ON m.category_id = c.id
    WHERE m.id = ?
");
$stmt->execute([$model_id]);
$model = $stmt->fetch();

if (!$model) {
    header('Location: models?');
    exit;
}

// 获取作者模型数量
$stmt = $pdo->prepare("SELECT COUNT(*) FROM models WHERE user_id = ?");
$stmt->execute([$model['user_id']]);
$author_model_count = $stmt->fetchColumn();

// 获取作者称号
$author_title = getUserTitle($author_model_count);

// 获取模型媒体并分类
$stmt = $pdo->prepare("
    SELECT * FROM model_media 
    WHERE model_id = ? 
    ORDER BY CASE 
        WHEN type = 'video' THEN 0 
        WHEN type = 'image' THEN 1 
        ELSE 2 
    END, `order`
");
$stmt->execute([$model_id]);
$allMedia = $stmt->fetchAll();

// 分类媒体内容
$videos = [];
$images = [];
$files = [];

foreach ($allMedia as $media) {
    switch ($media['type']) {
        case 'video':
            $videos[] = $media;
            break;
        case 'image':
            $images[] = $media;
            break;
        case 'file':
            $files[] = $media;
            break;
    }
}

// 获取模型评论（所有评论）
$stmt = $pdo->prepare("
    SELECT c.*, u.username, u.avatar, 
           (SELECT COUNT(*) FROM comment_likes WHERE comment_id = c.id) AS like_count,
           (SELECT COUNT(*) FROM comment_likes WHERE comment_id = c.id AND user_id = ?) AS is_liked,
           parent_user.username AS parent_username,
           parent_comment.content AS parent_content,
           parent_comment.parent_id AS parent_parent_id,
           grandparent_user.username AS grandparent_username
    FROM comments c
    JOIN users u ON c.user_id = u.id
    JOIN model_comments mc ON c.id = mc.comment_id
    LEFT JOIN comments parent_comment ON c.parent_id = parent_comment.id
    LEFT JOIN users parent_user ON parent_comment.user_id = parent_user.id
    LEFT JOIN comments grandparent_comment ON parent_comment.parent_id = grandparent_comment.id
    LEFT JOIN users grandparent_user ON grandparent_comment.user_id = grandparent_user.id
    WHERE mc.model_id = ?
    ORDER BY c.created_at ASC
");
$stmt->execute([$_SESSION['user_id'] ?? 0, $model_id]);
$comments = $stmt->fetchAll();

// 使用config?中的isMobile函数
$isMobile = isMobile();

// PHP 登录状态变量，供JavaScript使用
$isLoggedIn = isLoggedIn();
$isAdmin = isset($_SESSION['role']) && $_SESSION['role'] === 'admin';
$isOwner = $isLoggedIn && (int)($_SESSION['user_id'] ?? 0) === (int)$model['user_id'];
$isVip = false;

// 自动补会员字段：全部模型下载为会员专享
try {
    $stmt = $pdo->prepare("SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users' AND COLUMN_NAME = 'is_vip'");
    $stmt->execute();
    if ((int)$stmt->fetchColumn() === 0) {
        $pdo->exec("ALTER TABLE users ADD COLUMN is_vip TINYINT(1) NOT NULL DEFAULT 0 AFTER role");
    }
    $stmt = $pdo->prepare("SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users' AND COLUMN_NAME = 'vip_expire_at'");
    $stmt->execute();
    if ((int)$stmt->fetchColumn() === 0) {
        $pdo->exec("ALTER TABLE users ADD COLUMN vip_expire_at DATETIME DEFAULT NULL AFTER is_vip");
    }
} catch (Throwable $e) {}

if ($isLoggedIn) {
    try {
        $stmt = $pdo->prepare("SELECT is_vip, vip_expire_at FROM users WHERE id = ?");
        $stmt->execute([$_SESSION['user_id']]);
        $vipUser = $stmt->fetch();
        $isVip = $vipUser
            && (int)($vipUser['is_vip'] ?? 0) === 1
            && !empty($vipUser['vip_expire_at'])
            && strtotime($vipUser['vip_expire_at']) > time();
    } catch (Throwable $e) {}
}
$canDownloadModel = $isVip || $isAdmin || $isOwner;

function m_e($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
function m_avatar($u) { return $u ?: (defined('DEFAULT_AVATAR') ? DEFAULT_AVATAR : '/assets/default_avatar.png'); }
function m_date($d) { return function_exists('formatDate') ? formatDate($d) : date('Y-m-d H:i', strtotime($d)); }
function m_size($bytes) { return function_exists('formatFileSize') ? formatFileSize((int)$bytes) : ((int)$bytes > 0 ? round($bytes / 1024, 1) . ' KB' : '未知大小'); }

function ccModelComment($comment) {
    global $pdo, $model;
    $isReply = ($comment['parent_id'] !== null);
    $canDelete = false;
    if (isset($_SESSION['user_id'])) {
        $canDelete = $comment['user_id'] == $_SESSION['user_id']
            || $model['user_id'] == $_SESSION['user_id']
            || (isset($_SESSION['role']) && $_SESSION['role'] === 'admin');
    }
    $stmt = $pdo->prepare("SELECT url FROM model_comment_media WHERE comment_id = ?");
    $stmt->execute([$comment['id']]);
    $imgs = $stmt->fetchAll();
    ?>
    <div class="cc-comment" id="comment-<?php echo (int)$comment['id']; ?>" data-reveal>
        <a class="cc-comment-avatar" href="index??view=profile&id=<?php echo (int)$comment['user_id']; ?>">
            <img src="<?php echo m_e(m_avatar($comment['avatar'])); ?>" alt="">
        </a>
        <div class="cc-comment-body">
            <div class="cc-comment-meta">
                <a class="cc-comment-name" href="index??view=profile&id=<?php echo (int)$comment['user_id']; ?>"><?php echo m_e($comment['username']); ?></a>
                <span><?php echo m_e(m_date($comment['created_at'])); ?></span>
            </div>
            <?php if ($isReply && !empty($comment['parent_username']) && !empty($comment['parent_content'])): ?>
                <div class="cc-quote">
                    <div class="cc-quote-tag">回复 @<?php echo m_e($comment['parent_username']); ?><?php if (!empty($comment['grandparent_username'])): ?> · @<?php echo m_e($comment['grandparent_username']); ?><?php endif; ?></div>
                    <div class="cc-quote-text"><?php echo nl2br(m_e($comment['parent_content'])); ?></div>
                </div>
            <?php endif; ?>
            <div class="cc-comment-text"><?php echo nl2br(m_e($comment['content'])); ?></div>
            <?php if ($imgs): ?>
                <div class="cc-comment-images">
                    <?php foreach ($imgs as $img): ?>
                        <a class="cc-lightbox" href="<?php echo m_e($img['url']); ?>"><img src="<?php echo m_e($img['url']); ?>" alt=""></a>
                    <?php endforeach; ?>
                </div>
            <?php endif; ?>
            <div class="cc-comment-actions">
                <button class="cc-act like-btn <?php echo $comment['is_liked'] ? 'liked' : ''; ?>" data-comment-id="<?php echo (int)$comment['id']; ?>">
                    <svg viewBox="0 0 24 24" class="cc-ic"><path d="M12 21s-7.5-4.6-9.5-9.4C1 7.4 4.2 4 7.7 4c2 0 3.4 1 4.3 2.4C13 5 14.4 4 16.4 4c3.5 0 6.7 3.4 5.1 7.6C19.5 16.4 12 21 12 21Z"/></svg>
                    <span class="like-count"><?php echo (int)$comment['like_count']; ?></span>
                </button>
                <button class="cc-act reply-btn" data-comment-id="<?php echo (int)$comment['id']; ?>" data-username="<?php echo m_e($comment['username']); ?>">
                    <svg viewBox="0 0 24 24" class="cc-ic"><path d="M21 12a8 8 0 0 1-11.6 7.1L3 21l1.9-6.4A8 8 0 1 1 21 12Z"/></svg>
                    <span>回复</span>
                </button>
                <?php if ($canDelete): ?>
                    <button class="cc-act danger delete-comment-btn" data-comment-id="<?php echo (int)$comment['id']; ?>">
                        <svg viewBox="0 0 24 24" class="cc-ic"><path d="M5 7h14M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2m-7 0v12a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2V7"/></svg>
                    </button>
                <?php endif; ?>
            </div>
            <div class="cc-reply-form" id="reply-form-<?php echo (int)$comment['id']; ?>" hidden>
                <form class="reply-form" data-comment-id="<?php echo (int)$comment['id']; ?>">
                    <input type="hidden" name="action" value="comment">
                    <input type="hidden" name="parent_id" value="<?php echo (int)$comment['id']; ?>">
                    <textarea class="cc-textarea" name="content" rows="2" maxlength="1000" placeholder="回复 @<?php echo m_e($comment['username']); ?>..." required></textarea>
                    <div class="cc-mini-bar">
                        <label class="cc-chip" for="reply_image_<?php echo (int)$comment['id']; ?>">
                            <svg viewBox="0 0 24 24" class="cc-ic"><rect x="3" y="5" width="18" height="14" rx="3"/><circle cx="9" cy="11" r="2"/><path d="m4 19 5-5 4 4 3-3 4 4"/></svg>图片
                        </label>
                        <input type="file" name="comment_image" id="reply_image_<?php echo (int)$comment['id']; ?>" accept="image/*" hidden>
                        <button type="submit" class="cc-btn cc-btn-small">发送</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <?php
}
?>
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<title><?php echo m_e($model['title']); ?> · CartoonCove</title>
<link rel="icon" href="icon/icon.png">
<style>
:root{--blue:#2563eb;--blue2:#3b82f6;--blue3:#60a5fa;--soft:#dbeafe;--bg:#eff6ff;--text:#0f172a;--muted:#64748b;--card:rgba(255,255,255,.72);--strong:rgba(255,255,255,.9);--line:rgba(148,163,184,.24);--shadow:0 18px 45px -22px rgba(37,99,235,.45);--ease:cubic-bezier(.22,.8,.25,1)}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"PingFang SC","Microsoft YaHei",sans-serif;color:var(--text);background:var(--bg);background-image:radial-gradient(ellipse at 8% 8%,rgba(96,165,250,.32),transparent 48%),radial-gradient(ellipse at 92% 16%,rgba(59,130,246,.18),transparent 48%),linear-gradient(180deg,#f8fbff 0%,#eef6ff 55%,#fff 100%);background-attachment:fixed;padding-top:64px;padding-bottom:112px;overflow-x:hidden}body:before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;background:radial-gradient(circle at 22% 30%,rgba(255,255,255,.72),transparent 32%),radial-gradient(circle at 78% 74%,rgba(191,219,254,.55),transparent 40%);animation:bgFloat 14s ease-in-out infinite alternate}@keyframes bgFloat{to{transform:translate3d(-14px,8px,0) scale(1.02)}}a{text-decoration:none;color:inherit}button{font:inherit;color:inherit;border:0;background:none;cursor:pointer}img,video{max-width:100%;display:block}.cc-ic{width:21px;height:21px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.cc-top{position:fixed;inset:0 0 auto;height:64px;z-index:60;display:flex;align-items:center;gap:10px;padding:0 14px;background:linear-gradient(180deg,rgba(255,255,255,.84),rgba(255,255,255,.55));border-bottom:1px solid var(--line);backdrop-filter:saturate(160%) blur(18px);-webkit-backdrop-filter:saturate(160%) blur(18px)}.back-btn,.top-btn{width:40px;height:40px;border-radius:14px;display:grid;place-items:center;background:rgba(255,255,255,.72);box-shadow:0 8px 22px -12px rgba(37,99,235,.5);transition:.25s var(--ease)}.back-btn:hover{transform:translateX(-2px)}.brand{display:flex;align-items:center;gap:8px;font-weight:900;color:var(--blue)}.brand img{width:28px;height:28px;border-radius:8px;object-fit:contain}.grow{flex:1}
.app{max-width:760px;margin:0 auto;padding:16px 14px 148px}.card{background:var(--card);border:1px solid var(--line);border-radius:24px;box-shadow:var(--shadow);backdrop-filter:saturate(160%) blur(18px);-webkit-backdrop-filter:saturate(160%) blur(18px);overflow:hidden;animation:cardIn .55s var(--ease) both}@keyframes cardIn{from{opacity:0;transform:translateY(14px) scale(.985);filter:blur(6px)}to{opacity:1;transform:none;filter:none}}
.download-head{padding:14px}.download-layout{display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);gap:14px;align-items:stretch}.preview-panel{position:relative;min-height:250px;border-radius:20px;overflow:hidden;background:linear-gradient(135deg,#dbeafe,#eff6ff);border:1px solid var(--line);box-shadow:inset 0 1px 0 rgba(255,255,255,.7)}.preview-panel img,.preview-panel video{width:100%;height:100%;min-height:250px;object-fit:cover}.preview-empty{height:100%;min-height:250px;display:grid;place-items:center;color:var(--blue);font-weight:900;background:radial-gradient(circle at 70% 20%,rgba(255,255,255,.9),transparent 35%),linear-gradient(135deg,#bfdbfe,#eff6ff)}.preview-badge{position:absolute;left:12px;top:12px;display:inline-flex;align-items:center;gap:5px;padding:7px 10px;border-radius:999px;background:rgba(255,255,255,.78);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);color:var(--blue);font-size:12px;font-weight:900;box-shadow:0 10px 22px -14px rgba(15,23,42,.4)}
.download-info{display:flex;flex-direction:column;gap:12px;padding:4px 2px}.software-title{font-size:26px;line-height:1.18;letter-spacing:-.055em;font-weight:950}.software-desc{font-size:14.5px;line-height:1.62;color:#334155;display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}.creator-line{display:flex;align-items:center;gap:10px;padding:9px;border-radius:16px;background:rgba(255,255,255,.56);border:1px solid var(--line)}.creator-line .avatar{width:42px;height:42px;box-shadow:0 0 0 2px #fff,0 8px 18px -12px rgba(37,99,235,.55)}.creator-line .author-name{font-size:14px}.creator-line .author-meta{font-size:11px}.download-cta{display:grid;grid-template-columns:1fr auto;gap:10px;margin-top:auto}.main-download{display:flex;align-items:center;justify-content:center;gap:8px;min-height:50px;border-radius:18px;background:linear-gradient(135deg,var(--blue),var(--blue2));color:#fff;font-size:16px;font-weight:950;box-shadow:0 18px 36px -16px rgba(37,99,235,.8);transition:.25s var(--ease)}.main-download:hover{transform:translateY(-2px) scale(1.01)}.main-download.login{background:linear-gradient(135deg,#0f172a,#334155)}.ghost-action{display:grid;place-items:center;width:50px;height:50px;border-radius:18px;background:rgba(255,255,255,.7);border:1px solid var(--line);color:var(--blue);transition:.25s var(--ease)}.ghost-action:hover{transform:translateY(-2px)}
.inline-shots{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px;border-radius:16px;overflow:hidden}.inline-shots a{display:block;min-width:0;background:#e2e8f0;overflow:hidden}.inline-shots img{width:100%;height:100%;aspect-ratio:1/1;object-fit:cover;transition:.45s var(--ease)}.inline-shots a:hover img{transform:scale(1.05)}.meta-strip{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.meta-item{padding:10px 8px;border-radius:15px;background:rgba(255,255,255,.6);border:1px solid var(--line);text-align:center}.meta-item b{display:block;color:var(--blue);font-size:16px}.meta-item span{font-size:11px;color:var(--muted);font-weight:800}.file-count-hint{font-size:12px;color:var(--muted);font-weight:700;text-align:center}
.hero{position:relative}.hero-cover{height:168px;background:linear-gradient(135deg,#052c65 0%,var(--blue) 58%,var(--blue3));position:relative;overflow:hidden}.hero-cover:before{content:"";position:absolute;inset:0;background:radial-gradient(circle at 80% 18%,rgba(255,255,255,.5),transparent 7rem),linear-gradient(rgba(255,255,255,.11) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.11) 1px,transparent 1px);background-size:auto,34px 34px,34px 34px}.hero-body{padding:0 18px 18px}.author{display:flex;gap:12px;align-items:flex-end;margin-top:-34px;position:relative;z-index:2}.avatar{width:76px;height:76px;border-radius:999px;overflow:hidden;box-shadow:0 0 0 4px rgba(255,255,255,.95),0 12px 28px -14px rgba(15,23,42,.55);background:#fff}.avatar img{width:100%;height:100%;object-fit:cover}.author-main{flex:1;min-width:0;padding-bottom:5px}.author-name{font-weight:900;font-size:17px}.author-meta{font-size:12px;color:var(--muted);margin-top:3px;display:flex;gap:6px;flex-wrap:wrap}.title-badge{display:inline-flex;align-items:center;padding:3px 8px;border-radius:999px;background:linear-gradient(135deg,#e7f1ff,#dbeafe);color:var(--blue);font-size:11px;font-weight:800}.model-title{font-size:24px;line-height:1.25;letter-spacing:-.04em;margin:15px 0 8px;font-weight:950}.desc{font-size:15px;line-height:1.72;color:#1e293b;white-space:pre-line}.tag-row{display:flex;gap:8px;flex-wrap:wrap;margin:12px 0}.pill{display:inline-flex;align-items:center;gap:5px;padding:7px 10px;border-radius:999px;background:rgba(59,130,246,.1);color:var(--blue);font-size:12px;font-weight:800}.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:14px}.stat{padding:10px;border-radius:16px;background:rgba(255,255,255,.58);text-align:center;border:1px solid var(--line)}.stat b{display:block;color:var(--blue);font-size:17px}.stat span{font-size:11px;color:var(--muted);font-weight:700}
.section{padding:16px 18px}.section+.section{border-top:1px solid var(--line)}.section-title{font-size:15px;font-weight:900;margin-bottom:10px;display:flex;align-items:center;gap:8px}.video-box{border-radius:18px;overflow:hidden;background:#020617;box-shadow:0 18px 42px -24px rgba(15,23,42,.65)}.video-box video{width:100%;max-height:540px;background:#000}.grid{display:grid;gap:7px;grid-template-columns:repeat(2,1fr);border-radius:18px;overflow:hidden}.grid.n-1{grid-template-columns:1fr}.grid.n-3 a:first-child{grid-row:span 2}.grid a{background:#e2e8f0;overflow:hidden}.grid img{width:100%;height:100%;aspect-ratio:1/1;object-fit:cover;transition:.5s var(--ease)}.grid.n-1 img{aspect-ratio:auto;max-height:560px}.grid a:hover img{transform:scale(1.05)}
.files{display:grid;gap:9px}.file{display:flex;align-items:center;gap:12px;min-width:0;padding:11px 12px;border-radius:16px;background:rgba(255,255,255,.64);border:1px solid var(--line);transition:.25s var(--ease)}.file:hover{transform:translateY(-2px);box-shadow:0 14px 26px -18px rgba(37,99,235,.5)}.file-ico{width:42px;height:42px;flex:0 0 42px;border-radius:14px;display:grid;place-items:center;background:linear-gradient(135deg,#bfdbfe,#e0f2fe);color:var(--blue)}.file-info{flex:1 1 auto;min-width:0;overflow:hidden}.file-name{display:block;max-width:100%;font-weight:800;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-size{font-size:12px;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.primary{display:inline-flex;margin-left:5px;padding:2px 7px;border-radius:999px;background:var(--blue);color:#fff;font-size:10px;vertical-align:middle}.download{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;white-space:nowrap;gap:6px;padding:8px 14px;border-radius:999px;background:linear-gradient(135deg,var(--blue),var(--blue2));color:#fff;font-weight:800;font-size:13px;box-shadow:0 10px 26px -10px rgba(37,99,235,.7);transition:.25s var(--ease)}.download:disabled{opacity:.55}.download:hover{transform:translateY(-1px) scale(1.02)}
.download.vip-lock{background:linear-gradient(135deg,#f59e0b,#fbbf24);box-shadow:0 10px 26px -10px rgba(245,158,11,.7)}.vip-note{margin:10px 0 0;padding:10px 12px;border-radius:16px;background:rgba(251,191,36,.13);border:1px solid rgba(245,158,11,.22);color:#92400e;font-size:12px;font-weight:800;line-height:1.55}
.bar{display:flex;justify-content:space-around;padding:8px 4px 14px;border-top:1px solid var(--line)}.bar-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:10px;border-radius:15px;color:var(--muted);font-size:14px;font-weight:800;transition:.25s}.bar-btn:hover{background:rgba(59,130,246,.09);color:var(--blue)}
.comments{margin-top:16px;margin-bottom:120px;padding:18px}.comments-head{font-size:16px;font-weight:950;margin-bottom:12px;display:flex;align-items:center;gap:8px}.comments-head:before{content:"";width:4px;height:16px;border-radius:999px;background:linear-gradient(135deg,var(--blue),var(--blue3))}.empty{text-align:center;color:var(--muted);padding:32px 0}.cc-comment{display:flex;gap:10px;padding:12px 0;border-bottom:1px dashed rgba(148,163,184,.24)}.cc-comment:last-child{border-bottom:0}.cc-comment-avatar{width:40px;height:40px;flex:0 0 auto;border-radius:999px;overflow:hidden;box-shadow:0 0 0 2px #fff,0 6px 18px -10px rgba(37,99,235,.5)}.cc-comment-avatar img{width:100%;height:100%;object-fit:cover}.cc-comment-body{flex:1;min-width:0}.cc-comment-meta{display:flex;gap:8px;align-items:center;margin-bottom:4px;font-size:11px;color:var(--muted)}.cc-comment-name{font-size:14px;color:#1d4ed8;font-weight:900}.cc-comment-text{font-size:14.5px;line-height:1.62}.cc-quote{margin:6px 0;padding:8px 10px;border-radius:10px;background:rgba(96,165,250,.1);border-left:3px solid var(--blue3)}.cc-quote-tag{font-size:11px;color:var(--blue);font-weight:800}.cc-quote-text{font-size:12px;color:var(--muted);max-height:44px;overflow:hidden}.cc-comment-images{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}.cc-comment-images a{width:118px;height:118px;border-radius:13px;overflow:hidden;background:#e2e8f0}.cc-comment-images img{width:100%;height:100%;object-fit:cover}.cc-comment-actions{display:flex;gap:6px;margin-top:6px}.cc-act{display:inline-flex;align-items:center;gap:5px;padding:6px 9px;border-radius:999px;font-size:12px;color:var(--muted);font-weight:800}.cc-act:hover{background:rgba(59,130,246,.1);color:var(--blue)}.cc-act.liked{color:#ef4444}.cc-act.liked .cc-ic{fill:currentColor;stroke:none}.cc-act.danger:hover{color:#ef4444;background:rgba(239,68,68,.1)}.cc-act .cc-ic{width:16px;height:16px}.cc-reply-form{margin-top:8px;padding:10px;border:1px solid var(--line);border-radius:15px;background:rgba(255,255,255,.62)}.cc-textarea{width:100%;resize:none;border:0;outline:0;background:transparent;font-size:14px;line-height:1.5}.cc-mini-bar{display:flex;justify-content:space-between;align-items:center;margin-top:8px}.cc-chip{display:inline-flex;align-items:center;gap:5px;padding:7px 10px;border-radius:999px;background:rgba(59,130,246,.12);color:var(--blue);font-size:12px;font-weight:800;cursor:pointer}.cc-btn{border-radius:999px;padding:8px 16px;background:linear-gradient(135deg,var(--blue),var(--blue2));color:#fff;font-weight:900;box-shadow:0 10px 26px -10px rgba(37,99,235,.7)}.cc-btn-small{font-size:13px;padding:7px 14px}
.dock{position:fixed;left:0;right:0;bottom:0;z-index:50;background:linear-gradient(180deg,rgba(255,255,255,.65),rgba(255,255,255,.94));border-top:1px solid var(--line);backdrop-filter:saturate(160%) blur(18px);-webkit-backdrop-filter:saturate(160%) blur(18px);padding:8px 12px env(safe-area-inset-bottom,8px)}.reply-status{display:flex;justify-content:space-between;align-items:center;padding:6px 12px;margin-bottom:6px;border-radius:999px;background:rgba(59,130,246,.13);color:var(--blue);font-size:12px}.dock-row{display:flex;align-items:flex-end;gap:8px;max-width:760px;margin:0 auto}.dock-input{flex:1;padding:10px 14px;border-radius:18px;border:1px solid var(--line);background:rgba(255,255,255,.86)}.dock-input textarea{width:100%;resize:none;border:0;outline:0;background:transparent;font-size:14.5px;line-height:1.5;max-height:120px}.preview{position:relative;width:100px;margin-top:7px}.preview img{border-radius:11px}.preview button{position:absolute;right:-6px;top:-6px;width:22px;height:22px;border-radius:999px;background:#fff;color:#ef4444;box-shadow:0 4px 12px rgba(0,0,0,.18)}.send{width:42px;height:42px;border-radius:999px;display:grid;place-items:center;background:linear-gradient(135deg,var(--blue),var(--blue2));color:#fff;box-shadow:0 12px 28px -10px rgba(37,99,235,.7);transition:.25s}.send:hover{transform:scale(1.05) rotate(-8deg)}
.toast-wrap{position:fixed;top:80px;left:50%;transform:translateX(-50%);z-index:150;display:grid;gap:8px}.toast{padding:10px 16px;border-radius:999px;background:rgba(15,23,42,.88);color:#fff;font-size:13px;box-shadow:0 14px 34px -10px rgba(15,23,42,.5);animation:toastIn .3s}.toast.ok{background:linear-gradient(135deg,#10b981,#22c55e)}.toast.err{background:linear-gradient(135deg,#ef4444,#f87171)}@keyframes toastIn{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
.lb{position:fixed;inset:0;z-index:120;display:none;align-items:center;justify-content:center;background:rgba(0,0,0,.86);padding:20px}.lb.open{display:flex}.lb img{max-height:90vh;border-radius:14px;box-shadow:0 30px 70px rgba(0,0,0,.45)}.lb button{position:absolute;top:16px;right:16px;width:42px;height:42px;border-radius:999px;background:rgba(255,255,255,.18);color:#fff;display:grid;place-items:center}[data-reveal]{opacity:0;transform:translateY(12px) scale(.99);transition:.55s var(--ease)}[data-reveal].in{opacity:1;transform:none}
@media(max-width:680px){.download-layout{grid-template-columns:1fr}.preview-panel,.preview-panel img,.preview-panel video,.preview-empty{min-height:210px}.software-title{font-size:23px}.download-info{padding:0}.download-cta{grid-template-columns:1fr auto}}
@media(max-width:520px){.app{padding:12px 10px 150px}.hero-cover{height:136px}.model-title{font-size:21px}.stats{grid-template-columns:repeat(3,1fr)}.section{padding:14px}.comments{padding:14px}.file{align-items:flex-start}.download{padding:8px 12px}.grid{gap:5px}.download-head{padding:10px}.preview-panel,.preview-panel img,.preview-panel video,.preview-empty{min-height:190px}.software-title{font-size:21px}.meta-strip{grid-template-columns:repeat(3,1fr)}}
</style>
</head>
<body>
<header class="cc-top">
    <a class="back-btn" href="#" id="navBackBtn" aria-label="返回上一级"><svg viewBox="0 0 24 24" class="cc-ic"><path d="m15 18-6-6 6-6"/></svg></a>
    <a class="brand" href="index?"><img src="icon/icon.png" alt="CartoonCove"><span>CartoonCove</span></a>
    <div class="grow"></div>
    <a class="top-btn" href="index??view=resources" aria-label="资源列表"><svg viewBox="0 0 24 24" class="cc-ic"><path d="M4 6h16M4 12h16M4 18h10"/></svg></a>
</header>
<div class="toast-wrap" id="toastWrap"></div>
<main class="app">
    <?php if (isset($_SESSION['error'])): ?><div class="card" style="padding:12px 16px;margin-bottom:12px;color:#b91c1c;background:rgba(239,68,68,.1)"><?php echo m_e($_SESSION['error']); unset($_SESSION['error']); ?></div><?php endif; ?>
    <?php if (isset($_SESSION['success'])): ?><div class="card" style="padding:12px 16px;margin-bottom:12px;color:#047857;background:rgba(16,185,129,.1)"><?php echo m_e($_SESSION['success']); unset($_SESSION['success']); ?></div><?php endif; ?>
    <?php
    $primaryFile = null;
    foreach ($files as $f) {
        if (!empty($f['is_primary'])) { $primaryFile = $f; break; }
    }
    if (!$primaryFile && !empty($files)) $primaryFile = $files[0];
    $primaryFileName = $primaryFile ? ($primaryFile['name'] ?? basename($primaryFile['url'])) : '';
    ?>

    <article class="card download-head" data-reveal>
        <div class="download-layout">
            <div class="preview-panel">
                <span class="preview-badge"><svg viewBox="0 0 24 24" class="cc-ic" style="width:14px;height:14px"><path d="M12 3 4 7v10l8 4 8-4V7z"/><path d="m4 7 8 4 8-4M12 11v10"/></svg>模型资源</span>
                <?php if (!empty($videos)): ?>
                    <video controls playsinline preload="metadata"><source src="<?php echo m_e($videos[0]['url']); ?>" type="video/mp4">您的浏览器不支持视频播放</video>
                <?php elseif (!empty($images)): ?>
                    <a class="cc-lightbox" href="<?php echo m_e($images[0]['url']); ?>"><img src="<?php echo m_e($images[0]['url']); ?>" alt="<?php echo m_e($model['title']); ?>"></a>
                <?php else: ?>
                    <div class="preview-empty">CartoonCove 3D Model</div>
                <?php endif; ?>
            </div>
            <div class="download-info">
                <div class="tag-row" style="margin:0">
                    <a class="pill" href="index??view=resources&category=<?php echo urlencode($model['category_slug'] ?? ''); ?>"><svg viewBox="0 0 24 24" class="cc-ic" style="width:14px;height:14px"><path d="M3 12 12 3l9 9-9 9z"/></svg><?php echo m_e($model['category_name'] ?? '未分类'); ?></a>
                </div>
                <h1 class="software-title"><?php echo m_e($model['title']); ?></h1>
                <div class="creator-line">
                    <a class="avatar" href="index??view=profile&id=<?php echo (int)$model['user_id']; ?>"><img src="<?php echo m_e(m_avatar($model['avatar'])); ?>" alt=""></a>
                    <div class="author-main">
                        <a class="author-name" href="index??view=profile&id=<?php echo (int)$model['user_id']; ?>"><?php echo m_e($model['username']); ?></a>
                        <div class="author-meta"><span><?php echo date('Y-m-d H:i', strtotime($model['created_at'])); ?></span><span class="title-badge"><?php echo m_e($author_title); ?></span></div>
                    </div>
                </div>
                <div class="software-desc"><?php echo nl2br(m_e($model['description'])); ?></div>
                <?php if (!empty($images)): ?>
                    <div class="inline-shots" aria-label="预览截图">
                        <?php foreach ($images as $img): ?>
                            <a class="cc-lightbox" href="<?php echo m_e($img['url']); ?>"><img src="<?php echo m_e($img['url']); ?>" alt="模型预览图" loading="lazy"></a>
                        <?php endforeach; ?>
                    </div>
                <?php endif; ?>
                <div class="meta-strip">
                    <div class="meta-item"><b id="download-count"><?php echo (int)($model['downloads'] ?? 0); ?></b><span>下载</span></div>
                    <div class="meta-item"><b><?php echo count($files); ?></b><span>文件</span></div>
                    <div class="meta-item"><b id="comment-count"><?php echo count($comments); ?></b><span>评论</span></div>
                </div>
                <div class="download-cta">
                    <?php if ($primaryFile): ?>
                        <button class="main-download" id="scrollFilesBtn" type="button">
                            <svg viewBox="0 0 24 24" class="cc-ic"><path d="M12 4v12m0 0-4-4m4 4 4-4M4 20h16"/></svg>立即下载
                        </button>
                    <?php else: ?>
                        <button class="main-download" disabled>暂无下载文件</button>
                    <?php endif; ?>
                    <button class="ghost-action" id="share-btn" aria-label="分享"><svg viewBox="0 0 24 24" class="cc-ic"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.6 13.5 6.8 4M15.4 6.5l-6.8 4"/></svg></button>
                </div>
                <?php if ($primaryFile): ?><div class="file-count-hint">下方共有 <?php echo count($files); ?> 个下载文件</div><?php endif; ?>
            </div>
        </div>
        <div class="bar">
            <a class="bar-btn" href="index??view=profile&id=<?php echo (int)$model['user_id']; ?>"><svg viewBox="0 0 24 24" class="cc-ic"><path d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z"/><path d="M4 21a8 8 0 0 1 16 0"/></svg>作者主页</a>
            <button class="bar-btn" id="comment-scroll-btn"><svg viewBox="0 0 24 24" class="cc-ic"><path d="M21 12a8 8 0 0 1-11.6 7.1L3 21l1.9-6.4A8 8 0 1 1 21 12Z"/></svg>评论</button>
            <?php if (isset($_SESSION['user_id']) && $_SESSION['user_id'] == $model['user_id']): ?>
                <form method="post" action="delete_model?" onsubmit="return confirm('确定要删除这个模型吗？')"><input type="hidden" name="model_id" value="<?php echo (int)$model_id; ?>"><button class="bar-btn" style="color:#ef4444"><svg viewBox="0 0 24 24" class="cc-ic"><path d="M5 7h14M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2m-7 0v12a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2V7"/></svg>删除</button></form>
            <?php endif; ?>
        </div>
    </article>

    <?php if (!empty($files)): ?>
    <section class="card" style="margin-top:16px" data-reveal id="files-section">
        <?php if (!empty($files)): ?>
            <div class="section">
                <div class="section-title"><svg viewBox="0 0 24 24" class="cc-ic"><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/></svg>附件下载</div>
                <?php if ($isLoggedIn && !$canDownloadModel): ?>
                    <div class="vip-note">全部模型文件为会员专享，会员仅需 1 元/月。开通后即可下载全部模型。</div>
                <?php elseif (!$isLoggedIn): ?>
                    <div class="vip-note">模型下载为会员专享，请先登录后开通会员。作者可下载自己的模型。</div>
                <?php elseif ($isOwner): ?>
                    <div class="vip-note">你是该模型作者，可以下载自己的模型文件。</div>
                <?php endif; ?>
                <div class="files">
                    <?php foreach ($files as $file):
                        $fileSize = isset($file['file_size']) && $file['file_size'] > 0 ? $file['file_size'] : getRemoteFileSize($file['url']);
                        $fileName = $file['name'] ?? basename($file['url']);
                    ?>
                    <div class="file">
                        <div class="file-ico"><svg viewBox="0 0 24 24" class="cc-ic"><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/></svg></div>
                        <div class="file-info"><div class="file-name"><?php echo m_e($fileName); ?><?php if ($file['is_primary'] ?? false): ?><span class="primary">主文件</span><?php endif; ?></div><div class="file-size"><?php echo m_size($fileSize); ?></div></div>
                        <?php if (isLoggedIn() && $canDownloadModel): ?>
                            <button class="download" type="button" data-download="<?php echo (int)$file['id']; ?>" data-is-primary="<?php echo ($file['is_primary'] ?? 0) ? '1' : '0'; ?>"><svg viewBox="0 0 24 24" class="cc-ic" style="width:15px;height:15px"><path d="M12 4v12m0 0-4-4m4 4 4-4M4 20h16"/></svg>下载</button>
                        <?php elseif (isLoggedIn()): ?>
                            <a class="download vip-lock" href="vip?"><svg viewBox="0 0 24 24" class="cc-ic" style="width:15px;height:15px"><path d="m12 2 3 7 7 .7-5.3 4.8 1.6 7-6.3-3.7-6.3 3.7 1.6-7L2 9.7 9 9z"/></svg>会员下载</a>
                        <?php else: ?>
                            <a class="download" href="login??redirect=<?php echo urlencode($_SERVER['REQUEST_URI']); ?>">登录下载</a>
                        <?php endif; ?>
                    </div>
                    <?php endforeach; ?>
                </div>
            </div>
        <?php endif; ?>
    </section>
    <?php endif; ?>

    <section class="card comments" id="comments" data-reveal>
        <div class="comments-head">评论 <span style="color:var(--muted);font-size:12px;font-weight:700">(<span id="comment-count2"><?php echo count($comments); ?></span>)</span></div>
        <div id="comments-list">
            <?php if (empty($comments)): ?><div class="empty" id="no-comments">还没有评论，来抢沙发</div><?php else: ?><?php foreach ($comments as $comment): ccModelComment($comment); endforeach; ?><?php endif; ?>
        </div>
    </section>
</main>

<div class="lb" id="lightbox"><button type="button" aria-label="关闭"><svg viewBox="0 0 24 24" class="cc-ic"><path d="m6 6 12 12M18 6 6 18"/></svg></button><img src="" alt=""></div>

<div class="dock">
    <div class="reply-status" id="reply-status-bar" hidden><span id="reply-status-text"></span><button type="button" id="cancel-reply-btn">取消</button></div>
    <div class="dock-row">
        <?php if (isLoggedIn()): ?>
            <div class="dock-input">
                <textarea id="comment-input" rows="1" maxlength="1000" placeholder="写下你的评论..."></textarea>
                <div class="preview" id="comment-preview" hidden><img src="" id="preview-img" alt=""><button type="button" onclick="removePreview()">×</button></div>
            </div>
            <label class="top-btn" for="comment-image"><svg viewBox="0 0 24 24" class="cc-ic"><rect x="3" y="5" width="18" height="14" rx="3"/><circle cx="9" cy="11" r="2"/><path d="m4 19 5-5 4 4 3-3 4 4"/></svg></label>
            <input type="file" id="comment-image" accept="image/*" hidden>
            <button class="send" id="comment-submit"><svg viewBox="0 0 24 24" class="cc-ic"><path d="M3 11 22 2l-9 19-3-7z"/></svg></button>
        <?php else: ?>
            <a class="cc-btn" style="margin:auto" href="login??redirect=<?php echo urlencode($_SERVER['REQUEST_URI']); ?>">登录后评论</a>
        <?php endif; ?>
    </div>
</div>

<script>
const modelId = <?php echo (int)$model_id; ?>;
const isLoggedIn = <?php echo $isLoggedIn ? 'true' : 'false'; ?>;
let currentReply = {commentId:null, username:null};

document.getElementById('navBackBtn')?.addEventListener('click', e => { e.preventDefault(); if (history.length > 1) history.back(); else location.href = 'index??view=resources'; });
document.getElementById('scrollFilesBtn')?.addEventListener('click', () => {
    const target = document.getElementById('files-section');
    if (target) target.scrollIntoView({behavior:'smooth', block:'start'});
});
function toast(msg,type){const w=document.getElementById('toastWrap');const e=document.createElement('div');e.className='toast '+(type||'');e.textContent=msg;w.appendChild(e);setTimeout(()=>{e.style.opacity='0';e.style.transform='translateY(-8px)'},2200);setTimeout(()=>e.remove(),2600)}
function reveal(){document.querySelectorAll('[data-reveal]').forEach(el=>{if(el.getBoundingClientRect().top<innerHeight-30)el.classList.add('in')})}addEventListener('scroll',reveal,{passive:true});addEventListener('load',reveal);reveal();

document.addEventListener('click', e => { const a=e.target.closest('.cc-lightbox'); if(!a)return; e.preventDefault(); const lb=document.getElementById('lightbox'); lb.querySelector('img').src=a.href; lb.classList.add('open') });
document.getElementById('lightbox')?.addEventListener('click', e => { if(e.target.id==='lightbox'||e.target.closest('button')) e.currentTarget.classList.remove('open') });

document.getElementById('share-btn')?.addEventListener('click', async()=>{const url=location.href;if(navigator.share){try{await navigator.share({title:document.title,url});return}catch(e){}}try{await navigator.clipboard.writeText(url);toast('链接已复制','ok')}catch(e){toast('复制失败','err')}});
document.getElementById('comment-scroll-btn')?.addEventListener('click',()=>{document.getElementById('comments')?.scrollIntoView({behavior:'smooth'});setTimeout(()=>document.getElementById('comment-input')?.focus(),300)});

document.addEventListener('click', async e => {
    const b=e.target.closest('.like-btn'); if(!b||!b.dataset.commentId)return;
    if(!isLoggedIn){toast('请先登录','err');return}
    const fd=new FormData();fd.append('action','like_comment');fd.append('comment_id',b.dataset.commentId);
    try{const r=await fetch(`model??id=${modelId}`,{method:'POST',body:fd,headers:{'X-Requested-With':'XMLHttpRequest'}});const data=await r.json();if(data.success){b.classList.toggle('liked',data.is_liked);b.querySelector('.like-count').textContent=data.like_count}else toast(data.message||'点赞失败','err')}catch(err){toast('网络错误','err')}
});

// 无跳转下载处理
document.addEventListener('click', async e => {
    const btn = e.target.closest('[data-download]');
    if (!btn) return;
    if (!isLoggedIn) { toast('请先登录', 'err'); return; }
    const mediaId = btn.dataset.download;
    const isPrimary = btn.dataset.isPrimary === '1';

    // 先记录下载次数（主文件才记录）
    if (isPrimary) {
        const fd = new FormData();
        fd.append('action', 'record_download');
        fd.append('file_id', mediaId);
        fd.append('is_primary', '1');
        try {
            const r = await fetch(`model??id=${modelId}`, { method: 'POST', body: fd, headers: { 'X-Requested-With': 'XMLHttpRequest' } });
            const data = await r.json();
            if (!data.success) { toast(data.message || '下载记录失败', 'err'); return; }
        } catch (err) { toast('网络错误', 'err'); return; }
    }

    // 用 iframe 下载文件（不跳转页面）
    let iframe = document.getElementById('dl-iframe-' + mediaId);
    if (!iframe) {
        iframe = document.createElement('iframe');
        iframe.id = 'dl-iframe-' + mediaId;
        iframe.style.display = 'none';
        document.body.appendChild(iframe);
    }
    iframe.src = `download_model??media_id=${mediaId}&no_count=1`;
    toast('开始下载...', 'ok');
});

document.addEventListener('click', async e => {
    const del=e.target.closest('.delete-comment-btn'); if(!del)return;
    if(!confirm('确定要删除这条评论吗？'))return;
    const fd=new FormData();fd.append('action','delete_comment');fd.append('comment_id',del.dataset.commentId);
    try{const r=await fetch(`model??id=${modelId}`,{method:'POST',body:fd,headers:{'X-Requested-With':'XMLHttpRequest'}});const data=await r.json();if(data.success){document.getElementById('comment-'+del.dataset.commentId)?.remove();updateCount(data.comment_count);toast('已删除','ok')}else toast(data.message||'删除失败','err')}catch(err){toast('网络错误','err')}
});

document.addEventListener('click', e => {
    const r=e.target.closest('.reply-btn'); if(!r)return;
    if(!isLoggedIn){toast('请先登录','err');return}
    currentReply={commentId:r.dataset.commentId,username:r.dataset.username};
    document.querySelectorAll('.cc-reply-form').forEach(f=>f.hidden=true);
    const f=document.getElementById('reply-form-'+r.dataset.commentId); if(f){f.hidden=false;f.scrollIntoView({behavior:'smooth',block:'center'})}
    const bar=document.getElementById('reply-status-bar');bar.hidden=false;document.getElementById('reply-status-text').textContent='回复 @'+r.dataset.username;
});
document.getElementById('cancel-reply-btn')?.addEventListener('click',()=>{currentReply={commentId:null,username:null};document.getElementById('reply-status-bar').hidden=true;document.querySelectorAll('.cc-reply-form').forEach(f=>f.hidden=true)});

const input=document.getElementById('comment-input');input?.addEventListener('input',function(){this.style.height='auto';this.style.height=Math.min(this.scrollHeight,120)+'px'});
document.getElementById('comment-image')?.addEventListener('change',e=>{const f=e.target.files[0];if(!f)return;const rd=new FileReader();rd.onload=x=>{document.getElementById('preview-img').src=x.target.result;document.getElementById('comment-preview').hidden=false};rd.readAsDataURL(f)});
function removePreview(){const p=document.getElementById('comment-preview'),i=document.getElementById('preview-img'),f=document.getElementById('comment-image');if(p)p.hidden=true;if(i)i.src='';if(f)f.value=''}

async function submitMainComment(){
    const t=document.getElementById('comment-input'); if(!t||!t.value.trim()){toast('评论内容不能为空','err');return}
    const fd=new FormData();fd.append('action','comment');fd.append('content',t.value.trim());if(currentReply.commentId)fd.append('parent_id',currentReply.commentId);const img=document.getElementById('comment-image');if(img?.files[0])fd.append('comment_image',img.files[0]);
    await sendComment(fd,()=>{t.value='';t.style.height='auto';removePreview();document.getElementById('reply-status-bar').hidden=true;currentReply={commentId:null,username:null}})
}
document.getElementById('comment-submit')?.addEventListener('click',submitMainComment);
input?.addEventListener('keydown',e=>{if((e.ctrlKey||e.metaKey)&&e.key==='Enter'){e.preventDefault();submitMainComment()}});
document.addEventListener('submit',async e=>{const f=e.target;if(!f.classList.contains('reply-form'))return;e.preventDefault();const ta=f.querySelector('textarea');if(!ta.value.trim()){toast('回复内容不能为空','err');return}await sendComment(new FormData(f),()=>{ta.value='';f.closest('.cc-reply-form').hidden=true})});
async function sendComment(fd,done){try{const r=await fetch(`model??id=${modelId}`,{method:'POST',body:fd,headers:{'X-Requested-With':'XMLHttpRequest'}});const data=await r.json();if(data.success&&data.comment){addComment(data.comment);updateCount(data.comment_count);done&&done();toast('已发送','ok')}else toast(data.message||'发送失败','err')}catch(err){toast('网络错误','err')}}
function updateCount(n){document.getElementById('comment-count').textContent=n;document.getElementById('comment-count2').textContent=n}
function esc(s){const d=document.createElement('div');d.textContent=s||'';return d.innerHTML}
function addComment(c){document.getElementById('no-comments')?.remove();const el=document.createElement('div');el.className='cc-comment';el.id='comment-'+c.id;let imgs='';if(c.comment_images?.length){imgs='<div class="cc-comment-images">'+c.comment_images.map(u=>`<a class="cc-lightbox" href="${u}"><img src="${u}" alt=""></a>`).join('')+'</div>'}el.innerHTML=`<a class="cc-comment-avatar" href="index??view=profile&id=${c.user_id}"><img src="${c.avatar||'/assets/default_avatar.png'}" alt=""></a><div class="cc-comment-body"><div class="cc-comment-meta"><a class="cc-comment-name" href="index??view=profile&id=${c.user_id}">${esc(c.username)}</a><span>刚刚</span></div><div class="cc-comment-text">${esc(c.content).replace(/\n/g,'<br>')}</div>${imgs}<div class="cc-comment-actions"><button class="cc-act like-btn" data-comment-id="${c.id}"><svg viewBox="0 0 24 24" class="cc-ic"><path d="M12 21s-7.5-4.6-9.5-9.4C1 7.4 4.2 4 7.7 4c2 0 3.4 1 4.3 2.4C13 5 14.4 4 16.4 4c3.5 0 6.7 3.4 5.1 7.6C19.5 16.4 12 21 12 21Z"/></svg><span class="like-count">0</span></button><button class="cc-act reply-btn" data-comment-id="${c.id}" data-username="${esc(c.username)}"><svg viewBox="0 0 24 24" class="cc-ic"><path d="M21 12a8 8 0 0 1-11.6 7.1L3 21l1.9-6.4A8 8 0 1 1 21 12Z"/></svg><span>回复</span></button></div></div>`;document.getElementById('comments-list').prepend(el);requestAnimationFrame(()=>{el.style.opacity='0';el.style.transform='translateY(8px)';el.style.transition='.35s var(--ease)';requestAnimationFrame(()=>{el.style.opacity='1';el.style.transform='none'})})}
</script>
</body>
</html>