#!/usr/bin/env -S npx --yes tsx
// =============================================================================
// export.ts — Export a data store to a YAML definition file
//
// Part of: .opencode/skills/templating-vault/scripts/
//
// Reads a data directory and produces a YAML definition that can be used
// with init.ts to recreate the store.
//
// USAGE:
//   export.ts --store-dir <data_dir> [--output <file.yaml>]
//             [--include-values]
//
// OUTPUT: YAML definition to stdout or --output file
// =============================================================================
import * as fs from 'node:fs';
import * as path from 'node:path';
import { fileURLToPath } from 'node:url';
import yaml from 'js-yaml';
import { parseCommonFlags, getFlag, hasFlag, output, log } from './api.ts';

interface ExportedKey {
  [prop: string]: unknown;
}

async function main(): Promise<void> {
  const args = process.argv.slice(2);

  const storeDir = getFlag(args, '--store-dir');
  const outputPath = getFlag(args, '--output');
  const includeValues = hasFlag(args, '--include-values');

  if (!storeDir) {
    output({ exported: false, error: '--store-dir is required' });
    process.exit(1);
  }

  if (!fs.existsSync(storeDir)) {
    output({ exported: false, error: `Store directory "${storeDir}" not found` });
    process.exit(1);
  }

  const definition: Record<string, unknown> = {};

  // Read .store.yaml defaults
  const storeYamlPath = path.join(storeDir, '.store.yaml');
  if (fs.existsSync(storeYamlPath)) {
    const storeYaml = yaml.load(fs.readFileSync(storeYamlPath, 'utf-8')) as Record<string, unknown>;
    if (storeYaml?.defaults) {
      definition.defaults = storeYaml.defaults;
    }
  }

  // Walk directory tree and collect keys
  const keys: Record<string, ExportedKey> = {};

  function walk(dir: string, keyParts: string[]): void {
    const entries = fs.readdirSync(dir, { withFileTypes: true });
    const hasValueFile = entries.some((e) => e.isFile() && e.name === 'value');
    const hasMetaFile = entries.some((e) => e.isFile() && e.name === 'meta.yaml');

    if ((hasValueFile || hasMetaFile) && keyParts.length > 0) {
      const keyPath = keyParts.join('.');
      const keyDef: ExportedKey = {};

      // Read meta.yaml
      if (hasMetaFile) {
        const metaPath = path.join(dir, 'meta.yaml');
        try {
          const meta = yaml.load(fs.readFileSync(metaPath, 'utf-8')) as Record<string, unknown>;
          if (meta) Object.assign(keyDef, meta);
        } catch {
          // ignore
        }
      }

      // Optionally include value
      if (includeValues && hasValueFile) {
        const valuePath = path.join(dir, 'value');
        keyDef.value = fs.readFileSync(valuePath, 'utf-8');
      }

      if (Object.keys(keyDef).length > 0) {
        keys[keyPath] = keyDef;
      }
    }

    // Recurse
    for (const entry of entries) {
      if (entry.isDirectory() && !entry.name.startsWith('.')) {
        walk(path.join(dir, entry.name), [...keyParts, entry.name]);
      }
    }
  }

  walk(storeDir, []);

  if (Object.keys(keys).length > 0) {
    definition.keys = keys;
  }

  const yamlOutput = yaml.dump(definition, { lineWidth: 120, noRefs: true });

  if (outputPath) {
    const dir = path.dirname(outputPath);
    fs.mkdirSync(dir, { recursive: true });
    fs.writeFileSync(outputPath, yamlOutput, 'utf-8');
    output({ exported: true, output: outputPath, key_count: Object.keys(keys).length });
  } else {
    process.stdout.write(yamlOutput);
  }
}

if (process.argv[1] === fileURLToPath(import.meta.url)) {
  main().catch((err: unknown) => {
    output({ exported: false, error: String(err instanceof Error ? err.message : err) });
    process.exit(1);
  });
}
