// engine/operator-identity.js — W-mpejf0fq000e84d6
//
// Resolve the human operator's platform login for branch naming and other
// dispatch-time identity needs. The convention is documented in CLAUDE.md
// ("Branch naming convention") and shared with agents via playbook context.
//
// Resolution chain (first non-empty wins, cached at module scope):
//   1. `config.engine.operatorLogin` — explicit override from the Settings UI
//   2. `gh api user --jq .login`     — works in any GitHub-authed install
//   3. `git config user.email`        localpart (`user@host` → `user`)
//   4. `os.userInfo().username`       — last-resort fallback
//   5. literal string `'unknown'`     — if all four fail
//
// The resolved value is cached in module state. The cache is intentionally
// process-lifetime: `minions restart` re-resolves; the per-tick dispatch hot
// path does not. Test helpers expose cache reset + exec/os.username injection
// so unit tests stay hermetic.

const { execSync } = require('child_process');
const os = require('os');

let _cached = null;

// Test seams. The default impls shell out; tests inject pure functions.
let _execImpl = (cmd) => {
  try {
    return String(execSync(cmd, {
      encoding: 'utf8',
      stdio: ['ignore', 'pipe', 'ignore'],
      timeout: 5000,
    })).trim();
  } catch {
    return '';
  }
};

let _osUsernameOverride = null; // null = call real os.userInfo()

function _osUsername() {
  if (_osUsernameOverride !== null) return _osUsernameOverride;
  try {
    const u = os.userInfo().username;
    return u ? String(u) : '';
  } catch {
    return '';
  }
}

function resolveOperatorLogin(config, { force = false } = {}) {
  if (!force && _cached) return _cached;

  // 1. Explicit override
  const override = config?.engine?.operatorLogin;
  if (override && typeof override === 'string' && override.trim()) {
    _cached = override.trim();
    return _cached;
  }

  // 2. gh CLI
  const ghLogin = _execImpl('gh api user --jq .login');
  if (ghLogin) { _cached = ghLogin; return _cached; }

  // 3. git email localpart
  const email = _execImpl('git config user.email');
  if (email) {
    const local = String(email).split('@')[0].trim();
    if (local) { _cached = local; return _cached; }
  }

  // 4. OS username
  const user = _osUsername();
  if (user) { _cached = user; return _cached; }

  // 5. Last-resort sentinel
  _cached = 'unknown';
  return _cached;
}

// ── Test helpers (not part of the public API) ────────────────────────────────

function _resetOperatorLoginCacheForTest() { _cached = null; }
function _setExecImplForTest(fn) { _execImpl = typeof fn === 'function' ? fn : _execImpl; }
function _resetExecImplForTest() {
  _execImpl = (cmd) => {
    try {
      return String(execSync(cmd, {
        encoding: 'utf8',
        stdio: ['ignore', 'pipe', 'ignore'],
        timeout: 5000,
      })).trim();
    } catch {
      return '';
    }
  };
}
function _setOsUsernameForTest(value) { _osUsernameOverride = value; }

module.exports = {
  resolveOperatorLogin,
  _resetOperatorLoginCacheForTest,
  _setExecImplForTest,
  _resetExecImplForTest,
  _setOsUsernameForTest,
};
