#!/usr/bin/env node

/**
 * AeThex Language Compiler v1.0
 * Compiles .aethex files to JavaScript, Lua (Roblox), Verse (UEFN), and C# (Unity)
 */

const fs = require('fs');
const path = require('path');

class AeThexCompiler {
  constructor(options = {}) {
    this.target = options.target || 'javascript'; // javascript, roblox, uefn, unity
    this.output = [];
    this.indent = 0;
    this.errors = [];
    this.warnings = [];
    this.line = 1;
    this.sourceFile = options.sourceFile || 'unknown';
  }

  // Error handling
  error(message, line = this.line) {
    this.errors.push({
      type: 'error',
      message,
      line,
      file: this.sourceFile
    });
  }

  warn(message, line = this.line) {
    this.warnings.push({
      type: 'warning',
      message,
      line,
      file: this.sourceFile
    });
  }

  // Output helpers
  emit(code) {
    const indentation = '  '.repeat(this.indent);
    this.output.push(indentation + code);
  }

  // Main compile function
  compile(sourceCode) {
    this.output = [];
    this.errors = [];
    this.warnings = [];
    this.line = 1;

    // Add runtime based on target
    this.addRuntime();

    const lines = sourceCode.split('\n');
    let i = 0;

    while (i < lines.length) {
      this.line = i + 1;
      const line = lines[i].trim();

      if (!line || line.startsWith('#')) {
        i++;
        continue;
      }

      try {
        if (line.startsWith('reality ')) {
          i = this.compileReality(lines, i);
        } else if (line.startsWith('journey ')) {
          i = this.compileJourney(lines, i);
        } else if (line.startsWith('sync ')) {
          i = this.compileSync(lines, i);
        } else if (line.startsWith('when ')) {
          i = this.compileWhen(lines, i);
        } else if (line.startsWith('notify ')) {
          i = this.compileNotify(lines, i);
        } else if (line.startsWith('reveal ')) {
          i = this.compileReveal(lines, i);
        } else if (line.startsWith('import ')) {
          i = this.compileImport(lines, i);
        } else {
          i++;
        }
      } catch (err) {
        this.error(`Compilation error: ${err.message}`, i + 1);
        i++;
      }
    }

    return {
      code: this.output.join('\n'),
      errors: this.errors,
      warnings: this.warnings,
      success: this.errors.length === 0
    };
  }

  // Runtime based on target
  addRuntime() {
    if (this.target === 'javascript') {
      this.emit(`// AeThex Runtime v1.0 (JavaScript Target)`);
      this.emit(`const AeThex = {`);
      this.indent++;
      this.emit(`platform: 'web',`);
      this.emit(`sync: async function(data, platforms) {`);
      this.indent++;
      this.emit(`console.log('[AeThex] Syncing:', data, 'to platforms:', platforms);`);
      this.emit(`// TODO: Implement actual sync logic`);
      this.emit(`return true;`);
      this.indent--;
      this.emit(`},`);
      this.emit(`notify: function(message) {`);
      this.indent++;
      this.emit(`console.log('[AeThex]', message);`);
      this.indent--;
      this.emit(`},`);
      this.emit(`reveal: function(data) {`);
      this.indent++;
      this.emit(`console.log('[AeThex] Revealed:', data);`);
      this.indent--;
      this.emit(`}`);
      this.indent--;
      this.emit(`};`);
      this.emit(``);
    } else if (this.target === 'roblox') {
      this.emit(`-- AeThex Runtime v1.0 (Roblox/Lua Target)`);
      this.emit(`local AeThex = {`);
      this.indent++;
      this.emit(`platform = "roblox",`);
      this.emit(`sync = function(data, platforms)`);
      this.indent++;
      this.emit(`print("[AeThex] Syncing:", data, "to platforms:", table.concat(platforms, ", "))`);
      this.emit(`return true`);
      this.indent--;
      this.emit(`end,`);
      this.emit(`notify = function(message)`);
      this.indent++;
      this.emit(`print("[AeThex]", message)`);
      this.indent--;
      this.emit(`end,`);
      this.emit(`reveal = function(data)`);
      this.indent++;
      this.emit(`print("[AeThex] Revealed:", data)`);
      this.indent--;
      this.emit(`end`);
      this.indent--;
      this.emit(`}`);
      this.emit(``);
    }
  }

  // Compile 'reality' blocks
  compileReality(lines, startIndex) {
    const line = lines[startIndex].trim();
    const match = line.match(/reality\s+(\w+)\s*\{/);
    
    if (!match) {
      this.error(`Invalid reality declaration: ${line}`);
      return startIndex + 1;
    }

    const realityName = match[1];
    
    if (this.target === 'javascript') {
      this.emit(`// Reality: ${realityName}`);
      this.emit(`const ${realityName} = {`);
      this.indent++;
    } else if (this.target === 'roblox') {
      this.emit(`-- Reality: ${realityName}`);
      this.emit(`local ${realityName} = {`);
      this.indent++;
    }

    let i = startIndex + 1;
    while (i < lines.length && !lines[i].trim().startsWith('}')) {
      const propLine = lines[i].trim();
      if (propLine && !propLine.startsWith('#')) {
        const propMatch = propLine.match(/(\w+):\s*(.+)/);
        if (propMatch) {
          const [, key, value] = propMatch;
          if (this.target === 'javascript') {
            this.emit(`${key}: ${value},`);
          } else if (this.target === 'roblox') {
            this.emit(`${key} = ${value.replace(/\[/g, '{').replace(/\]/g, '}')},`);
          }
        }
      }
      i++;
    }

    this.indent--;
    if (this.target === 'javascript') {
      this.emit(`};`);
    } else if (this.target === 'roblox') {
      this.emit(`}`);
    }
    this.emit(``);

    return i + 1;
  }

  // Compile 'journey' functions
  compileJourney(lines, startIndex) {
    const line = lines[startIndex].trim();
    const match = line.match(/journey\s+(\w+)\(([^)]*)\)\s*\{/);
    
    if (!match) {
      this.error(`Invalid journey declaration: ${line}`);
      return startIndex + 1;
    }

    const [, name, params] = match;
    
    if (this.target === 'javascript') {
      this.emit(`async function ${name}(${params}) {`);
    } else if (this.target === 'roblox') {
      this.emit(`function ${name}(${params})`);
    }
    this.indent++;

    let i = startIndex + 1;
    while (i < lines.length && !lines[i].trim().startsWith('}')) {
      const bodyLine = lines[i].trim();
      
      if (bodyLine && !bodyLine.startsWith('#') && !bodyLine.includes('platform:')) {
        if (bodyLine.startsWith('sync ')) {
          i = this.compileSync(lines, i);
        } else if (bodyLine.startsWith('when ')) {
          i = this.compileWhen(lines, i);
        } else if (bodyLine.startsWith('notify ')) {
          i = this.compileNotify(lines, i);
        } else if (bodyLine.startsWith('reveal ')) {
          i = this.compileReveal(lines, i);
        } else {
          i++;
        }
      } else {
        i++;
      }
    }

    this.indent--;
    if (this.target === 'javascript') {
      this.emit(`}`);
    } else if (this.target === 'roblox') {
      this.emit(`end`);
    }
    this.emit(``);

    return i + 1;
  }

  // Compile 'sync' statements
  compileSync(lines, index) {
    const line = lines[index].trim();
    const match = line.match(/sync\s+(.+?)\s+across\s+\[(.+?)\]/);
    
    if (!match) {
      this.error(`Invalid sync statement: ${line}`);
      return index + 1;
    }

    const [, data, platforms] = match;
    
    if (this.target === 'javascript') {
      this.emit(`await AeThex.sync(${data}, [${platforms}]);`);
    } else if (this.target === 'roblox') {
      this.emit(`AeThex.sync(${data}, {${platforms}})`);
    }

    return index + 1;
  }

  // Compile 'when' conditionals
  compileWhen(lines, startIndex) {
    const line = lines[startIndex].trim();
    const match = line.match(/when\s+(.+?)\s*\{/);
    
    if (!match) {
      this.error(`Invalid when statement: ${line}`);
      return startIndex + 1;
    }

    const condition = match[1];
    
    if (this.target === 'javascript') {
      this.emit(`if (${condition}) {`);
    } else if (this.target === 'roblox') {
      this.emit(`if ${condition} then`);
    }
    this.indent++;

    let i = startIndex + 1;
    while (i < lines.length && !lines[i].trim().startsWith('}')) {
      const bodyLine = lines[i].trim();
      if (bodyLine && !bodyLine.startsWith('#')) {
        if (bodyLine.startsWith('sync ')) {
          i = this.compileSync(lines, i);
        } else if (bodyLine.startsWith('notify ')) {
          i = this.compileNotify(lines, i);
        } else if (bodyLine.startsWith('reveal ')) {
          i = this.compileReveal(lines, i);
        } else {
          this.emit(bodyLine);
          i++;
        }
      } else {
        i++;
      }
    }

    this.indent--;
    if (this.target === 'javascript') {
      this.emit(`}`);
    } else if (this.target === 'roblox') {
      this.emit(`end`);
    }

    return i + 1;
  }

  // Compile 'notify' statements
  compileNotify(lines, index) {
    const line = lines[index].trim();
    const match = line.match(/notify\s+"(.+)"/);
    
    if (!match) {
      this.error(`Invalid notify statement: ${line}`);
      return index + 1;
    }

    const message = match[1];
    this.emit(`AeThex.notify("${message}");`);

    return index + 1;
  }

  // Compile 'reveal' statements
  compileReveal(lines, index) {
    const line = lines[index].trim();
    const match = line.match(/reveal\s+(.+)/);
    
    if (!match) {
      this.error(`Invalid reveal statement: ${line}`);
      return index + 1;
    }

    const data = match[1];
    this.emit(`AeThex.reveal(${data});`);

    return index + 1;
  }

  // Compile 'import' statements
  compileImport(lines, index) {
    const line = lines[index].trim();
    const match = line.match(/import\s+\{([^}]+)\}\s+from\s+"(.+)"/);
    
    if (!match) {
      this.error(`Invalid import statement: ${line}`);
      return index + 1;
    }

    const [, imports, module] = match;
    
    if (this.target === 'javascript') {
      this.emit(`import { ${imports} } from "${module}";`);
    } else if (this.target === 'roblox') {
      this.emit(`-- Import: ${imports} from ${module}`);
      this.emit(`local ${imports.split(',')[0].trim()} = require(game.ServerScriptService.${module.replace(/@aethex\//,'')})`);
    }

    return index + 1;
  }

  // Format errors for display
  formatErrors() {
    if (this.errors.length === 0 && this.warnings.length === 0) {
      return '✅ Compilation successful!';
    }

    let output = '';
    
    if (this.errors.length > 0) {
      output += '❌ Compilation failed with errors:\n\n';
      this.errors.forEach(err => {
        output += `  ${this.sourceFile}:${err.line} - ${err.message}\n`;
      });
    }

    if (this.warnings.length > 0) {
      output += '\n⚠️  Warnings:\n\n';
      this.warnings.forEach(warn => {
        output += `  ${this.sourceFile}:${warn.line} - ${warn.message}\n`;
      });
    }

    return output;
  }
}

// CLI Interface
if (require.main === module) {
  const args = process.argv.slice(2);
  
  if (args.length === 0) {
    console.log(`
AeThex Language Compiler v1.0

Usage:
  aethex <file.aethex> [options]

Options:
  --target <platform>    Target platform: javascript, roblox, uefn, unity (default: javascript)
  --output <file>        Output file path
  --help                 Show this help

Examples:
  aethex myapp.aethex
  aethex myapp.aethex --target roblox --output game.lua
    `);
    process.exit(0);
  }

  const inputFile = args[0];
  const targetIndex = args.indexOf('--target');
  const outputIndex = args.indexOf('--output');
  
  const target = targetIndex !== -1 ? args[targetIndex + 1] : 'javascript';
  const outputFile = outputIndex !== -1 ? args[outputIndex + 1] : null;

  if (!fs.existsSync(inputFile)) {
    console.error(`❌ File not found: ${inputFile}`);
    process.exit(1);
  }

  const sourceCode = fs.readFileSync(inputFile, 'utf-8');
  const compiler = new AeThexCompiler({ target, sourceFile: inputFile });
  const result = compiler.compile(sourceCode);

  console.log(compiler.formatErrors());

  if (result.success) {
    if (outputFile) {
      fs.writeFileSync(outputFile, result.code);
      console.log(`\n✅ Compiled to: ${outputFile}`);
    } else {
      console.log('\n--- Compiled Output ---\n');
      console.log(result.code);
    }
  } else {
    process.exit(1);
  }
}

module.exports = AeThexCompiler;
