#!/usr/bin/env node
/**
 * Enrich plaza post pages with polished HTML + update summaries.
 * Then run: pnpm sync:plaza-prod -- --include-offline
 */
import crypto from 'node:crypto';
import fs from 'node:fs/promises';
import fsSync from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { createDbPool } from '../db.mjs';
import { getEnrichment } from './plaza-rich-content.mjs';

const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
const storageRoot = path.resolve(process.env.MINDSPACE_STORAGE_ROOT ?? path.join(root, 'data', 'mindspace'));

function loadEnvFile(filePath) {
  if (!fsSync.existsSync(filePath)) return;
  for (const line of fsSync.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'));

function absStorageKey(storageKey) {
  const resolved = path.resolve(storageRoot, storageKey);
  if (resolved !== storageRoot && !resolved.startsWith(`${storageRoot}${path.sep}`)) {
    throw new Error(`非法 storage_key: ${storageKey}`);
  }
  return resolved;
}

async function ensureBundle(conn, row, html) {
  const now = Date.now();
  const checksum = crypto.createHash('sha256').update(html).digest('hex');
  const sizeBytes = Buffer.byteLength(html, 'utf8');
  const storageKey = `users/${row.user_id}/publications/${row.publication_id}/index.html`;
  const filePath = absStorageKey(storageKey);
  await fs.mkdir(path.dirname(filePath), { recursive: true });
  await fs.writeFile(filePath, html, 'utf8');

  let bundleAssetId = row.bundle_asset_id;
  let assetVersionId = row.bundle_version_id;

  if (!bundleAssetId) {
    bundleAssetId = crypto.randomUUID();
    assetVersionId = crypto.randomUUID();
    await conn.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, risk_level, visibility,
        status, source_type, created_at, updated_at)
       VALUES (?, ?, ?, ?, 'html', 'text/html', 'index.html', ?, ?, ?, ?, 'none',
               'public_candidate', 'ready', 'generated', ?, ?)`,
      [
        bundleAssetId,
        row.user_id,
        row.space_id,
        row.category_id,
        `${row.title} · 发布快照`,
        assetVersionId,
        sizeBytes,
        checksum,
        now,
        now,
      ],
    );
    await conn.query(
      `INSERT INTO h5_asset_versions
       (id, asset_id, version_no, storage_key, size_bytes, checksum, mime_type,
        created_by, change_note, scan_status, created_at)
       VALUES (?, ?, 1, ?, ?, ?, 'text/html', ?, '广场内容完善', 'passed', ?)`,
      [assetVersionId, bundleAssetId, storageKey, sizeBytes, checksum, row.user_id, now],
    );
    await conn.query(`UPDATE h5_page_versions SET bundle_asset_id = ? WHERE id = ?`, [
      bundleAssetId,
      row.page_version_id,
    ]);
  } else {
    await conn.query(
      `UPDATE h5_asset_versions
       SET storage_key = ?, size_bytes = ?, checksum = ?, scan_status = 'passed'
       WHERE asset_id = ? AND version_no = 1`,
      [storageKey, sizeBytes, checksum, bundleAssetId],
    );
    await conn.query(
      `UPDATE h5_assets SET size_bytes = ?, checksum = ?, updated_at = ? WHERE id = ?`,
      [sizeBytes, checksum, now, bundleAssetId],
    );
  }

  return { storageKey, checksum, sizeBytes };
}

async function main() {
  const pool = createDbPool();
  const [rows] = await pool.query(
    `SELECT pp.id AS post_id, pp.title,
            pr.id AS publication_id, pr.page_id, pr.page_version_id, pr.user_id, pr.status AS pub_status,
            p.space_id, p.category_id, p.title AS page_title,
            pv.bundle_asset_id,
            (SELECT av.id FROM h5_asset_versions av
             WHERE av.asset_id = pv.bundle_asset_id AND av.version_no = 1 LIMIT 1) AS bundle_version_id
     FROM plaza_posts pp
     JOIN h5_publish_records pr ON pr.id = pp.publication_id
     JOIN h5_page_records p ON p.id = pr.page_id
     JOIN h5_page_versions pv ON pv.id = pr.page_version_id
     WHERE pp.status = 'published'
     ORDER BY pp.hot_score DESC`,
  );

  const conn = await pool.getConnection();
  let updated = 0;
  try {
    await conn.beginTransaction();
    for (const row of rows) {
      const { summary, html, skipHtml } = getEnrichment(row.post_id, row.title);
      const summaryOnly = skipHtml && row.bundle_asset_id;
      if (!summaryOnly) {
        await ensureBundle(conn, row, html);
      }
      await conn.query(
        `UPDATE plaza_posts SET summary = ?, updated_at = ? WHERE id = ?`,
        [summary.slice(0, 500), Date.now(), row.post_id],
      );
      await conn.query(
        `UPDATE h5_page_records SET title = ?, summary = ?, updated_at = ? WHERE id = ?`,
        [row.title, summary.slice(0, 1000), Date.now(), row.page_id],
      );
      if (row.pub_status !== 'online') {
        await conn.query(
          `UPDATE h5_publish_records SET status = 'online', offline_at = NULL, updated_at = ? WHERE id = ?`,
          [Date.now(), row.publication_id],
        );
      }
      if (row.post_id === '4c1bf255-d7fd-4065-9044-d347579f85e4') {
        await conn.query(`UPDATE plaza_posts SET title = ?, updated_at = ? WHERE id = ?`, [
          'MindSpace 公开发布指南',
          Date.now(),
          row.post_id,
        ]);
      }
      updated += 1;
      console.log(`✓ ${row.title}`);
    }
    await conn.commit();
  } catch (error) {
    await conn.rollback();
    throw error;
  } finally {
    conn.release();
    await pool.end();
  }

  console.log(`\n完成：已完善 ${updated} 张卡片的内容与摘要。`);
  console.log('同步到线上：pnpm sync:plaza-prod -- --include-offline');
}

main().catch((error) => {
  console.error(error instanceof Error ? error.stack : error);
  process.exit(1);
});
