#!/usr/bin/env node
const { spawnSync } = require('node:child_process')
const { copyFileSync, linkSync, unlinkSync, chmodSync, statSync, readFileSync, writeFileSync } = require('node:fs')
const { arch } = require('node:os')
const path = require('node:path')

const WRAPPER_NAME = require('./package.json').name
const PLATFORMS = {
	'darwin-arm64': { pkg: '@ampcode/cli-darwin-arm64', bin: 'amp' },
	'darwin-x64': { pkg: '@ampcode/cli-darwin-x64', bin: 'amp' },
	'linux-arm64': { pkg: '@ampcode/cli-linux-arm64', bin: 'amp' },
	'linux-x64': { pkg: '@ampcode/cli-linux-x64', bin: 'amp' },
	'win32-x64': { pkg: '@ampcode/cli-win32-x64', bin: 'amp.exe' },
}

function printHelp() {
	console.error('  For help, visit https://ampcode.com/manual or email amp-devs@ampcode.com.')
}

function detectMusl() {
	if (process.platform !== 'linux') {
		return false
	}
	const report = typeof process.report?.getReport === 'function' ? process.report.getReport() : null
	return report != null && report.header?.glibcVersionRuntime === undefined
}

function getPlatformKey() {
	let cpu = arch()
	if (process.platform === 'linux') {
		return 'linux-' + cpu + (detectMusl() ? '-musl' : '')
	}
	if (process.platform === 'darwin' && cpu === 'x64') {
		const result = spawnSync('sysctl', ['-n', 'sysctl.proc_translated'], { encoding: 'utf8' })
		if (result.stdout?.trim() === '1') {
			cpu = 'arm64'
		}
	}
	return process.platform + '-' + cpu
}

function placeBinary(src, dest) {
	try {
		linkSync(src, dest)
	} catch (error) {
		if (error.code === 'EEXIST') {
			const stub = statSync(dest).size < 4096 ? readFileSync(dest) : null
			unlinkSync(dest)
			try {
				linkSync(src, dest)
			} catch {
				try {
					copyFileSync(src, dest)
				} catch (copyError) {
					if (stub) {
						try {
							writeFileSync(dest, stub, { mode: 0o755 })
						} catch {}
					}
					throw copyError
				}
			}
		} else if (error.code === 'EXDEV' || error.code === 'EPERM') {
			copyFileSync(src, dest)
		} else {
			throw error
		}
	}
	if (process.platform !== 'win32') {
		chmodSync(dest, 0o755)
	}
}

function main() {
	const platformKey = getPlatformKey()
	const info = PLATFORMS[platformKey]
	if (!info) {
		console.error(`[${WRAPPER_NAME} postinstall] Unsupported platform: ${process.platform} ${arch()}`)
		console.error(`  Supported: ${Object.keys(PLATFORMS).join(', ')}`)
		printHelp()
		return
	}

	let src
	try {
		const pkgDir = path.dirname(require.resolve(info.pkg + '/package.json'))
		src = path.join(pkgDir, info.bin)
	} catch {
		console.error(`[${WRAPPER_NAME} postinstall] Native package "${info.pkg}" not found.`)
		console.error('  This happens with --omit=optional or when the download failed.')
		console.error('  Fallback: node ' + path.join(__dirname, 'cli-wrapper.cjs'))
		printHelp()
		return
	}

	try {
		placeBinary(src, path.join(__dirname, 'bin', 'amp.exe'))
	} catch (error) {
		console.error(`[${WRAPPER_NAME} postinstall] Failed to place binary: ${error.message}`)
		console.error('  Fallback: node ' + path.join(__dirname, 'cli-wrapper.cjs'))
		printHelp()
		process.exitCode = 1
	}
}

main()
