/**
 * Build the WeChat upload "项目备注" from recent change summaries.
 * Prefer recent git commit subjects (Chinese commit messages in this repo);
 * fall back to the latest CHANGELOG bullets when git history is unavailable.
 */

const fs = require("node:fs");
const path = require("node:path");
const { execFileSync } = require("node:child_process");

const DEFAULT_MAX_LENGTH = 100;

function cleanCommitSubject(subject) {
  return String(subject || "")
    .trim()
    .replace(
      /^(feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert)(\([^)]*\))?:\s*/i,
      "",
    )
    .replace(/\s+/g, " ")
    .trim();
}

function truncateDesc(text, maxLength = DEFAULT_MAX_LENGTH) {
  const value = String(text || "").trim();
  if (!value) {
    return "";
  }
  if ([...value].length <= maxLength) {
    return value;
  }
  const chars = [...value].slice(0, Math.max(0, maxLength - 1));
  return `${chars.join("")}…`;
}

function collectRecentCommitSubjects(repoRoot, limit = 5) {
  try {
    const output = execFileSync(
      "git",
      [
        "log",
        `-${Math.max(1, limit * 3)}`,
        "--pretty=%s",
        "--",
        "mini/",
        "CHANGELOG.md",
        "Features.md",
      ],
      {
        cwd: repoRoot,
        encoding: "utf8",
        stdio: ["ignore", "pipe", "ignore"],
      },
    );

    const subjects = [];
    const seen = new Set();
    for (const line of output.split("\n")) {
      const cleaned = cleanCommitSubject(line);
      if (!cleaned || seen.has(cleaned)) {
        continue;
      }
      // Skip pure docs/chore noise when better subjects exist.
      if (/^(说明|文档|记录)/.test(cleaned) && subjects.length > 0) {
        continue;
      }
      seen.add(cleaned);
      subjects.push(cleaned);
      if (subjects.length >= limit) {
        break;
      }
    }
    return subjects;
  } catch {
    return [];
  }
}

function collectRecentChangelogBullets(repoRoot, limit = 5) {
  const changelogPath = path.join(repoRoot, "CHANGELOG.md");
  if (!fs.existsSync(changelogPath)) {
    return [];
  }

  const lines = fs.readFileSync(changelogPath, "utf8").split(/\r?\n/);
  const bullets = [];
  const seen = new Set();

  for (const line of lines) {
    const match = line.match(/^\s*-\s+(.+)\s*$/);
    if (!match) {
      continue;
    }
    const bullet = match[1].replace(/\s+/g, " ").trim();
    if (!bullet || seen.has(bullet)) {
      continue;
    }
    seen.add(bullet);
    bullets.push(bullet);
    if (bullets.length >= limit) {
      break;
    }
  }

  return bullets;
}

function resolveUploadDesc({
  repoRoot,
  versionLabel = "",
  maxLength = DEFAULT_MAX_LENGTH,
  maxItems = 3,
} = {}) {
  const root = repoRoot || process.cwd();
  const fromGit = collectRecentCommitSubjects(root, maxItems);
  const fromChangelog = collectRecentChangelogBullets(root, maxItems);
  const parts = fromGit.length > 0 ? fromGit : fromChangelog;

  if (parts.length === 0) {
    const shortSha = String(versionLabel || "")
      .trim()
      .slice(0, 7);
    return truncateDesc(
      shortSha ? `CI upload ${shortSha}` : "CI upload",
      maxLength,
    );
  }

  // Fit as many summaries as possible within the WeChat remark limit.
  const selected = [];
  for (const part of parts) {
    const candidate = [...selected, part].join("；");
    if ([...candidate].length > maxLength) {
      if (selected.length === 0) {
        return truncateDesc(part, maxLength);
      }
      break;
    }
    selected.push(part);
  }

  return truncateDesc(selected.join("；"), maxLength);
}

module.exports = {
  cleanCommitSubject,
  collectRecentChangelogBullets,
  collectRecentCommitSubjects,
  resolveUploadDesc,
  truncateDesc,
};
