/**
 * Open the user's editor to compose feedback text, à la `git commit`.
 *
 * The feedback body is MARKDOWN, so the editor buffer is left completely
 * untouched — no comment/instruction lines are injected or stripped (that would
 * clobber markdown `#` headings). Guidance is printed to the terminal before the
 * editor launches instead. Returns the trimmed body, or null when it is empty
 * (caller treats that as "abort").
 */

import { spawnSync } from 'child_process';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';

/** Resolve the editor command, mirroring git's precedence. */
function resolveEditor(): string {
  return (
    process.env.VISUAL ||
    process.env.EDITOR ||
    (process.platform === 'win32' ? 'notepad' : 'vi')
  );
}

/**
 * Open the editor and return the composed feedback (verbatim, trimmed), or null
 * if empty/aborted. Throws if the editor cannot be launched or exits non-zero.
 */
export function composeInEditor(): string | null {
  const file = path.join(os.tmpdir(), `sungen-feedback-${process.pid}-${Date.now()}.md`);
  fs.writeFileSync(file, '', 'utf8');
  try {
    const editor = resolveEditor();
    console.error('Composing feedback in your editor (markdown supported). Save & close to submit; leave empty to abort.');
    // shell:true so editors with args work (e.g. VISUAL="code --wait").
    const result = spawnSync(`${editor} "${file}"`, { shell: true, stdio: 'inherit' });
    if (result.error) throw new Error(`Could not launch editor "${editor}": ${result.error.message}`);
    if (typeof result.status === 'number' && result.status !== 0) {
      throw new Error(`Editor "${editor}" exited with code ${result.status}.`);
    }
    // Verbatim — only trim outer whitespace so markdown (headings, lists, code
    // fences, HTML comments) is preserved exactly as written.
    const body = fs.readFileSync(file, 'utf8').trim();
    return body.length > 0 ? body : null;
  } finally {
    try { fs.unlinkSync(file); } catch { /* best effort */ }
  }
}
