#!/usr/bin/env tsx
import fs from 'fs/promises';
import path from 'path';

async function generateIndividualDTOs() {
  const openapiPath = path.join(__dirname, '../apps/api/openapi.json');
  const outputDir = path.join(__dirname, '../apps/website/lib/types/generated');

  console.log('🔄 Generating individual DTO files from OpenAPI spec...');

  try {
    // Check if OpenAPI spec exists
    await fs.access(openapiPath);
  } catch {
    console.error(`❌ OpenAPI spec not found at: ${openapiPath}`);
    console.error('Run "npm run api:generate-spec" first');
    process.exit(1);
  }

  try {
    // Read the OpenAPI spec
    const specContent = await fs.readFile(openapiPath, 'utf-8');
    const spec = JSON.parse(specContent);

    // Ensure output directory exists
    await fs.mkdir(outputDir, { recursive: true });

    // Extract schemas from the spec
    const schemas = spec.components?.schemas || {};

    console.log(`📝 Found ${Object.keys(schemas).length} schemas to generate`);

    // Generate individual files for each schema
    for (const [schemaName, schema] of Object.entries(schemas)) {
      if (typeof schema === 'object' && schema !== null) {
        const fileName = `${schemaName}.ts`;
        const filePath = path.join(outputDir, fileName);

        // Convert OpenAPI schema to TypeScript interface
        const tsInterface = generateTypeScriptInterface(schemaName, schema);

        await fs.writeFile(filePath, tsInterface);
        console.log(`✅ Generated ${fileName}`);
      }
    }

    console.log(`🎉 Generated ${Object.keys(schemas).length} DTO files in ${outputDir}`);

  } catch (error) {
    console.error('❌ Failed to generate DTOs:', error);
    process.exit(1);
  }
}

function generateTypeScriptInterface(name: string, schema: any): string {
  const properties = schema.properties || {};
  const required = schema.required || [];

  let interfaceContent = `/**
 * Auto-generated DTO from OpenAPI spec
 * This file is generated by scripts/generate-api-types.ts
 * Do not edit manually - regenerate using: npm run api:sync-types
 */

export interface ${name} {\n`;

  for (const [propName, propSchema] of Object.entries(properties)) {
    const isRequired = required.includes(propName);
    const optionalMark = isRequired ? '' : '?';
    const type = openApiTypeToTypeScript(propSchema);

    interfaceContent += `  ${propName}${optionalMark}: ${type};\n`;
  }

  interfaceContent += '}\n';

  return interfaceContent;
}

function openApiTypeToTypeScript(schema: any): string {
  if (schema.$ref) {
    // Handle references
    const refName = schema.$ref.split('/').pop();
    return refName;
  }

  if (schema.type === 'array') {
    const itemType = openApiTypeToTypeScript(schema.items);
    return `${itemType}[]`;
  }

  if (schema.type === 'object') {
    // For complex objects, we'll use a generic Record for now
    return 'Record<string, any>';
  }

  switch (schema.type) {
    case 'string':
      if (schema.format === 'date-time') {
        return 'string'; // Keep as string for now, could be Date
      }
      return 'string';
    case 'number':
    case 'integer':
      return 'number';
    case 'boolean':
      return 'boolean';
    default:
      return 'any';
  }
}

generateIndividualDTOs().catch(console.error);