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

export interface CompileResult {
  code: string;
  errors: CompileError[];
  warnings: CompileWarning[];
  success: boolean;
}

export interface CompileError {
  type: 'error';
  message: string;
  line: number;
  file: string;
}

export interface CompileWarning {
  type: 'warning';
  message: string;
  line: number;
  file: string;
}

export type CompileTarget = 'javascript' | 'roblox' | 'uefn' | 'unity';

export class AeThexCompiler {
  private target: CompileTarget;
  private output: string[];
  private indent: number;
  private errors: CompileError[];
  private warnings: CompileWarning[];
  private line: number;
  private sourceFile: string;

  constructor(options: { target?: CompileTarget; sourceFile?: string } = {}) {
    this.target = options.target || 'javascript';
    this.output = [];
    this.indent = 0;
    this.errors = [];
    this.warnings = [];
    this.line = 1;
    this.sourceFile = options.sourceFile || 'unknown';
  }

  private error(message: string, line: number = this.line) {
    this.errors.push({
      type: 'error',
      message,
      line,
      file: this.sourceFile
    });
  }

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

  private emit(code: string) {
    const indentation = '  '.repeat(this.indent);
    this.output.push(indentation + code);
  }

  compile(sourceCode: string): CompileResult {
    this.output = [];
    this.errors = [];
    this.warnings = [];
    this.line = 1;

    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('import ')) {
          i = this.compileImport(lines, i);
        } else if (line.startsWith('let ')) {
          this.emit(line.replace('let ', 'const ') + ';');
          i++;
        } else if (line.startsWith('when ')) {
          this.emit('if (' + line.substring(5) + ') {');
          this.indent++;
          i++;
        } else if (line === '}' || line.startsWith('}')) {
          this.indent--;
          this.emit('}');
          i++;
        } else if (line.startsWith('notify ')) {
          const msg = line.substring(7);
          this.emit(`console.log(${msg});`);
          i++;
        } else if (line.startsWith('sync ')) {
          this.compileSync(line);
          i++;
        } else if (line.startsWith('reveal ')) {
          const expr = line.substring(7);
          this.emit(`return ${expr};`);
          i++;
        } else if (line === 'otherwise {' || line.startsWith('} otherwise {')) {
          if (line.startsWith('}')) {
            this.indent--;
            this.emit('} else {');
            this.indent++;
          } else {
            this.emit('} else {');
          }
          i++;
        } else {
          this.emit(line);
          i++;
        }
      } catch (err: any) {
        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
    };
  }

  private addRuntime() {
    if (this.target === 'javascript') {
      this.emit('// AeThex Runtime');
      this.emit('// Generated by AeThex Compiler v1.0');
      this.emit('');
    } else if (this.target === 'roblox') {
      this.emit('-- AeThex Runtime (Roblox/Lua)');
      this.emit('-- Generated by AeThex Compiler v1.0');
      this.emit('');
    }
  }

  private compileReality(lines: string[], startIndex: number): number {
    const line = lines[startIndex].trim();
    const match = line.match(/reality\s+(\w+)\s*\{/);

    if (!match) {
      this.error('Invalid reality syntax');
      return startIndex + 1;
    }

    const realityName = match[1];
    this.emit(`// Reality: ${realityName}`);

    let i = startIndex + 1;
    while (i < lines.length && !lines[i].trim().startsWith('}')) {
      i++;
    }

    return i + 1;
  }

  private compileJourney(lines: string[], startIndex: number): number {
    const line = lines[startIndex].trim();
    const match = line.match(/journey\s+(\w+)\((.*?)\)\s*\{/);

    if (!match) {
      this.error('Invalid journey syntax');
      return startIndex + 1;
    }

    const funcName = match[1];
    const params = match[2];

    if (this.target === 'javascript') {
      this.emit(`async function ${funcName}(${params}) {`);
    } else if (this.target === 'roblox') {
      this.emit(`local function ${funcName}(${params})`);
    }

    this.indent++;

    return startIndex + 1;
  }

  private compileImport(lines: string[], startIndex: number): number {
    const line = lines[startIndex].trim();
    const match = line.match(/import\s+\{([^}]+)\}\s+from\s+"([^"]+)"/);

    if (!match) {
      this.error('Invalid import syntax');
      return startIndex + 1;
    }

    const imports = match[1].trim();
    const module = match[2];

    if (this.target === 'javascript') {
      // For browser, we'll use the core module directly
      if (module.includes('@aethex/core')) {
        this.emit(`// Import from @aethex/core: ${imports}`);
        this.emit(`// Using built-in AeThex runtime`);
      } else {
        this.emit(`import { ${imports} } from "${module}";`);
      }
    }

    return startIndex + 1;
  }

  private compileSync(line: string) {
    // sync passport across [roblox, web]
    this.emit('// TODO: Implement sync');
  }
}
