/**
 * commands/design-template.mjs — `apt-tools design-template <sub>` (C42).
 *
 * Curated DESIGN.md template library CLI. Four subcommands:
 *
 *   apt-tools design-template list [--library-dir <path>]
 *     → { status, command, count, entries: [{slug,name,description,origin,source}], warnings }
 *
 *   apt-tools design-template show <slug> [--library-dir <path>]
 *     → { status, command, slug, path, design_md, frontmatter, provenance }
 *
 *   apt-tools design-template add <slug> [--project-dir <path>] [--force] [--library-dir <path>]
 *     → { status, command, slug, from, to, overwritten }
 *
 *   apt-tools design-template submit <path> [--as <slug>] [--library-dir <path>] [--force]
 *     → { status, command, slug, copied_to, provenance_path, warnings }
 *
 * Error envelope shape matches design-validate:
 *   { status: 'error', command: 'design-template', error: '<msg>', ... }
 * with exit code 1 on any error path. Custom shape preserved verbatim via
 * the local templateErr() helper that returns { envelope, exitCode: 1 }.
 *
 * Wiring: `bin/apt-tools.mjs` routes the `design-template` case into
 * `cmdDesignTemplate(args[1], args[2], args.slice(3))`.
 */

import {
	addLibraryEntry,
	listLibraryEntries,
	loadLibraryEntry,
	submitLibraryEntry,
} from '../design/template.mjs'
import { parseFlags } from '../util/args.mjs'
import { exitWith, ok } from '../util/result.mjs'

/**
 * Build the design-template custom error envelope. Returns the
 * {envelope, exitCode} tuple wrap() consumes.
 *
 * @param {string} sub
 * @param {string} message
 * @param {Record<string, unknown>} [extras]
 */
function templateErr(sub, message, extras = {}) {
	return exitWith(
		{
			status: 'error',
			command: 'design-template',
			subcommand: sub,
			error: message,
			...extras,
		},
		1,
	)
}

function cmdList(extraArgs) {
	const flags = parseFlags(extraArgs || [])
	const libraryDir = typeof flags.get('library-dir') === 'string' ? flags.get('library-dir') : null
	const { entries, warnings } = listLibraryEntries({ libraryDir })
	return ok({
		status: 'ok',
		command: 'design-template',
		subcommand: 'list',
		count: entries.length,
		entries,
		warnings,
	})
}

function cmdShow(slug, extraArgs) {
	if (!slug || typeof slug !== 'string' || slug.startsWith('--')) {
		return templateErr(
			'show',
			'Usage: apt-tools design-template show <slug> [--library-dir <path>]',
		)
	}
	const flags = parseFlags(extraArgs || [])
	const libraryDir = typeof flags.get('library-dir') === 'string' ? flags.get('library-dir') : null
	try {
		const entry = loadLibraryEntry({ libraryDir, slug })
		return ok({
			status: 'ok',
			command: 'design-template',
			subcommand: 'show',
			slug: entry.slug,
			path: entry.path,
			design_md: entry.design_md,
			frontmatter: entry.frontmatter,
			provenance: entry.provenance,
		})
	} catch (e) {
		const msg = e instanceof Error ? e.message : String(e)
		return templateErr('show', msg, { slug })
	}
}

function cmdAdd(slug, extraArgs) {
	if (!slug || typeof slug !== 'string' || slug.startsWith('--')) {
		return templateErr(
			'add',
			'Usage: apt-tools design-template add <slug> [--project-dir <path>] [--force] [--library-dir <path>]',
		)
	}
	const flags = parseFlags(extraArgs || [])
	const libraryDir = typeof flags.get('library-dir') === 'string' ? flags.get('library-dir') : null
	const projectDirFlag = flags.get('project-dir')
	const projectDir = typeof projectDirFlag === 'string' ? projectDirFlag : process.cwd()
	const force = flags.get('force') === true || flags.get('force') === 'true'
	try {
		const result = addLibraryEntry({ libraryDir, slug, projectDir, force })
		return ok({
			status: 'ok',
			command: 'design-template',
			subcommand: 'add',
			slug: result.slug,
			from: result.from,
			to: result.to,
			overwritten: result.overwritten,
		})
	} catch (e) {
		const msg = e instanceof Error ? e.message : String(e)
		// @ts-expect-error — code attached by template.mjs
		const code = e && e.code ? e.code : null
		return templateErr('add', msg, { slug, code })
	}
}

function cmdSubmit(candidatePath, extraArgs) {
	if (!candidatePath || typeof candidatePath !== 'string' || candidatePath.startsWith('--')) {
		return templateErr(
			'submit',
			'Usage: apt-tools design-template submit <path-to-DESIGN.md> [--as <slug>] [--library-dir <path>] [--force]',
		)
	}
	const flags = parseFlags(extraArgs || [])
	const libraryDir = typeof flags.get('library-dir') === 'string' ? flags.get('library-dir') : null
	const asFlag = flags.get('as')
	const slug = typeof asFlag === 'string' && asFlag.length > 0 ? asFlag : undefined
	const force = flags.get('force') === true || flags.get('force') === 'true'
	try {
		const result = submitLibraryEntry({ libraryDir, slug, candidatePath, force })
		return ok({
			status: 'ok',
			command: 'design-template',
			subcommand: 'submit',
			slug: result.slug,
			copied_to: result.copied_to,
			provenance_path: result.provenance_path,
			warnings: result.warnings,
		})
	} catch (e) {
		const msg = e instanceof Error ? e.message : String(e)
		// @ts-expect-error — code attached by template.mjs
		const code = e && e.code ? e.code : null
		// @ts-expect-error — validation attached by template.mjs on EINVALID_CANDIDATE
		const validation = e && e.validation ? e.validation : null
		const extras = { code }
		if (validation && Array.isArray(validation.errors)) {
			extras.validation_errors = validation.errors
		}
		if (validation && Array.isArray(validation.warnings)) {
			extras.validation_warnings = validation.warnings
		}
		return templateErr('submit', msg, extras)
	}
}

/**
 * Entry point for the `design-template` CLI dispatch. The parent bin/apt-tools.mjs
 * always calls into here — no per-subcommand routing in the dispatcher.
 *
 * @param {string | undefined} subcommand
 * @param {string | undefined} arg1
 * @param {string[] | undefined} extraArgs
 */
export function cmdDesignTemplate(subcommand, arg1, extraArgs) {
	if (!subcommand || typeof subcommand !== 'string') {
		return templateErr('(none)', 'Usage: apt-tools design-template <list|show|add|submit> [args]')
	}
	switch (subcommand) {
		case 'list':
			return cmdList([arg1, ...(extraArgs || [])].filter((v) => v !== undefined))
		case 'show':
			return cmdShow(arg1, extraArgs)
		case 'add':
			return cmdAdd(arg1, extraArgs)
		case 'submit':
			return cmdSubmit(arg1, extraArgs)
		default:
			return templateErr(
				subcommand,
				`Unknown design-template subcommand: ${subcommand}. Expected: list | show | add | submit.`,
			)
	}
}
