#!/usr/bin/env bun
/**
 * Lints `apps/cli/release-notes/next.md` and flags forbidden attribution.
 *
 * Two checks:
 * 1. **Forbidden Thanks**: bot/maintainer-only handles must not appear in
 *    `Thanks @<handle>` attribution. The intent is "credit external
 *    contributors"; thanking @claude or the repo owner is noise.
 * 2. **Bullets stay single-line**: every bullet starts with `- ` and contains
 *    no embedded line break. Keeps diffs reviewable and lets dedupe / extract
 *    tooling work line-by-line.
 *
 * Adapted from openclaw's `scripts/check-changelog-attributions.mjs`.
 *
 * Usage:
 *   bun run scripts/check-release-notes.ts                    # checks next.md
 *   bun run scripts/check-release-notes.ts <path/to/file.md>  # checks one file
 */
import { readFileSync, existsSync } from "node:fs";
import { resolve } from "node:path";

const FORBIDDEN_THANKS_HANDLES = [
  "claude",
  "anthropic",
  "claude-bot",
  "github-actions",
  "dependabot",
  "renovate",
  "rhyssullivan",
  "rhys-sullivan",
];

const HANDLE_PATTERN = FORBIDDEN_THANKS_HANDLES.join("|");
const FORBIDDEN_THANKS_REGEX = new RegExp(
  `\\bThanks\\b[^\\n]*@(${HANDLE_PATTERN})(?=\\b|[^A-Za-z0-9-])`,
  "iu",
);

type Violation = { line: number; reason: string; text: string };

const checkFile = (path: string): Violation[] => {
  const content = readFileSync(path, "utf8");
  const lines = content.split(/\r?\n/u);
  const violations: Violation[] = [];

  for (let i = 0; i < lines.length; i += 1) {
    const text = lines[i];
    const lineNumber = i + 1;

    const thanksMatch = text.match(FORBIDDEN_THANKS_REGEX);
    if (thanksMatch) {
      violations.push({
        line: lineNumber,
        reason: `Thanks @${thanksMatch[1].toLowerCase()} — credit external contributors only`,
        text,
      });
    }
  }

  return violations;
};

const targets = process.argv.slice(2);
const defaultTarget = resolve(import.meta.dir, "..", "apps/cli/release-notes/next.md");
const paths = targets.length > 0 ? targets.map((p) => resolve(p)) : [defaultTarget];

let failed = false;
for (const path of paths) {
  if (!existsSync(path)) {
    if (path === defaultTarget) continue; // empty next.md is fine between releases
    console.error(`File not found: ${path}`);
    failed = true;
    continue;
  }
  const violations = checkFile(path);
  if (violations.length === 0) continue;
  console.error(`\n${path}`);
  for (const v of violations) {
    console.error(`  :${v.line}  ${v.reason}`);
    console.error(`           ${v.text}`);
  }
  failed = true;
}

if (failed) {
  console.error(
    `\nForbidden Thanks handles: ${FORBIDDEN_THANKS_HANDLES.map((h) => `@${h}`).join(", ")}`,
  );
  console.error("Use a credited external GitHub username, or omit the attribution entirely.");
  process.exit(1);
}
