/**
 * git/remote.mjs — public-remote detection for the C35 policy gate.
 *
 * Rationale: `apt init` defaults to the `solo` share policy — nothing leaves
 * the user's machine unless they explicitly opt in via /apt:setup or by
 * editing .aperant/config.json. But if the repo already has a public remote
 * (github.com, gitlab.com, bitbucket.org on https or ssh) AND the user later
 * turns on any share.* toggle, files they may have assumed were private will
 * become world-readable.
 *
 * This helper detects the public-host case deterministically so init can emit
 * an advisory `publicRemoteWarning` block and /apt:setup can surface a
 * louder confirmation question. Self-hosted GitLab / Gitea / enterprise
 * GitHub (github.acme.com) report isPublic=false — users on those hosts
 * know their threat model; we only flag the "oops, this is literally the
 * public internet" case.
 *
 * Regex choice:
 *   - https://github.com/, https://gitlab.com/, https://bitbucket.org/
 *   - git@github.com:, git@gitlab.com:, git@bitbucket.org:
 *   - any trailing path (the repo slug) matches — we only care about host.
 *
 * Spec cross-ref: spec.md §6.
 *
 * @internal
 */

import { execFileSync } from 'node:child_process'

/**
 * @typedef {Object} PublicRemoteInfo
 * @property {boolean} isPublic  True when origin points at one of the known
 *                               public-internet hosts.
 * @property {string|null} url   The raw remote URL as git reported it, or
 *                               null if origin is unset / unreachable.
 * @property {string|null} host  The host string when public (e.g. 'github.com'),
 *                               otherwise null.
 */

const PUBLIC_HOSTS = ['github.com', 'gitlab.com', 'bitbucket.org']
const HTTPS_RE = /^https:\/\/(github\.com|gitlab\.com|bitbucket\.org)\//
const SSH_RE = /^git@(github\.com|gitlab\.com|bitbucket\.org):/

/**
 * Detect whether the current repo's `origin` remote points at a public host.
 * Never throws — unreachable / missing / non-git returns a safe fallback.
 *
 * @param {string} targetDir  Project directory.
 * @returns {PublicRemoteInfo}
 *
 * @internal
 */
export function detectPublicRemote(targetDir) {
	let url
	try {
		url = execFileSync('git', ['remote', 'get-url', 'origin'], {
			cwd: targetDir,
			encoding: 'utf-8',
			stdio: ['ignore', 'pipe', 'ignore'],
		}).trim()
	} catch {
		return { isPublic: false, url: null, host: null }
	}

	if (!url) return { isPublic: false, url: null, host: null }

	const httpsMatch = url.match(HTTPS_RE)
	if (httpsMatch) {
		return { isPublic: true, url, host: httpsMatch[1] }
	}
	const sshMatch = url.match(SSH_RE)
	if (sshMatch) {
		return { isPublic: true, url, host: sshMatch[1] }
	}

	// Detect-but-not-flagged: private / self-hosted / SSH to a non-major host.
	// Return the URL for diagnostics but isPublic=false.
	return { isPublic: false, url, host: null }
}

/**
 * Helper: list public-host strings the detector recognizes. Exposed so the
 * setup skill can present the list to users ("we flag github.com, gitlab.com,
 * bitbucket.org").
 *
 * @returns {ReadonlyArray<string>}
 *
 * @internal
 */
export function listKnownPublicHosts() {
	return PUBLIC_HOSTS
}
