#include <exception>
#include <fstream>
#include <iostream>
#include <stdexcept>

#include "frontend/AntlrDriver.h"
#include "frontend/AstBuilder.h"
#include "ir/IR.h"
#include "irgen/IRGen.h"
#include "mir/MIR.h"
#include "sem/Sema.h"
#include "utils/CLI.h"
#include "utils/Log.h"
#include "ast/AstNodes.h"

int main(int argc, char** argv) {
  try {
    auto opts = ParseCLI(argc, argv);
    if (opts.show_help) {
      PrintHelp(std::cout);
      return 0;
    }
    auto antlr = ParseFileWithAntlr(opts.input);
    auto ast = BuildAst(antlr.tree);
    bool need_blank_line = false;
    if (opts.emit_ast) {
      ast::PrintAST(*ast);  // 调试 AST
      need_blank_line = true;
    }
    if (!opts.ast_dot_output.empty()) {
      std::ofstream dot_out(opts.ast_dot_output);
      if (!dot_out) {
        throw std::runtime_error("无法写入 AST DOT 文件: " + opts.ast_dot_output);
      }
      ast::PrintASTDot(*ast, dot_out);
    }
    ast = RunSema(std::move(ast));
    // IR 生成：当前使用 IRGenDriver.cpp 里的最小实现，
    // 同学们可以在 irgen/ 目录下按提示自行完善或替换实现。
    auto module = GenerateIR(*ast);

    if (opts.emit_ir) {
      ir::IRPrinter printer;
      if (need_blank_line) {
        std::cout << "\n";
      }
      printer.Print(*module);
      need_blank_line = true;
    }

    if (opts.emit_asm) {
      auto machine_func = mir::LowerToMIR(*module);
      mir::RunRegAlloc(*machine_func);
      mir::RunFrameLowering(*machine_func);
      if (need_blank_line) {
        std::cout << "\n";
      }
      mir::PrintAsm(*machine_func, std::cout);
    }
  } catch (const std::exception& ex) {
    std::cerr << "error: " << ex.what() << "\n";
    return 1;
  }
  return 0;
}
