#!/usr/bin/env node
import crypto from 'node:crypto';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { createDbPool, initSchema } from '../db.mjs';
import { createPlazaPostService } from '../plaza-posts.mjs';
import { initializeDefaultSpace } from '../mindspace.mjs';

const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');

function loadEnvFile(filePath) {
  if (!fs.existsSync(filePath)) return;
  for (const line of fs.readFileSync(filePath, 'utf8').split('\n')) {
    const trimmed = line.trim();
    if (!trimmed || trimmed.startsWith('#')) continue;
    const eq = trimmed.indexOf('=');
    if (eq < 0) continue;
    const key = trimmed.slice(0, eq).trim();
    const value = trimmed.slice(eq + 1).trim();
    if (!process.env[key]) process.env[key] = value;
  }
}

loadEnvFile(path.join(root, '../../.env.local'));
loadEnvFile(path.join(root, '.env'));

const DEMO_POSTS = [
  {
    category: 'work-report',
    title: 'Q2 产品增长复盘：从 0 到 10 万 DAU',
    summary: '拆解增长漏斗、渠道投放 ROI 与留存曲线，附可复用的周报模板。',
    tags: ['增长', '复盘', '产品'],
    likes: 128,
    comments: 24,
    views: 3200,
    author: 'john',
  },
  {
    category: 'work-report',
    title: 'AI 客服落地 30 天执行报告',
    summary: '从需求澄清、知识库搭建到上线监控，记录真实踩坑与指标变化。',
    tags: ['AI', '客服', '落地'],
    likes: 86,
    comments: 11,
    views: 1840,
    author: 'john',
  },
  {
    category: 'work-report',
    title: '供应链数字化周报 · 第 18 期',
    summary: '库存周转、缺货预警与供应商协同进展，适合制造业团队参考。',
    tags: ['供应链', '周报'],
    likes: 45,
    comments: 6,
    views: 920,
    author: 'admin',
  },
  {
    category: 'study-notes',
    title: 'Rust 所有权模型 15 分钟图解',
    summary: '用生活类比讲清 borrow / move / lifetime，附练习题与答案。',
    tags: ['Rust', '编程', '笔记'],
    likes: 203,
    comments: 37,
    views: 5100,
    author: 'john',
  },
  {
    category: 'study-notes',
    title: 'LLM Prompt 工程速查表',
    summary: '角色设定、Few-shot、CoT、结构化输出，一张表搞定常见场景。',
    tags: ['Prompt', 'LLM'],
    likes: 312,
    comments: 58,
    views: 8900,
    author: 'john',
  },
  {
    category: 'creative',
    title: '赛博水墨城市概念海报',
    summary: 'MindSpace 生成的东方未来主义视觉，适合活动主 KV 参考。',
    tags: ['设计', '海报', 'AI绘画'],
    likes: 167,
    comments: 19,
    views: 4200,
    author: 'john',
  },
  {
    category: 'creative',
    title: '独立音乐人首张 EP 视觉方案',
    summary: '封面、社媒九宫格与演出海报的统一视觉语言。',
    tags: ['音乐', '品牌'],
    likes: 74,
    comments: 9,
    views: 1600,
    author: 'admin',
  },
  {
    category: 'business',
    title: '社区咖啡店开业 7 天运营手记',
    summary: '选址理由、爆款 SKU、会员拉新与坪效测算一页看懂。',
    tags: ['咖啡', '开店'],
    likes: 96,
    comments: 15,
    views: 2400,
    author: 'john',
  },
  {
    category: 'business',
    title: '普拉提工作室 618 活动页',
    summary: '课程包组合、限时优惠与预约转化话术，可直接复用结构。',
    tags: ['健身', '618'],
    likes: 58,
    comments: 7,
    views: 1300,
    author: 'john',
  },
  {
    category: 'travel',
    title: '马来西亚 5 日轻量旅行攻略',
    summary: '吉隆坡 + 槟城路线、美食清单与预算表，适合周末出发。',
    tags: ['马来西亚', '攻略'],
    likes: 241,
    comments: 42,
    views: 7600,
    author: 'john',
  },
  {
    category: 'travel',
    title: '京都红叶季小众散步地图',
    summary: '避开人潮的 8 条街道与 3 家深夜食堂，附交通换乘。',
    tags: ['日本', '红叶'],
    likes: 189,
    comments: 31,
    views: 5400,
    author: 'admin',
  },
  {
    category: 'data-analysis',
    title: '电商大促 GMV 归因看板',
    summary: '渠道、品类、客单三层下钻，附 SQL 与可视化截图说明。',
    tags: ['电商', 'BI'],
    likes: 112,
    comments: 18,
    views: 2900,
    author: 'john',
  },
  {
    category: 'data-analysis',
    title: '用户留存 Cohort 分析模板',
    summary: '按注册周看 D1/D7/D30 留存，含异常波动排查 checklist。',
    tags: ['留存', '分析'],
    likes: 77,
    comments: 12,
    views: 2100,
    author: 'john',
  },
  {
    category: 'lifestyle',
    title: '极简桌面改造：提升专注的 12 个细节',
    summary: '线缆收纳、光照、显示器高度与数字断舍离清单。',
    tags: ['桌面', '效率'],
    likes: 134,
    comments: 21,
    views: 3600,
    author: 'john',
  },
  {
    category: 'lifestyle',
    title: '晨间写作 21 天挑战记录',
    summary: '每天 20 分钟自由书写，记录情绪变化与可执行习惯。',
    tags: ['写作', '习惯'],
    likes: 63,
    comments: 14,
    views: 1500,
    author: 'admin',
  },
  {
    category: 'other',
    title: '给未来的自己：2026 愿望清单',
    summary: '学习、健康、关系与创作四个维度的年度目标墙。',
    tags: ['年度规划'],
    likes: 39,
    comments: 8,
    views: 980,
    author: 'john',
  },
  {
    category: 'other',
    title: '开源副业项目冷启动笔记',
    summary: '从 0 Star 到首批付费用户的 6 个关键动作。',
    tags: ['开源', '副业'],
    likes: 91,
    comments: 16,
    views: 2200,
    author: 'john',
  },
];

async function loadUser(pool, username) {
  const [rows] = await pool.query(
    `SELECT id, username, slug, display_name FROM h5_users WHERE username = ? LIMIT 1`,
    [username],
  );
  return rows[0] ?? null;
}

async function ensureUserSpace(pool, userId) {
  const [[space]] = await pool.query(
    `SELECT id FROM h5_user_spaces WHERE user_id = ? LIMIT 1`,
    [userId],
  );
  if (space?.id) return;
  await initializeDefaultSpace(pool, userId);
}

async function createDemoPublication(pool, userId, demo, index) {
  const now = Date.now() - index * 3_600_000;
  const publicationId = crypto.randomUUID();
  const pageId = crypto.randomUUID();
  const pageVersionId = crypto.randomUUID();
  const contentAssetId = crypto.randomUUID();
  const assetVersionId = crypto.randomUUID();
  const scanId = crypto.randomUUID();
  const slug = `demo-${demo.category}-${index}-${publicationId.slice(0, 6)}`;

  const [[space]] = await pool.query(
    `SELECT id FROM h5_user_spaces WHERE user_id = ? LIMIT 1`,
    [userId],
  );
  const [[category]] = await pool.query(
    `SELECT id FROM h5_space_categories WHERE user_id = ? AND category_code = 'draft' LIMIT 1`,
    [userId],
  );
  if (!space?.id || !category?.id) throw new Error(`用户 ${userId} 缺少空间或分类`);

  const [[user]] = await pool.query(`SELECT slug, username FROM h5_users WHERE id = ? LIMIT 1`, [userId]);
  const ownerSlug = user?.slug || user?.username || 'user';
  const publicUrl = `/u/${ownerSlug}/pages/${slug}`;

  await pool.query(
    `INSERT INTO h5_assets
     (id, user_id, space_id, category_id, asset_type, mime_type, original_filename, display_name,
      current_version_id, size_bytes, checksum, visibility, status, source_type, created_at, updated_at)
     VALUES (?, ?, ?, ?, 'content', 'text/markdown', 'page.md', ?, ?, 128, ?, 'private', 'ready', 'upload', ?, ?)`,
    [contentAssetId, userId, space.id, category.id, demo.title, assetVersionId, 'demo-seed', now, now],
  );
  await pool.query(
    `INSERT INTO h5_asset_versions
     (id, asset_id, version_no, storage_key, size_bytes, checksum, mime_type, created_by, created_at)
     VALUES (?, ?, 1, ?, 128, ?, 'text/markdown', ?, ?)`,
    [assetVersionId, contentAssetId, `users/${userId}/assets/${contentAssetId}/v1`, 'demo-seed', userId, now],
  );
  await pool.query(
    `INSERT INTO h5_page_records
     (id, user_id, space_id, category_id, title, summary, page_type, template_id, status, visibility, created_at, updated_at)
     VALUES (?, ?, ?, ?, ?, ?, 'article', 'editorial', 'published', 'public', ?, ?)`,
    [pageId, userId, space.id, category.id, demo.title, demo.summary, now, now],
  );
  await pool.query(
    `INSERT INTO h5_security_scans
     (id, user_id, target_type, target_id, scanner_version, status, risk_level, findings_count, started_at, completed_at)
     VALUES (?, ?, 'page_version', ?, 'seed', 'passed', 'none', 0, ?, ?)`,
    [scanId, userId, pageVersionId, now, now],
  );
  await pool.query(
    `INSERT INTO h5_page_versions
     (id, page_id, version_no, content_asset_id, created_by, immutable, created_at)
     VALUES (?, ?, 1, ?, ?, 1, ?)`,
    [pageVersionId, pageId, contentAssetId, userId, now],
  );
  await pool.query(
    `UPDATE h5_page_records SET current_version_id = ?, updated_at = ? WHERE id = ?`,
    [pageVersionId, now, pageId],
  );
  await pool.query(
    `INSERT INTO h5_publish_records
     (id, user_id, page_id, page_version_id, url_slug, public_url, access_mode, published_at, status,
      view_count, security_scan_id, created_at, updated_at)
     VALUES (?, ?, ?, ?, ?, ?, 'public', ?, 'online', 0, ?, ?, ?)`,
    [publicationId, userId, pageId, pageVersionId, slug, publicUrl, now, scanId, now, now],
  );

  return { publicationId, publicUrl };
}

async function bumpPostStats(pool, postId, demo) {
  await pool.query(
    `UPDATE plaza_posts
     SET view_count = ?, like_count = ?, comment_count = ?, hot_score = ?, hot_updated_at = ?, updated_at = ?
     WHERE id = ?`,
    [demo.views, demo.likes, demo.comments, demo.likes * 3 + demo.comments * 5, Date.now(), Date.now(), postId],
  );
}

const pool = createDbPool();
await initSchema(pool);
await createPlazaPostService(pool).ensureCategories();

const users = {};
for (const name of ['john', 'admin']) {
  const user = await loadUser(pool, name);
  if (!user) {
    console.warn(`跳过：用户 ${name} 不存在`);
    continue;
  }
  await ensureUserSpace(pool, user.id);
  users[name] = user;
}

const plazaPosts = createPlazaPostService(pool);
let created = 0;
let skipped = 0;

for (const [index, demo] of DEMO_POSTS.entries()) {
  const user = users[demo.author] ?? users.john;
  if (!user) continue;

  const { publicationId } = await createDemoPublication(pool, user.id, demo, index);
  try {
    const post = await plazaPosts.createPost(user.id, {
      publication_id: publicationId,
      category_slug: demo.category,
      tags: demo.tags,
      allow_comment: true,
    });
    await plazaPosts.reviewPost(post.id, 'approve');
    await bumpPostStats(pool, post.id, demo);
    created += 1;
    console.log(`✓ [${demo.category}] ${demo.title}`);
  } catch (error) {
    if (error?.code === 'ALREADY_PUBLISHED') {
      skipped += 1;
      continue;
    }
    throw error;
  }
}

const [pendingRows] = await pool.query(
  `SELECT id FROM plaza_posts WHERE status = 'pending_review'`,
);
if (pendingRows.length > 0) {
  for (const row of pendingRows) {
    await plazaPosts.reviewPost(row.id, 'approve');
  }
  console.log(`✓ 已通过 ${pendingRows.length} 条待审核帖子`);
}

await pool.end();
console.log(`\n完成：新增 ${created} 条演示帖，跳过 ${skipped} 条。`);
console.log('刷新查看：http://localhost:3001/plaza');
console.log('职场报告：http://localhost:3001/plaza/cat/work-report');
