import { MANIFEST_SCHEMA_ID, humanizeResourceType } from "./resource-defaults.js";
import fs from "node:fs";
import path from "node:path";

//#region src/cli/commands/plugin/create/scaffold.ts
/** Convert kebab-name to PascalCase (e.g. my-plugin -> MyPlugin). */
function toPascalCase(name) {
	return name.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase()).join("");
}
/** Convert kebab-name to camelCase (e.g. my-plugin -> myPlugin). */
function toCamelCase(name) {
	const pascal = toPascalCase(name);
	return pascal.charAt(0).toLowerCase() + pascal.slice(1);
}
/** Build manifest.json resources from selected resources. */
function buildManifestResources(answers) {
	const required = [];
	const optional = [];
	for (const r of answers.resources) {
		const alias = humanizeResourceType(r.type);
		const entry = {
			type: r.type,
			alias,
			resourceKey: r.resourceKey,
			description: r.description || `Required for ${alias} functionality.`,
			permission: r.permission,
			fields: r.fields
		};
		if (r.required) required.push(entry);
		else optional.push(entry);
	}
	return {
		required,
		optional
	};
}
/** Build full manifest object for manifest.json. */
function buildManifest(answers) {
	const { required, optional } = buildManifestResources(answers);
	const manifest = {
		$schema: MANIFEST_SCHEMA_ID,
		name: answers.name,
		displayName: answers.displayName,
		description: answers.description,
		resources: {
			required,
			optional
		}
	};
	if (answers.author) manifest.author = answers.author;
	manifest.version = answers.version || "0.1.0";
	if (answers.license) manifest.license = answers.license;
	return manifest;
}
/** Resolve absolute target directory from cwd and answers. */
function resolveTargetDir(cwd, answers) {
	return path.resolve(cwd, answers.targetPath);
}
/** Track files written during scaffolding for rollback on failure. */
function writeTracked(filePath, content, written) {
	fs.writeFileSync(filePath, content);
	written.push(filePath);
}
/** Remove files written during a failed scaffold attempt. */
function rollback(written, targetDir) {
	for (const filePath of written.reverse()) try {
		fs.unlinkSync(filePath);
	} catch {}
	try {
		if (fs.readdirSync(targetDir).length === 0) fs.rmdirSync(targetDir);
	} catch {}
}
/**
* Scaffold plugin files into targetDir. Pure: no interactive I/O.
* Writes manifest.json, manifest.ts, {name}.ts, index.ts; for isolated also package.json, tsconfig.json, README.md.
* On failure, rolls back any files already written.
*/
function scaffoldPlugin(targetDir, answers, options) {
	fs.mkdirSync(targetDir, { recursive: true });
	const written = [];
	try {
		const manifest = buildManifest(answers);
		const className = toPascalCase(answers.name);
		const exportName = toCamelCase(answers.name);
		writeTracked(path.join(targetDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`, written);
		writeTracked(path.join(targetDir, "manifest.ts"), `import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import type { PluginManifest } from "@databricks/appkit";

const __dirname = dirname(fileURLToPath(import.meta.url));

export const manifest = JSON.parse(
  readFileSync(join(__dirname, "manifest.json"), "utf-8"),
) as PluginManifest;
`, written);
		const pluginTs = `import { Plugin, toPlugin, type IAppRouter } from "@databricks/appkit";
import { manifest } from "./manifest.js";

export class ${className} extends Plugin {
  name = "${answers.name}";

  static manifest = manifest;

  injectRoutes(router: IAppRouter): void {
    // Add your routes here, e.g.:
    // this.route(router, {
    //   name: "example",
    //   method: "get",
    //   path: "/",
    //   handler: async (_req, res) => {
    //     res.json({ message: "Hello from ${answers.name}" });
    //   },
    // });
  }
}

export const ${exportName} = toPlugin<
  typeof ${className},
  Record<string, never>,
  "${answers.name}"
>(${className}, "${answers.name}");
`;
		writeTracked(path.join(targetDir, `${answers.name}.ts`), pluginTs, written);
		const indexTs = `export { ${className}, ${exportName} } from "./${answers.name}.js";
`;
		writeTracked(path.join(targetDir, "index.ts"), indexTs, written);
		if (options.isolated) {
			const packageName = answers.name.includes("/") || answers.name.startsWith("@") ? answers.name : `appkit-plugin-${answers.name}`;
			const packageJson = {
				name: packageName,
				version: answers.version || "0.1.0",
				type: "module",
				main: "./dist/index.js",
				types: "./dist/index.d.ts",
				files: ["dist"],
				scripts: {
					build: "tsc",
					typecheck: "tsc --noEmit"
				},
				peerDependencies: { "@databricks/appkit": ">=0.5.0" },
				devDependencies: { typescript: "^5.0.0" }
			};
			writeTracked(path.join(targetDir, "package.json"), `${JSON.stringify(packageJson, null, 2)}\n`, written);
			writeTracked(path.join(targetDir, "tsconfig.json"), `${JSON.stringify({
				compilerOptions: {
					target: "ES2022",
					module: "NodeNext",
					moduleResolution: "NodeNext",
					outDir: "dist",
					rootDir: ".",
					declaration: true,
					strict: true,
					skipLibCheck: true
				},
				include: ["*.ts"],
				exclude: ["node_modules", "dist"]
			}, null, 2)}\n`, written);
			const readme = `# ${answers.displayName}

${answers.description}

## Installation

\`\`\`bash
pnpm add ${packageName} @databricks/appkit
\`\`\`

## Usage

Register the plugin in your AppKit app:

\`\`\`ts
import { createApp } from "@databricks/appkit";
import { ${exportName} } from "${packageName}";

createApp({
  plugins: [
    ${exportName}(),
    // ... other plugins
  ],
}).then((app) => { /* ... */ });
\`\`\`
`;
			writeTracked(path.join(targetDir, "README.md"), readme, written);
		}
	} catch (err) {
		rollback(written, targetDir);
		throw err;
	}
}

//#endregion
export { resolveTargetDir, scaffoldPlugin };
//# sourceMappingURL=scaffold.js.map