#include "irgen/IRGen.h"

#include <stdexcept>

#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"

// 语句生成当前只实现了最小子集。
// 目前支持：
// - return <exp>;
//
// 还未支持：
// - 赋值语句
// - if / while 等控制流
// - 空语句、块语句嵌套分发之外的更多语句形态

std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
  if (!ctx) {
    throw std::runtime_error(FormatError("irgen", "缺少语句"));
  }
  if (ctx->lValue() && ctx->ASSIGN() && ctx->exp()) {
    ir::Value* rhs = EvalExpr(*ctx->exp());
    ir::Value* slot = ResolveStorage(ctx->lValue());
    if (!slot) {
      throw std::runtime_error(
          FormatError("irgen", "赋值目标未找到存储槽位: " +
                                   (ctx->lValue()->ID()
                                        ? ctx->lValue()->ID()->getText()
                                        : "?")));
    }
    builder_.CreateStore(rhs, slot);
    return BlockFlow::Continue;
  }
  if (ctx->blockStmt()) {
    ctx->blockStmt()->accept(this);
    return builder_.GetInsertBlock() && builder_.GetInsertBlock()->HasTerminator()
               ? BlockFlow::Terminated
               : BlockFlow::Continue;
  }
  if (ctx->IF()) {
    if (!ctx->cond() || ctx->stmt().empty()) {
      throw std::runtime_error(FormatError("irgen", "if 语句不完整"));
    }
    auto* then_bb = func_->CreateBlock(NextBlockName());
    auto* merge_bb = func_->CreateBlock(NextBlockName());
    auto* else_bb = ctx->ELSE() ? func_->CreateBlock(NextBlockName()) : merge_bb;

    ir::Value* cond = ToBoolValue(EvalCond(*ctx->cond()));
    builder_.CreateCondBr(cond, then_bb, else_bb);

    builder_.SetInsertPoint(then_bb);
    auto then_flow = std::any_cast<BlockFlow>(ctx->stmt(0)->accept(this));
    bool then_term = (then_flow == BlockFlow::Terminated);
    if (then_flow != BlockFlow::Terminated) {
      builder_.CreateBr(merge_bb);
    }

    bool else_term = false;
    if (ctx->ELSE()) {
      builder_.SetInsertPoint(else_bb);
      auto else_flow = std::any_cast<BlockFlow>(ctx->stmt(1)->accept(this));
      else_term = (else_flow == BlockFlow::Terminated);
      if (else_flow != BlockFlow::Terminated) {
        builder_.CreateBr(merge_bb);
      }
    }

    if (ctx->ELSE() && then_term && else_term) {
      // 两个分支都终结时，merge 块不可达；补一个自环 terminator 以满足结构校验。
      builder_.SetInsertPoint(merge_bb);
      builder_.CreateBr(merge_bb);
      return BlockFlow::Terminated;
    }

    builder_.SetInsertPoint(merge_bb);
    return BlockFlow::Continue;
  }
  if (ctx->WHILE()) {
    if (!ctx->cond() || ctx->stmt().empty()) {
      throw std::runtime_error(FormatError("irgen", "while 语句不完整"));
    }
    auto* cond_bb = func_->CreateBlock(NextBlockName());
    auto* body_bb = func_->CreateBlock(NextBlockName());
    auto* exit_bb = func_->CreateBlock(NextBlockName());

    builder_.CreateBr(cond_bb);
    builder_.SetInsertPoint(cond_bb);
    ir::Value* cond = ToBoolValue(EvalCond(*ctx->cond()));
    builder_.CreateCondBr(cond, body_bb, exit_bb);

    loop_stack_.push_back({cond_bb, exit_bb});
    builder_.SetInsertPoint(body_bb);
    auto body_flow = std::any_cast<BlockFlow>(ctx->stmt(0)->accept(this));
    if (body_flow != BlockFlow::Terminated) {
      builder_.CreateBr(cond_bb);
    }
    loop_stack_.pop_back();

    builder_.SetInsertPoint(exit_bb);
    return BlockFlow::Continue;
  }
  if (ctx->BREAK()) {
    if (loop_stack_.empty()) {
      throw std::runtime_error(FormatError("irgen", "break 不在循环中"));
    }
    builder_.CreateBr(loop_stack_.back().break_target);
    return BlockFlow::Terminated;
  }
  if (ctx->CONTINUE()) {
    if (loop_stack_.empty()) {
      throw std::runtime_error(FormatError("irgen", "continue 不在循环中"));
    }
    builder_.CreateBr(loop_stack_.back().continue_target);
    return BlockFlow::Terminated;
  }
  if (ctx->returnStmt()) {
    return ctx->returnStmt()->accept(this);
  }
  if (ctx->exp()) {
    EvalExpr(*ctx->exp());
    return BlockFlow::Continue;
  }
  if (ctx->SEMICOLON()) {
    return BlockFlow::Continue;
  }
  throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型"));
}


std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
  if (!ctx) {
    throw std::runtime_error(FormatError("irgen", "缺少 return 语句"));
  }
  if (!ctx->exp()) {
    // void 函数的 return;
    builder_.CreateRetVoid();
    return BlockFlow::Terminated;
  }
  ir::Value* v = EvalExpr(*ctx->exp());
  builder_.CreateRet(v);
  return BlockFlow::Terminated;
}
