#!/usr/bin/env node

// Check Node.js version FIRST, before loading any modules
const MIN_NODE_VERSION = 20
const currentNodeVersion = process.versions.node
const majorVersion = parseInt(currentNodeVersion.split('.')[0], 10)

if (majorVersion < MIN_NODE_VERSION) {
  console.error(`Error: BILD CLI requires Node.js version ${MIN_NODE_VERSION} or higher.`)
  console.error(`Current version: ${currentNodeVersion}`)
  console.error(`Please upgrade Node.js: https://nodejs.org/`)
  process.exit(1)
}

// browserslist → baseline-browser-mapping prints a stale-data warning to console.warn on load
const _bildOriginalWarn = console.warn
console.warn = (...args) => {
  const text = args.map((a) => (typeof a === 'string' ? a : '')).join(' ')
  if (text.includes('[baseline-browser-mapping]')) return
  _bildOriginalWarn.apply(console, args)
}

// Check dependencies before loading modules that require them
const { checkDependencies } = require('./lib/check-dependencies')
if (!checkDependencies()) {
  process.exit(1)
}

// Now safe to require modules
const { program, Option } = require('commander')
const { version } = require('../package.json')
const loginCommand = require('./commands/login')
const logoutCommand = require('./commands/logout')
const tokenCommand = require('./commands/token')
const tokenSetCommand = require('./commands/token-set')
const libraryAddCommand = require('./commands/library-add')
const libraryUpdateCommand = require('./commands/library-update')
const libraryPullCommand = require('./commands/library-pull')
const libraryListCommand = require('./commands/library-list')
const libraryDeleteCommand = require('./commands/library-delete')
const listAppsCommand = require('./commands/list-apps')
const useCommand = require('./commands/use')
const copyCommand = require('./commands/copy')
const updateBannersCommand = require('./commands/update-banners')
const pagesImportCommand = require('./commands/pages-import')
const pagesListCommand = require('./commands/pages-list')
const pagesCreateCommand = require('./commands/pages-create')
const pagesUpdateCommand = require('./commands/pages-update')
const initCommand = require('./commands/init')
const { depsInitCommand, depsComponentsCommand, depsAddCommand } = require('./commands/deps')
const templateInitCommand = require('./commands/template-init')
const templateLegacyInitCommand = require('./commands/template-legacy-init')
const templateValidateCommand = require('./commands/template-validate')
const templateLegacyValidateCommand = require('./commands/template-legacy-validate')
const templateV2FromJsxCommand = require('./commands/template-v2-from-jsx')
const templateV2FromTsxCommand = require('./commands/template-v2-from-tsx')
const templateV2FromHtmlCommand = require('./commands/template-v2-from-html')
const templateLegacyFromJsxCommand = require('./commands/template-legacy-from-jsx')
const templateLegacyFromTsxCommand = require('./commands/template-legacy-from-tsx')
const templatePullCommand = require('./commands/template-pull')

program
  .name('bild')
  .description('CLI tool for managing BILDIT CMS Templates')
  .version(version)

program
  .command('init')
  .description('Initialize bild.json config file')
  .action(initCommand)

const depsCommand = program
  .command('deps')
  .description('Scaffold and update local cmsDependencies.ts (consumer site)')

depsCommand
  .command('init')
  .description('Write the standard cmsDependencies.ts boilerplate if the file is missing (use --force to replace)')
  .option('--site-path <dir>', 'Consumer site root (or set sitePath in config)')
  .option(
    '--deps-file <path>',
    'Path to cmsDependencies: relative to --site-path when set, otherwise relative to cwd or absolute',
  )
  .option('--force', 'Replace an existing file')
  .option(
    '--with-components',
    'Include import * as Components, @components registry entry, and create src/app/components/Components.tsx (unless it exists)',
  )
  .option(
    '--without-components',
    'Omit @components / Components import even if a components barrel file already exists (default: add @components if barrel exists)',
  )
  .option(
    '--components-import <path>',
    'Module specifier for the barrel (default: @/app/components/Components) — must match tsconfig paths',
  )
  .option(
    '--components-barrel <path>',
    'Relative to site: barrel file to create (default: src/app/components/Components.tsx, or .jsx with --jsx)',
  )
  .option('--jsx', 'Use .jsx for the components barrel; implies Components.jsx + matching import for JS-only projects')
  .action(depsInitCommand)

depsCommand
  .command('components')
  .description('Scaffold the components barrel (re-exports) used with @components in cmsDependencies')
  .option('--site-path <dir>', 'Consumer site root (or set sitePath in config)')
  .option(
    '--components-barrel <path>',
    'Relative to site (default: src/app/components/Components.tsx, or .jsx with --jsx)',
  )
  .option('--force', 'Replace an existing file')
  .option('--jsx', 'Write Components.jsx')
  .action(depsComponentsCommand)

depsCommand
  .command('add')
  .description(
    'Add imports from component file(s) to the cmsDependencies file (on-disk source unchanged; use with `bild library add --apply-deps` or `bild library update --apply-deps` to merge when publishing)',
  )
  .argument('<files...>', 'Source .js/.jsx/.ts/.tsx files or a directory of those')
  .option('--site-path <dir>', 'Consumer site root (or set sitePath in config)')
  .option('--deps-file <path>', 'Explicit cmsDependencies file path')
  .option('--deps-alias <alias>', "Import alias (default from config, e.g. '@/cmsDependencies')")
  .option('--dry-run', 'Show suggested patches only, do not write', false)
  .action(depsAddCommand)

program
  .command('login')
  .description('Authenticate with BILDIT CMS')
  .argument('[url]', 'BILDIT CMS instance URL')
  .option('--token', 'Prompt for bearer token directly (skip OAuth flow)')
  .option('--password-login', 'Sign in with CMS email and password', false)
  .option('--auth-api-key <key>', 'API key for email/password sign-in (optional if returned by CMS config)')
  .option('--env', 'Display token for environment variable export')
  .addOption(new Option('--firebase').hideHelp())
  .addOption(new Option('--firebase-api-key <key>').hideHelp())
  .action(loginCommand)

program
  .command('logout')
  .description('Remove stored authentication token from keychain')
  .action(logoutCommand)

const tokenProgram = program
  .command('token')
  .description('Display and manage authentication token')

tokenProgram
  .command('set')
  .description('Store bearer token in the system keychain (no environment variable)')
  .argument('[token...]', 'JWT / ID token (omit to paste interactively or pipe on stdin)')
  .addHelpText(
    'after',
    `
If the token starts with "-", use -- or quote it:
  $ bild token set -- "<jwt>"
  $ printf %s "$JWT" | bild token set

A leading "Bearer " prefix or "Authorization: Bearer ..." line is stripped automatically.
You may run:  bild token set Bearer <jwt>   (with a space after Bearer, no quotes)
`,
  )
  .action(tokenSetCommand)

tokenProgram
  .option('--export', 'Show token with shell-specific export command')
  .option('--validate', 'Validate token format (JWT check)')
  .option('--source', 'Show where the token is loaded from')
  .addHelpText('after', `
Environment Variables:
  BILD_TOKEN   Primary authentication token (CLI / CI)
  CMS_TOKEN    Alternate token (lower priority than BILD_TOKEN)

Token Priority:
  1. BILD_TOKEN environment variable
  2. CMS_TOKEN environment variable
  3. Keychain storage (from "bild login" or "bild token set")

Examples:
  $ bild token                 Display current token
  $ bild token set             Paste token securely (prompt)
  $ bild token set "<jwt>"     Store token without env vars
  $ bild token --export        Show export command for your shell
  $ bild token --validate      Check if token is valid JWT format
  $ bild token --source        Show where token is loaded from
`)
  .action(tokenCommand)

const libraryCommand = program
  .command('library')
  .description('Manage Templates (CMS templates)')
  .addHelpText('after', `
Command Options:

  add|create              Add/create a new template
    --app-id <id>         App ID (uses defaultAppId from config if not provided)
    --template-id <id>   Template ID (extracted from filename if not provided)
    --code-type <type>    Code type: jsx, tsx, or html (detected from file extension)
    --type <type>         Template type (default: Homepage)
    --description <desc>  Description for the template
    --name <name>         Display name (defaults to template ID)
    --image <url>         Image URL or local file path (will be uploaded if local file)
                            Local uploads: first progress is bytes sent; then "waiting for server"
                            until the CMS returns a URL (BILD_MEDIA_DEBUG=1 logs URL and timings)
    --site-path <dir>     Consumer site root for import hints (or set sitePath in ~/.bild.json)
    --deps-file <path>    cmsDependencies file for import hints (export name conflicts)
    --deps-alias <alias>  Import alias for hints (default from config)

  update                  Update an existing template
    --app-id <id>         App ID (uses defaultAppId from config if not provided)
    --template-id <id>   Template ID (from bild library list, or the template name; use --template-id=-… if it starts with -)
    --root <dir>          Batch update all items under a template library folder tree (from library pull)
    --code-type <type>    Code type: jsx, tsx, or html (detected from file extension)
    --type <type>         Template type (keeps existing if not provided)
    --description <desc>  Description (keeps existing if not provided)
    --name <name>         Display name (keeps existing if not provided)
    --image <url>         Image URL or local file path (will be uploaded if local file)
    --site-path <dir>     Consumer site root for cmsDependencies import hints (or sitePath in config)
    --deps-file <path>    Path to cmsDependencies file for import hints and patches
    --deps-alias <alias>  Import alias (default from config)
    --apply-deps          Same as add: re-export local/@/ through Components, register npm on cms; update deps file, upload (needs --deps-file + sitePath or --site-path)

  pull [output-dir]       Export all templates to disk (type folders + metadata)
    --app-id <id>         App ID (uses defaultAppId from config if not provided)
    --output <dir>        Output directory (default: ./template-library)

  list|ls                 List templates (--verbose for full detail; former list-code-libs)
    --app-id <id>         App ID (uses defaultAppId from config if not provided)
    -v, --verbose         Show all fields (template ID, type, description, …)

  copy <template-id>      Copy a template to other apps
    --from <app-id>       Source app ID
    --to <app-ids...>     Target app ID(s)

  delete [template-id]    Delete a template by Template ID (use --template-id if the value starts with -)
    --template-id <id>    Template ID (use --template-id=-… or --template-id "-…" when the value starts with a hyphen)
    --app-id <id>         App ID (uses defaultAppId from config if not provided)
    -y, --yes             Skip confirmation prompt

Examples:
      $ bild library add hero.jsx --app-id myapp --template-id hero --type Homepage
      $ bild library add hero.jsx --image ./hero.png --description "Hero component"
      $ bild library update --template-id hero --image ./hero-new.png
      $ bild library update --root ./template-library --app-id myapp
      $ bild library pull ./template-library --app-id myapp
      $ bild library list --app-id myapp
      $ bild library list --verbose --app-id myapp
      $ bild library copy hero --from src-app --to dst-app
      $ bild library delete --template-id=-OrFkw6Pb8ZeCuMkx-Cg --app-id myapp
  $ bild library add --help                    Show detailed help for add command
  $ bild library update --help                 Show detailed help for update command
  $ bild library pull --help                   Show detailed help for pull command
  $ bild library list --help                   Show detailed help for list command
  $ bild library copy --help                   Show detailed help for copy command
  $ bild library delete --help                 Show detailed help for delete command
`)

const addCommand = libraryCommand
  .command('add')
  .alias('create')
  .description('Add/create a new template')
  .argument('[files...]', 'File paths or folder paths (optional, will prompt if not provided)')
  .option('--app-id <id>', 'App ID (uses defaultAppId from config if not provided)')
      .option('--template-id <id>', 'Template ID (extracted from filename if not provided)')
  .option('--code-type <type>', 'Code type: jsx, tsx, or html (detected from file extension if not provided)')
  .option('--type <type>', 'Template type (default: Homepage)')
  .option('--description <desc>', 'Description for the template')
  .option('--name <name>', 'Display name for the template (defaults to template ID)')
  .option('--image <url>', 'Image URL or local file path (will be uploaded if local file)')
  .option('--site-path <dir>', 'Site root for cmsDependencies import hints (or set sitePath in config)')
  .option('--deps-file <path>', 'Path to cmsDependencies file for import hints')
  .option('--deps-alias <alias>', "Import alias for hints (default from config, e.g. '@/cmsDependencies')")
  .addOption(
    new Option(
      '--lint-env <env>',
      'ESLint runtime environment: auto (detect), browser, node, or both (default: auto)',
    ).choices(['auto', 'browser', 'node', 'both']).default('auto'),
  )
  .option(
    '--apply-deps',
    'Re-export relative / @/ through app/components/Components, register npm packages on the cms object (import * as Pkg + record key; source still uses from "pkg"). Requires --deps-file and sitePath (or --site-path).',
    false,
  )
  .option(
    '--no-lint',
    'Skip lint step (transpile still runs). For files whose name contains .template. and a matching top // {templateId}:v… comment, lint is skipped by default.',
  )
  .action(libraryAddCommand)

// Make help work for subcommands
addCommand.addHelpText('after', `
Examples:
  $ bild library add hero.jsx
      $ bild library add hero.jsx --app-id myapp --template-id hero --type Homepage
  $ bild library add hero.jsx --image ./hero.png --description "Hero component"
  $ bild library add Hero.tsx --deps-file ./src/cmsDependencies.ts --apply-deps --image ./hero.png
`)


const updateCommand = libraryCommand
  .command('update')
  .description('Update an existing template')
  .argument('[files...]', 'File paths or folder paths (optional, will prompt if not provided)')
  .option('--app-id <id>', 'App ID (uses defaultAppId from config if not provided)')
  .option(
    '--template-id <id>',
    'Template ID: template name, or the value in the Template ID column from bild library list (if not provided, you will be prompted; use --template-id=-… if the value starts with a hyphen; surrounding quotes are stripped)',
  )
  .addOption(new Option('--cid <id>').hideHelp())
  .option(
    '--root <dir>',
    'Root folder from bild library pull (template library export tree; batch update all items under type subfolders)',
  )
  .option('--code-type <type>', 'Code type: jsx, tsx, or html (detected from file extension if not provided)')
  .option('--type <type>', 'Template type (keeps existing if not provided)')
  .option('--description <desc>', 'Description for the template (keeps existing if not provided)')
  .option('--name <name>', 'Display name for the template (keeps existing if not provided)')
  .option('--image <url>', 'Image URL or local file path (will be uploaded if local file, keeps existing if not provided)')
  .option('--site-path <dir>', 'Site root for cmsDependencies import hints (or set sitePath in config)')
  .option('--deps-file <path>', 'Path to cmsDependencies file for import hints')
  .option('--deps-alias <alias>', "Import alias for hints (default from config, e.g. '@/cmsDependencies')")
  .addOption(
    new Option(
      '--lint-env <env>',
      'ESLint runtime environment: auto (detect), browser, node, or both (default: auto)',
    ).choices(['auto', 'browser', 'node', 'both']).default('auto'),
  )
  .option(
    '--apply-deps',
    'Re-export relative / @/ through app/components/Components, register npm packages on the cms object (import * as Pkg + record key; source still uses from "pkg"). Requires --deps-file and sitePath (or --site-path).',
    false,
  )
  .option('--no-lint', 'Skip lint step (transpile still runs)')
  .action(libraryUpdateCommand)

// Make help work for subcommands
updateCommand.addHelpText('after', `
Examples:
  $ bild library update
      $ bild library update hero.jsx --template-id hero
  $ bild library update hero.jsx --app-id myapp --image ./hero-new.png
  $ bild library update HomeHero.template.tsx --template-id HomeHero --deps-file ./utils/cmsDependencies.ts --apply-deps --site-path .
  $ bild library update hero.jsx --template-id hero --apply-deps --site-path ./my-app
  $ bild library update --root ./template-library --app-id myapp
  $ bild library update hero.jsx --template-id=-OrFkw6Pb8ZeCuMkx-Cg --app-id myapp
`)

const pullLibraryCommand = libraryCommand
  .command('pull')
  .description('Export all templates to disk (mirrors type folder layout + JSON metadata)')
  .argument('[output-dir]', 'Output directory (default: ./template-library)')
  .option('--app-id <id>', 'App ID (uses defaultAppId from config if not provided)')
  .option('--output <dir>', 'Output directory (overrides positional output-dir)')
  .action(libraryPullCommand)

pullLibraryCommand.addHelpText('after', `
Examples:
  $ bild library pull
  $ bild library pull ./my-templates --app-id myapp
  $ bild library pull --output ./exports --app-id myapp
`)

const listLibraryCommand = libraryCommand
  .command('list')
  .alias('ls')
  .description('List templates for the app (compact table; use --verbose for full detail)')
  .option('--app-id <id>', 'App ID (uses defaultAppId from config if not provided)')
  .option('-v, --verbose', 'Show full detail per item (same as former list-code-libs)')
  .action(libraryListCommand)

listLibraryCommand.addHelpText('after', `
Examples:
  $ bild library list
  $ bild library ls --app-id myapp
  $ bild library list --verbose
`)

const deleteLibraryCommand = libraryCommand
  .command('delete')
  .alias('remove')
  .description('Delete a template by Template ID')
  .argument(
    '[template-id]',
    'Template ID (optional if --template-id is set; for values starting with -, use --template-id or place the value after --)',
  )
  .option(
    '--template-id <id>',
    'Template ID (use when the value starts with a hyphen, e.g. --template-id=-xId or --template-id "-xId"; surrounding quotes are stripped)',
  )
  .addOption(new Option('--cid <id>').hideHelp())
  .option('--app-id <id>', 'App ID (uses defaultAppId from config if not provided)')
  .option('-y, --yes', 'Skip confirmation prompt (non-interactive)')
  .action(libraryDeleteCommand)

deleteLibraryCommand.addHelpText('after', `
Examples:
  $ bild library delete cl_abc123 --app-id myapp
  $ bild library delete cl_abc123 --yes
  $ bild library delete --template-id=-OrFkw6Pb8ZeCuMkx-Cg --app-id myapp
  $ bild library delete -- -OrFkw6Pb8ZeCuMkx-Cg --app-id myapp
`)

const copyLibraryCommand = libraryCommand
  .command('copy')
  .description('Copy a template from one app to one or more target apps')
  .argument('<template-id>', 'Template ID to copy')
  .requiredOption('--from <app-id>', 'Source app ID')
  .requiredOption('--to <app-ids...>', 'Target app ID(s)')
  .action(copyCommand)

copyLibraryCommand.addHelpText('after', `
Examples:
  $ bild library copy herostandard7 --from PaintingBanner --to belk-dev-web
  $ bild library copy hero --from app1 --to app2 app3

Note: Put <template-id> before options.
`)

const appCommand = program
  .command('app')
  .description('List and manage BILDIT apps and websites')

appCommand
  .command('list')
  .description('List available apps and websites')
  .action(listAppsCommand)

appCommand.addHelpText('after', `
Examples:
  $ bild app list
`)

program
  .command('use')
  .description('Select and set default app or website from available list')
  .action(useCommand)

const bannerCommand = program
  .command('banner')
  .description('Manage CMS banners')

bannerCommand
  .command('update')
  .description('Update banners with new template versions')
  .argument('<template-id>', 'Template ID')
  .requiredOption('--app-id <id>', 'App ID')
  .option('--start-date <date>', 'Start date (ISO format)')
  .option('--end-date <date>', 'End date (ISO format)')
  .option('--override', 'Override published banner restriction')
  .action(updateBannersCommand)

bannerCommand.addHelpText('after', `
Examples:
  $ bild banner update herostandard7 --app-id my-app
`)

const pageCommand = program
  .command('page')
  .description('List, create, update, and bulk-import CMS pages (and linked HTML content)')
  .addHelpText('after', `
Subcommands:
  import    CSV → content records (HTML body) + linked pages (slug, title, metaTags, preview)
  list      List pages for an app (--json for raw payload)
  create    Create a page linked to existing content (--slug, --name, --content-id)
  update    Patch a page (--page-id or --slug to select)

Examples:
  $ bild page import ./posts.csv --app-id my-app
  $ bild page import ./posts.csv --upsert --devices web,ipad
  $ bild page list --app-id my-app
  $ bild page list --app-id my-app --slug about --json
  $ bild page create --app-id my-app --slug about --name About --content-id cl_abc123
  $ bild page update --app-id my-app --slug about --meta-title "About Us"
`)

const pageImportCmd = pageCommand
  .command('import')
  .description(
    'Bulk-import pages and required content from CSV: creates/updates HTML content (slug, code) and linked pages (URL slug, title, metaTags, preview, contentId).',
  )
  .argument('<file>', 'Path to CSV file')
  .option('--app-id <id>', 'App ID (uses defaultAppId from bild.json if omitted)')
  .option(
    '--devices <list>',
    'Comma-separated content targets: iphone, ipad, android, web (default: web)',
    'web',
  )
  .option('--delimiter <char>', 'CSV field delimiter', ',')
  .option(
    '--upsert',
    'Update existing content (by content slug) and page (by page slug) instead of only creating',
    false,
  )
  .option('--dry-run', 'Parse CSV and print actions without calling the API', false)
  .option('--draft', 'Force draft/unpublished content and unpublished pages (ignore published_at)', false)
  .option(
    '--no-upload-images',
    'Do not upload local image paths for ogImage; use URLs as-is',
  )
  .action(pagesImportCommand)

pageImportCmd.addHelpText('after', `
CSV columns: slug (content slug), title, published_at, excerpt, content (HTML → content.code), category,
tags (→ meta keywords), author, image (→ ogImage URL or local file to upload), meta_title, meta_description.
Optional: page_slug — URL slug for the page (defaults to slug).

Uses POST/PUT /api/apps/<appId>/contents then /api/apps/<appId>/pages.
`)

pageCommand
  .command('list')
  .description('List pages for an app')
  .option('--app-id <id>', 'App ID (uses defaultAppId from bild.json if omitted)')
  .option('--slug <slug>', 'Filter by page URL slug (passed to CMS list API)')
  .option('--draft', 'Filter draft pages only', false)
  .option('--published', 'Filter published pages only', false)
  .option('--archived', 'Filter archived pages only', false)
  .option('--json', 'Print JSON array instead of a compact table', false)
  .action(pagesListCommand)

pageCommand
  .command('create')
  .description('Create a CMS page linked to existing content')
  .requiredOption('--slug <slug>', 'Page URL slug (lowercase kebab-case)')
  .requiredOption('--name <name>', 'Page title / display name')
  .requiredOption('--content-id <id>', 'Existing content id (HTML body record)')
  .option('--app-id <id>', 'App ID (uses defaultAppId from bild.json if omitted)')
  .option('--draft', 'Create as unpublished', false)
  .option('--preview-description <text>', 'Short preview / excerpt text')
  .option('--meta-title <text>', 'SEO title')
  .option('--meta-description <text>', 'SEO description')
  .option('--keywords <text>', 'SEO keywords')
  .option('--og-title <text>', 'Open Graph title')
  .option('--og-description <text>', 'Open Graph description')
  .option('--og-image <url>', 'Open Graph image URL')
  .action(pagesCreateCommand)

pageCommand
  .command('update')
  .description('Update a page (select with --page-id or --slug)')
  .option('--app-id <id>', 'App ID (uses defaultAppId from bild.json if omitted)')
  .option('--page-id <id>', 'CMS page document id')
  .option('--slug <slug>', 'Page URL slug (when --page-id omitted)')
  .option('--new-slug <slug>', 'Set a new URL slug')
  .option('--name <name>', 'Page title / display name')
  .option('--content-id <id>', 'Link to different content id')
  .option('--draft', 'Set unpublished', false)
  .option('--publish', 'Set published', false)
  .option('--archived', 'Set archived', false)
  .option('--unarchived', 'Clear archived', false)
  .option('--preview-description <text>', 'Short preview / excerpt (omit value via shell to leave unchanged)')
  .option('--meta-title <text>', 'SEO title')
  .option('--meta-description <text>', 'SEO description')
  .option('--keywords <text>', 'SEO keywords')
  .option('--og-title <text>', 'Open Graph title')
  .option('--og-description <text>', 'Open Graph description')
  .option('--og-image <url>', 'Open Graph image URL')
  .option(
    '--published-at <iso>',
    'Set blog-style publish time (CMS page schedule.startDate); any Date.parse-compatible string'
  )
  .option('--clear-published-at', 'Omit schedule from payload (drops publish/start schedule)', false)
  .option(
    '--created-at <iso>',
    'Set CMS page createdAt (stored as epoch milliseconds); Date.parse-compatible; does not change schedule unless combined with --published-at'
  )
  .action(pagesUpdateCommand)

const templateCommand = program
  .command('template')
  .description('V2 templates (default): JSX → plain const literals + // @template v2 + per-const @group/@type JSDoc. Subcommand `legacy` = $() + // group.')
  .addHelpText('after', `
V2 (default) — JSX/TSX → regular JS/TS template (// @template v2, JSDoc @group / @type; no $() syntax):
  $ bild template init hero
  $ bild template from-jsx hero.jsx
  $ bild template from-tsx hero.tsx
  $ bild template from-html hero.html
  $ bild template validate Hero.jsx
  $ bild template pull herostandard7 --app-id my-app

V1 — legacy $() template syntax with // group / // endgroup:
  $ bild template legacy init hero
  $ bild template legacy from-jsx hero.jsx
  $ bild template legacy from-tsx hero.tsx
  $ bild template legacy validate hero.template.jsx
  $ bild template legacy pull herostandard7 --app-id my-app
`)

templateCommand
  .command('init')
  .description('Scaffold a starter template file for Templates (pure JS / JSX, v2)')
  .argument('<name>', 'Template name (used for filename and component)')
  .option('--out <path>', 'Output path (defaults to <name>.jsx)')
  .option('--ts', 'Emit .tsx instead of .jsx')
  .option('--force', 'Overwrite existing file')
  .action(templateInitCommand)

templateCommand
  .command('validate')
  .description('Validate a template file: lint + transpile (pure JS; no $() preprocessing)')
  .argument('<file>', 'Source file to validate')
  .option('--no-lint', 'Skip lint step (transpile-only)')
  .option('--quiet', 'Suppress warnings, show errors only')
  .action(templateValidateCommand)

templateCommand
  .command('from-jsx')
  .description('Rewrite JSX/TSX into a v2 template: plain const literals + JSDoc (inline CSS, deps; no $() syntax)')
  .argument('<file>', 'Source component file (.jsx, .tsx, etc.)')
  .option('--out <path>', 'Output path (use "-" for stdout; default: <name>.template.<ext> beside source)')
  .option('--css-mode <mode>', 'hybrid | inline | style-tag (default from config or hybrid)')
  .option('--naming <strategy>', 'camelComponent | layerPath')
  .option('--site-path <dir>', 'Path to the consumer site (where cmsDependencies lives)')
  .option('--deps-file <path>', 'Override cmsDependencies file path')
  .option('--deps-alias <alias>', "Import alias for deps file (default '@/cmsDependencies')")
  .option('--dry-run', 'Do not write any files; print what would happen')
  .option(
    '--strict',
    'Fail if the source has SSR/hydration risks (browser-only globals in render) or lint reports errors on generated output',
  )
  .option('--no-ssr-check', 'Skip SSR/hydration pattern scan on the source file')
  .option('--no-verify', 'Skip post-transpile verification (not recommended)')
  .action(templateV2FromJsxCommand)

templateCommand
  .command('from-tsx')
  .description('Rewrite TypeScript (.ts/.tsx) into a v2 template: plain const literals + JSDoc (no $() syntax)')
  .argument('<file>', 'Source component file (.ts or .tsx)')
  .option('--out <path>', 'Output path (use "-" for stdout; default: <name>.template.<ext> beside source)')
  .option('--css-mode <mode>', 'hybrid | inline | style-tag (default from config or hybrid)')
  .option('--naming <strategy>', 'camelComponent | layerPath')
  .option('--site-path <dir>', 'Path to the consumer site (where cmsDependencies lives)')
  .option('--deps-file <path>', 'Override cmsDependencies file path')
  .option('--deps-alias <alias>', "Import alias for deps file (default '@/cmsDependencies')")
  .option('--dry-run', 'Do not write any files; print what would happen')
  .option(
    '--strict',
    'Fail if the source has SSR/hydration risks (browser-only globals in render) or lint reports errors on generated output',
  )
  .option('--no-ssr-check', 'Skip SSR/hydration pattern scan on the source file')
  .option('--no-verify', 'Skip post-transpile verification (not recommended)')
  .action(templateV2FromTsxCommand)

templateCommand
  .command('from-html')
  .description('Copy an HTML (.html/.htm) file for Templates upload (v2; no $() codemod)')
  .argument('<file>', 'Source .html or .htm file')
  .option('--out <path>', 'Output path (use "-" for stdout; default: <name>.export.<ext> beside source)')
  .option('--dry-run', 'Do not write; print what would happen')
  .option('--strict', 'Verify copy (HTML skips ESLint; not ECMAScript)')
  .option('--no-verify', 'Skip post-copy transpile verification (not recommended)')
  .action(templateV2FromHtmlCommand)

templateCommand
  .command('pull')
  .description('Download source of an existing template from the CMS')
  .argument('[template-id]', 'Template ID to pull (prompts if omitted)')
  .option('--app-id <id>', 'App ID (uses defaultAppId from config if not provided)')
  .option('--out <path>', 'Output path')
  .action(templatePullCommand)

const templateLegacyCommand = templateCommand
  .command('legacy')
  .description('V1 BILDIT templates ($() field syntax)')

templateLegacyCommand
  .command('init')
  .description('Scaffold a starter $() template file')
  .argument('<name>', 'Template name (used for filename and component)')
  .option('--out <path>', 'Output path (defaults to <name>.jsx)')
  .option('--ts', 'Emit .tsx instead of .jsx')
  .option('--force', 'Overwrite existing file')
  .action(templateLegacyInitCommand)

templateLegacyCommand
  .command('validate')
  .description('Validate a $() template file: preprocess -> lint -> transpile')
  .argument('<file>', 'Template file to validate')
  .option('--no-lint', 'Skip lint step (transpile-only)')
  .option('--quiet', 'Suppress warnings, show errors only')
  .action(templateLegacyValidateCommand)

templateLegacyCommand
  .command('from-jsx')
  .description('Rewrite JSX or TSX into a BILDIT $() template (// group sections; inline CSS + extract deps)')
  .argument('<file>', 'Source component file (.jsx, .tsx, etc.)')
  .option('--out <path>', 'Output path (use "-" for stdout)')
  .option('--css-mode <mode>', 'hybrid | inline | style-tag (default from config or hybrid)')
  .option('--naming <strategy>', 'camelComponent | layerPath')
  .option('--site-path <dir>', 'Path to the consumer site (where cmsDependencies lives)')
  .option('--deps-file <path>', 'Override cmsDependencies file path')
  .option('--deps-alias <alias>', "Import alias for deps file (default '@/cmsDependencies')")
  .option('--dry-run', 'Do not write any files; print what would happen')
  .option(
    '--strict',
    'Fail if the source has SSR/hydration risks (browser-only globals in render) or lint reports errors on generated output',
  )
  .option('--no-ssr-check', 'Skip SSR/hydration pattern scan on the source file')
  .option('--no-verify', 'Skip post-transpile verification (not recommended)')
  .action(templateLegacyFromJsxCommand)

templateLegacyCommand
  .command('from-tsx')
  .description('Rewrite TypeScript (.ts/.tsx) into a BILDIT $() template (// group sections; inline CSS + extract deps)')
  .argument('<file>', 'Source component file (.ts or .tsx)')
  .option('--out <path>', 'Output path (use "-" for stdout)')
  .option('--css-mode <mode>', 'hybrid | inline | style-tag (default from config or hybrid)')
  .option('--naming <strategy>', 'camelComponent | layerPath')
  .option('--site-path <dir>', 'Path to the consumer site (where cmsDependencies lives)')
  .option('--deps-file <path>', 'Override cmsDependencies file path')
  .option('--deps-alias <alias>', "Import alias for deps file (default '@/cmsDependencies')")
  .option('--dry-run', 'Do not write any files; print what would happen')
  .option(
    '--strict',
    'Fail if the source has SSR/hydration risks (browser-only globals in render) or lint reports errors on generated output',
  )
  .option('--no-ssr-check', 'Skip SSR/hydration pattern scan on the source file')
  .option('--no-verify', 'Skip post-transpile verification (not recommended)')
  .action(templateLegacyFromTsxCommand)

templateLegacyCommand
  .command('pull')
  .description('Download source of an existing template from the CMS')
  .argument('[template-id]', 'Template ID to pull (prompts if omitted)')
  .option('--app-id <id>', 'App ID (uses defaultAppId from config if not provided)')
  .option('--out <path>', 'Output path')
  .action(templatePullCommand)

program.parse()

