/*
 * Copyright 2026 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <memory>
#include <sstream>
#include <unordered_map>
#include <unordered_set>
#include <variant>
#include <vector>

#include "cfg/wto.h"
#include "gtest/gtest.h"

using namespace wasm;

namespace {

// The WTO utility is parameterized on the BasicBlock type associated with a
// CFG. Since BasicBlock itself contains a user-provided Contents type, there is
// no canonical BasicBlock type ready to use. Since we don't need a full
// CFGWalker, just create a mini version of CFGWalker for testing that has all
// the expected associated types and fields.
struct TestCFG {
  struct Contents {
    bool inQueue = false;
    Index index = 0;
  };

  struct BasicBlock {
    Contents contents;
    std::vector<BasicBlock*> out;
    std::vector<BasicBlock*> in;
  };

  std::vector<std::unique_ptr<BasicBlock>> basicBlocks;
  std::vector<BasicBlock*> loopTops;
  BasicBlock* entry = nullptr;

  explicit TestCFG(Index numBlocks) {
    basicBlocks.reserve(numBlocks);
    for (Index i = 0; i < numBlocks; ++i) {
      auto block = std::make_unique<BasicBlock>();
      block->contents.index = i;
      basicBlocks.push_back(std::move(block));
    }
    if (numBlocks > 0) {
      entry = basicBlocks[0].get();
    }
  }

  void addEdge(Index u, Index v) {
    assert(u < basicBlocks.size());
    assert(v < basicBlocks.size());
    basicBlocks[u]->out.push_back(basicBlocks[v].get());
    basicBlocks[v]->in.push_back(basicBlocks[u].get());
    if (u >= v) {
      loopTops.push_back(basicBlocks[v].get());
    }
  }
};

// Index-based mirror of a Weak Topological Ordering used in tests so that:
//   1. Expected orderings can be written concisely with block indices (e.g.
//      `WTOList{0, C({1, 2}), 3}`) and pretty-printed on failure.
//   2. Test assertions remain independent of the internal representation of
//      `WeakTopologicalOrdering` (which will be flattened into a contiguous
//      entry array in a follow-on commit).
struct WTOCycle;
struct WTOElem;
using WTOList = std::vector<WTOElem>;

struct WTOCycle {
  WTOList elems;

  WTOCycle(std::initializer_list<WTOElem> list);
  explicit WTOCycle(WTOList elems);

  Index head() const;
  bool operator==(const WTOCycle& other) const;
};

struct WTOElem : std::variant<Index, WTOCycle> {
  using Base = std::variant<Index, WTOCycle>;
  using Base::Base;
  WTOElem(Index v) : Base(v) {}
  WTOElem(int v) : Base(Index(v)) {}
  WTOElem(WTOCycle c) : Base(std::move(c)) {}
};

WTOCycle::WTOCycle(std::initializer_list<WTOElem> list) : elems(list) {}
WTOCycle::WTOCycle(WTOList elems) : elems(std::move(elems)) {}
Index WTOCycle::head() const { return std::get<Index>(elems.front()); }
bool WTOCycle::operator==(const WTOCycle& other) const {
  return elems == other.elems;
}

WTOCycle C(std::initializer_list<WTOElem> list) { return WTOCycle(list); }

std::ostream& operator<<(std::ostream& os, const WTOElem& elem);
std::ostream& operator<<(std::ostream& os, const WTOList& list);

std::ostream& operator<<(std::ostream& os, const WTOCycle& cycle) {
  return os << "(" << cycle.elems << ")";
}

std::ostream& operator<<(std::ostream& os, const WTOElem& elem) {
  if (auto* v = std::get_if<Index>(&elem)) {
    return os << *v;
  }
  return os << std::get<WTOCycle>(elem);
}

std::ostream& operator<<(std::ostream& os, const WTOList& list) {
  for (size_t i = 0; i < list.size(); ++i) {
    if (i > 0) {
      os << " ";
    }
    os << list[i];
  }
  return os;
}

using BasicBlock = TestCFG::BasicBlock;

WTOList toIndexWTO(const WeakTopologicalOrdering<BasicBlock>& wto) {
  constexpr Index NoIndex = WeakTopologicalOrdering<BasicBlock>::NoIndex;
  std::vector<std::pair<Index, WTOElem>> stack;
  for (Index pc = 0; pc < wto.entries.size(); ++pc) {
    const auto& entry = wto.entries[pc];
    if (entry.cycleTarget == NoIndex) {
      stack.emplace_back(pc, WTOElem(entry.block->contents.index));
    } else {
      EXPECT_EQ(entry.block, wto.entries[entry.cycleTarget].block);
      size_t start = stack.size();
      while (stack[start - 1].first != entry.cycleTarget) {
        --start;
      }
      WTOList cycleElems;
      for (size_t i = start - 1; i < stack.size(); ++i) {
        cycleElems.push_back(std::move(stack[i].second));
      }
      stack.erase(stack.begin() + start, stack.end());
      stack.back() = {NoIndex, WTOElem(WTOCycle(std::move(cycleElems)))};
    }
  }
  WTOList dst;
  for (auto& [_, elem] : stack) {
    dst.push_back(std::move(elem));
  }
  return dst;
}

// Check the formal properties of a Weak Topological Ordering (Bourdoncle 1993,
// Definition 1) over the reachable subgraph of `cfg`.
void verifyWTOInvariants(const TestCFG& cfg, const WTOList& wto) {
  std::vector<Index> flatOrder;
  std::unordered_map<Index, size_t> pos;
  std::unordered_map<Index, std::unordered_set<Index>> cycleMembers;

  auto walk = [&](auto& self,
                  const WTOList& list,
                  std::vector<Index>& activeHeads) -> void {
    for (const auto& elem : list) {
      if (auto* v = std::get_if<Index>(&elem)) {
        // Every vertex appears at most once in the flattened ordering.
        EXPECT_FALSE(pos.contains(*v)) << "Duplicate vertex " << *v;
        pos[*v] = flatOrder.size();
        flatOrder.push_back(*v);
        for (Index head : activeHeads) {
          cycleMembers[head].insert(*v);
        }
      } else {
        // Every cycle is non-empty and its head (first element) is a single
        // vertex, not a nested cycle.
        const auto& cycle = std::get<WTOCycle>(elem);
        ASSERT_FALSE(cycle.elems.empty()) << "Empty cycle in WTO";
        ASSERT_TRUE(std::holds_alternative<Index>(cycle.elems.front()))
          << "Cycle head must be a single vertex, not a nested cycle";
        Index head = cycle.head();
        activeHeads.push_back(head);
        self(self, cycle.elems, activeHeads);
        activeHeads.pop_back();
      }
    }
  };

  std::vector<Index> activeHeads;
  walk(walk, wto, activeHeads);

  // Check invariants for edges u -> v.
  for (Index u : flatOrder) {
    for (auto* succ : cfg.basicBlocks[u]->out) {
      Index v = succ->contents.index;
      // Every reachable vertex appears at least once in the ordering.
      ASSERT_TRUE(pos.contains(v))
        << "Reachable vertex " << v << " missing from WTO";
      if (pos[u] >= pos[v]) {
        // Backedges must be to the head of a cycle containing both v and u.
        ASSERT_TRUE(cycleMembers.contains(v))
          << "Back-edge " << u << " -> " << v << " targets non-head vertex "
          << v;
        EXPECT_TRUE(cycleMembers[v].contains(u))
          << "Back-edge " << u << " -> " << v
          << " is not enclosed in the cycle headed by " << v;
      }
    }
  }
}

WTOList getWTO(TestCFG& cfg) {
  WeakTopologicalOrdering<BasicBlock> wto(cfg.basicBlocks);
  auto list = toIndexWTO(wto);
  EXPECT_EQ(list, list);
  verifyWTOInvariants(cfg, list);
  return list;
}

} // namespace

TEST(WTOTest, Empty) {
  TestCFG cfg(0);
  EXPECT_EQ(getWTO(cfg), WTOList{});
}

TEST(WTOTest, Singleton) {
  TestCFG cfg(1);
  EXPECT_EQ(getWTO(cfg), WTOList{0});
}

TEST(WTOTest, LinearChain) {
  TestCFG cfg(3);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 2);
  EXPECT_EQ(getWTO(cfg), (WTOList{0, 1, 2}));
}

TEST(WTOTest, Diamond) {
  {
    TestCFG cfg(4);
    cfg.addEdge(0, 1);
    cfg.addEdge(0, 2);
    cfg.addEdge(1, 3);
    cfg.addEdge(2, 3);
    EXPECT_EQ(getWTO(cfg), (WTOList{0, 1, 2, 3}));
  }
  {
    // Reversed edge insertion order at the split and join.
    TestCFG cfg(4);
    cfg.addEdge(0, 2);
    cfg.addEdge(0, 1);
    cfg.addEdge(2, 3);
    cfg.addEdge(1, 3);
    EXPECT_EQ(getWTO(cfg), (WTOList{0, 1, 2, 3}));
  }
  {
    // Asymmetric diamond (one arm has two blocks, the other has one) under both
    // valid RPO block orderings.
    TestCFG leftFirst(5);
    leftFirst.addEdge(0, 1);
    leftFirst.addEdge(1, 2);
    leftFirst.addEdge(0, 3);
    leftFirst.addEdge(2, 4);
    leftFirst.addEdge(3, 4);
    EXPECT_EQ(getWTO(leftFirst), (WTOList{0, 1, 2, 3, 4}));

    TestCFG rightFirst(5);
    rightFirst.addEdge(0, 2);
    rightFirst.addEdge(2, 3);
    rightFirst.addEdge(0, 1);
    rightFirst.addEdge(3, 4);
    rightFirst.addEdge(1, 4);
    EXPECT_EQ(getWTO(rightFirst), (WTOList{0, 1, 2, 3, 4}));
  }
}

TEST(WTOTest, SelfLoop) {
  TestCFG cfg(3);
  cfg.addEdge(0, 0);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 1);
  cfg.addEdge(1, 2);
  EXPECT_EQ(getWTO(cfg), (WTOList{C({0}), C({1}), 2}));
}

TEST(WTOTest, SimpleCycle) {
  TestCFG cfg(2);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 0);
  EXPECT_EQ(getWTO(cfg), (WTOList{C({0, 1})}));
}

TEST(WTOTest, ThreeNodeCycle) {
  TestCFG cfg(3);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 2);
  cfg.addEdge(2, 0);
  EXPECT_EQ(getWTO(cfg), (WTOList{C({0, 1, 2})}));
}

TEST(WTOTest, SharedLoopHeader) {
  // Two loops sharing header 0: 0 -> 1 -> 0 and 0 -> 2 -> 0.
  TestCFG cfg(3);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 0);
  cfg.addEdge(0, 2);
  cfg.addEdge(2, 0);
  EXPECT_EQ(getWTO(cfg), (WTOList{C({0, 1, 2})}));
}

TEST(WTOTest, BourdonclePaperExample) {
  // The example control-flow graph from Bourdoncle's 1993 paper "Efficient
  // chaotic iteration strategies with widenings", Figure 1 (0-indexed: vertices
  // 0..7 correspond to 1..8 in the paper):
  //   0 -> 1
  //   1 -> 2, 1 -> 7
  //   2 -> 3
  //   3 -> 4, 3 -> 6
  //   4 -> 5
  //   5 -> 4, 5 -> 6
  //   6 -> 2, 6 -> 7
  // Expected WTO from the paper: 0 1 (2 3 (4 5) 6) 7
  TestCFG cfg(8);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 2);
  cfg.addEdge(1, 7);
  cfg.addEdge(2, 3);
  cfg.addEdge(3, 4);
  cfg.addEdge(3, 6);
  cfg.addEdge(4, 5);
  cfg.addEdge(5, 4);
  cfg.addEdge(5, 6);
  cfg.addEdge(6, 2);
  cfg.addEdge(6, 7);
  auto wto = getWTO(cfg);
  EXPECT_EQ(wto, (WTOList{0, 1, C({2, 3, C({4, 5}), 6}), 7}));
  std::ostringstream ss;
  ss << wto;
  EXPECT_EQ(ss.str(), "0 1 (2 3 (4 5) 6) 7");
}

TEST(WTOTest, LoopHeaderDominatesExit) {
  // Same as Bourdoncle's paper graph, except block 7 is only reachable from
  // block 6 (no direct edge 1 -> 7). Block 2 dominates block 7 even though
  // block 7 is outside the natural loop of 2. Block 7 must remain outside the
  // cycle of 2.
  TestCFG cfg(8);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 2);
  cfg.addEdge(2, 3);
  cfg.addEdge(3, 4);
  cfg.addEdge(3, 6);
  cfg.addEdge(4, 5);
  cfg.addEdge(5, 4);
  cfg.addEdge(5, 6);
  cfg.addEdge(6, 2);
  cfg.addEdge(6, 7);
  EXPECT_EQ(getWTO(cfg), (WTOList{0, 1, C({2, 3, C({4, 5}), 6}), 7}));
}

TEST(WTOTest, DiamondOfLoops) {
  // 01 -> 23 -> 67 and 01 -> 45 -> 67, where each pair is a 2-block loop.
  TestCFG cfg(8);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 0);
  cfg.addEdge(1, 2);
  cfg.addEdge(1, 4);

  cfg.addEdge(2, 3);
  cfg.addEdge(3, 2);
  cfg.addEdge(3, 6);

  cfg.addEdge(4, 5);
  cfg.addEdge(5, 4);
  cfg.addEdge(5, 6);

  cfg.addEdge(6, 7);
  cfg.addEdge(7, 6);

  EXPECT_EQ(getWTO(cfg), (WTOList{C({0, 1}), C({2, 3}), C({4, 5}), C({6, 7})}));
}

TEST(WTOTest, UnreachableBlocks) {
  // Blocks 0, 1, 2 form a reachable loop 0 -> 1 -> 2 -> 1.
  // Blocks 3, 4 form an unreachable cycle 3 -> 4 -> 3 with edges into 1 and 2.
  TestCFG cfg(5);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 2);
  cfg.addEdge(2, 1);
  cfg.addEdge(3, 4);
  cfg.addEdge(4, 3);
  cfg.addEdge(3, 1);
  cfg.addEdge(4, 2);
  EXPECT_EQ(getWTO(cfg), (WTOList{0, C({1, 2})}));
}

TEST(WTOTest, WorklistEvaluation) {
  // Evaluate a chaotic iteration sequence on Bourdoncle's paper graph where the
  // inner cycle (4 5) stabilizes in 2 iterations and the outer cycle
  // (2 3 (4 5) 6) stabilizes in 2 iterations.
  TestCFG cfg(8);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 2);
  cfg.addEdge(1, 7);
  cfg.addEdge(2, 3);
  cfg.addEdge(3, 4);
  cfg.addEdge(3, 6);
  cfg.addEdge(4, 5);
  cfg.addEdge(5, 4);
  cfg.addEdge(5, 6);
  cfg.addEdge(6, 2);
  cfg.addEdge(6, 7);

  WTOWorklist<TestCFG> work(cfg);
  work.push(cfg.entry);

  std::vector<Index> visits;
  unsigned count4 = 0;
  unsigned count2 = 0;
  work.run([&](BasicBlock* block) {
    Index id = block->contents.index;
    visits.push_back(id);
    for (auto* out : block->out) {
      Index outId = out->contents.index;
      if (id == 5 && outId == 4) {
        if (++count4 < 2) {
          work.push(out);
        }
      } else if (id == 6 && outId == 2) {
        if (++count2 < 2) {
          count4 = 0;
          work.push(out);
        }
      } else {
        work.push(out);
      }
    }
  });

  // Expected recursive evaluation order:
  // 0, 1,
  // first iteration of (2 3 (4 5) 6): 2, 3, 4, 5, 4, 5, 6,
  // second iteration of (2 3 (4 5) 6): 2, 3, 4, 5, 4, 5, 6,
  // 7
  EXPECT_EQ(
    visits,
    (std::vector<Index>{0, 1, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 7}));
}

TEST(WTOTest, WorklistSelectivePropagation) {
  // In Bourdoncle's graph, test when block 3 only queues block 6 (skipping the
  // inner cycle (4 5) completely) and block 6 does not re-queue block 2.
  TestCFG cfg(8);
  cfg.addEdge(0, 1);
  cfg.addEdge(1, 2);
  cfg.addEdge(1, 7);
  cfg.addEdge(2, 3);
  cfg.addEdge(3, 4);
  cfg.addEdge(3, 6);
  cfg.addEdge(4, 5);
  cfg.addEdge(5, 4);
  cfg.addEdge(5, 6);
  cfg.addEdge(6, 2);
  cfg.addEdge(6, 7);

  WTOWorklist<TestCFG> work(cfg);
  work.push(cfg.entry);

  std::vector<Index> visits;
  work.run([&](BasicBlock* block) {
    Index id = block->contents.index;
    visits.push_back(id);
    if (id == 0) {
      work.push(cfg.basicBlocks[1].get());
    } else if (id == 1) {
      work.push(cfg.basicBlocks[2].get());
    } else if (id == 2) {
      work.push(cfg.basicBlocks[3].get());
    } else if (id == 3) {
      work.push(cfg.basicBlocks[6].get());
    } else if (id == 6) {
      work.push(cfg.basicBlocks[7].get());
    }
  });

  EXPECT_EQ(visits, (std::vector<Index>{0, 1, 2, 3, 6, 7}));
}
