/**
 * Inferred Types Generator
 *
 * Generates TypeScript types using InferSchema<typeof schema>.
 * Appends type export to the schema file generated by rawSchema().
 *
 * Output: `export type Intf = InferSchema<typeof schema>;`
 */

import type {
  GeneratorPlugin,
  TransformContext,
  GeneratedFile,
} from '../codegen/types';

// ============================================================================
// Options
// ============================================================================

export interface InferredTypesOptions {
  /** Import path for InferSchema (default: 'ts-xsd') */
  inferSchemaImport?: string;
  /** Type name pattern. Use {Name} for PascalCase schema name (default: '{Name}') */
  typeNamePattern?: string;
  /** Schema variable name to infer from (default: 'schema' for default export) */
  schemaVariable?: string;
}

// ============================================================================
// Generator
// ============================================================================

/**
 * Create an inferred types generator plugin
 *
 * This generator should be used AFTER rawSchema() in the pipeline.
 * It modifies the generated schema file to add type exports.
 *
 * @example
 * ```ts
 * import { rawSchema, inferredTypes } from '@abapify/ts-xsd/generators';
 *
 * export default defineConfig({
 *   generators: [
 *     rawSchema(),
 *     inferredTypes(),  // Adds: export type Intf = InferSchema<typeof schema>;
 *   ],
 * });
 * ```
 */
export function inferredTypes(
  options: InferredTypesOptions = {},
): GeneratorPlugin {
  const { inferSchemaImport = 'ts-xsd', typeNamePattern = '{Name}' } = options;

  return {
    name: 'inferred-types',

    transform(ctx: TransformContext): GeneratedFile[] {
      const { schema } = ctx;
      const typeName = typeNamePattern.replace(
        '{Name}',
        pascalCase(schema.name),
      );

      // Store for later - we'll modify the file in finalize
      // For now, generate a separate types file that re-exports
      const lines: string[] = [
        '/**',
        ' * Auto-generated type from schema',
        ' * ',
        ' * DO NOT EDIT - Generated by ts-xsd codegen',
        ' */',
        '',
        `import type { InferSchema } from '${inferSchemaImport}';`,
        `import schema from './${schema.name}';`,
        '',
        `/** Inferred type for ${schema.name} schema */`,
        `export type ${typeName} = InferSchema<typeof schema>;`,
        '',
        `export default schema;`,
        '',
      ];

      // Generate a typed wrapper file instead of modifying the raw schema
      return [
        {
          path: `${schema.name}.typed.ts`,
          content: lines.join('\n'),
        },
      ];
    },
  };
}

// ============================================================================
// Helpers
// ============================================================================

function pascalCase(str: string): string {
  return str
    .replaceAll(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))
    .replace(/^./, (s) => s.toUpperCase());
}
