// Copyright 2026 The GN Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gn/build_file_editor.h"

#include <algorithm>

#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "gn/build_settings.h"
#include "gn/command_format.h"
#include "gn/edit_subcommands.h"
#include "gn/filesystem_utils.h"
#include "gn/input_file.h"
#include "gn/label.h"
#include "gn/loader.h"
#include "gn/parse_tree.h"
#include "gn/parser.h"
#include "gn/scope.h"
#include "gn/string_atom.h"
#include "gn/tokenizer.h"
#include "gn/value.h"

namespace {

std::optional<Value> AsLiteralValue(const ParseNode* node) {
  auto* literal = node->AsLiteral();
  if (!literal) {
    return std::nullopt;
  }
  Scope scope(static_cast<const Settings*>(nullptr));
  Err err;
  Value v = literal->Execute(&scope, &err);
  // Literals should *usually* not error out, but there are some cases they do.
  // Eg. the string literal "${foo}" with no variable foo in scope.
  // When this happens, just treat them as if they're opaque things we don't
  // know about.
  if (err.has_error()) {
    return std::nullopt;
  }
  return v;
}

std::optional<std::string> AsStringLiteral(const ParseNode* node) {
  auto val = AsLiteralValue(node);
  if (val && val->type() == Value::STRING) {
    return std::move(val->string_value());
  }
  return std::nullopt;
}

// Returns true if a node in the tree is a literal node matching the user's
// request.
bool Matches(const EditTarget& target,
             const ParseNode* node,
             const Value& value) {
  auto got_value = AsLiteralValue(node);
  if (!got_value) {
    return false;
  }
  if (*got_value == value) {
    return true;
  }
  if (got_value->type() == Value::STRING && value.type() == Value::STRING) {
    // If the user requests "remove deps //foo:bar" //foo:baz, and //foo:baz
    // contains the literal ":bar", that should match.
    Err err;
    Label got_label =
        Label::Resolve(target.label.dir(), "", target.label.GetToolchainLabel(),
                       *got_value, &err);
    Label want_label = Label::Resolve(
        target.label.dir(), "", target.label.GetToolchainLabel(), value, &err);
    return !err.has_error() && got_label == want_label;
  }
  return false;
}

// Finds matching nodes in an expression.
template <typename T>
void FindExpressionRecursive(
    ParseNode* node,
    std::vector<ParseNode*>& stack,
    const std::function<std::optional<T>(TreeNode&)>& transform,
    std::vector<T>* results) {
  if (!node)
    return;

  stack.push_back(node);

  TreeNode node_ref(stack);
  if (auto mapped = transform(node_ref)) {
    results->push_back(std::move(*mapped));
  }

  if (auto* list = node->AsListMut()) {
    for (auto& item : list->contents()) {
      FindExpressionRecursive(item.get(), stack, transform, results);
    }
  } else if (auto* op = node->AsBinaryOpMut()) {
    if (op->op().type() == Token::PLUS) {
      FindExpressionRecursive(op->left(), stack, transform, results);
      FindExpressionRecursive(op->right(), stack, transform, results);
    }
  }

  stack.pop_back();
}

// Finds matching nodes in an expression.
template <typename T>
std::vector<T> FindExpression(
    const TreeNode& root,
    const std::function<std::optional<T>(TreeNode&)>& transform) {
  std::vector<T> results;
  std::vector<ParseNode*> stack = root.stack();
  stack.pop_back();
  FindExpressionRecursive<T>(root.node(), stack, transform, &results);
  return results;
}

// Resolves a single LabelPattern to matching SourceFiles.
Result<std::vector<SourceFile>> ResolvePatternToFiles(
    const BuildSettings* build_settings,
    const Loader* loader,
    const LabelPattern& pattern) {
  std::vector<SourceFile> matched_files;
  auto add_dir = [&](const SourceDir& dir) {
    auto build_file = loader->BuildFileForLabel(Label(dir, "dummy"));
    if (base::PathExists(build_settings->GetFullPath(build_file))) {
      matched_files.push_back(build_file);
    }
  };

  add_dir(pattern.dir());

  if (pattern.type() == LabelPattern::MATCH ||
      pattern.type() == LabelPattern::DIRECTORY) {
    if (matched_files.empty()) {
      return Err(
          Location(),
          "Build file does not exist: " +
              loader->BuildFileForLabel(Label(pattern.dir(), "dummy")).value());
    }
    return matched_files;
  }

  base::FilePath disk_path = build_settings->GetFullPath(pattern.dir());
  if (!base::DirectoryExists(disk_path)) {
    return Err(Location(),
               "Directory does not exist: " + pattern.dir().value());
  }

  base::FileEnumerator traverser(disk_path, /*recursive=*/true,
                                 base::FileEnumerator::DIRECTORIES);
  for (base::FilePath current = traverser.Next(); !current.empty();
       current = traverser.Next()) {
    base::FilePath relative;
    if (build_settings->root_path().AppendRelativePath(current, &relative)) {
      std::string source_path = "//" + FilePathToUTF8(relative) + "/";
      NormalizePath(&source_path);
      add_dir(SourceDir(source_path));
    }
  }

  return matched_files;
}

}  // namespace

std::vector<TreeNode> FindListElementInAssignment(const EditTarget& target,
                                                  const TreeNode& root,
                                                  const Value& value) {
  auto* node = root.AsAssignment();
  if (!node)
    return {};
  return FindExpression<TreeNode>(
      root.Descend(node->right()),
      [&](TreeNode& node_ref) -> std::optional<TreeNode> {
        if (node_ref.parent() && node_ref.parent()->AsList() &&
            Matches(target, node_ref.node(), value)) {
          return node_ref;
        }
        return std::nullopt;
      });
}

std::optional<ListNode*> FindListInAssignment(const TreeNode& assignment) {
  auto* op = assignment.AsAssignment();
  if (!op)
    return std::nullopt;
  auto results = FindExpression<ListNode*>(
      assignment.Descend(op->right()),
      [](TreeNode& node_ref) -> std::optional<ListNode*> {
        if (auto* list = node_ref->AsListMut()) {
          return list;
        }
        return std::nullopt;
      });
  if (results.empty())
    return std::nullopt;
  return results.front();
}

TreeNode TreeNode::Descend(ParseNode* child) const {
  std::vector<ParseNode*> s = stack_;
  s.push_back(child);
  return TreeNode(std::move(s));
}

BinaryOpNode* TreeNode::AsAssignment() const {
  if (auto* op = node()->AsBinaryOpMut()) {
    if (op->op().type() == Token::EQUAL ||
        op->op().type() == Token::PLUS_EQUALS) {
      return op;
    }
  }
  return nullptr;
}

bool TreeNode::is_conditional() const {
  DCHECK(!stack_.empty()) << "stack should never be empty";
  for (auto it = stack_.rbegin() + 1; it != stack_.rend(); ++it) {
    if ((*it)->AsCondition()) {
      return true;
    }
    // Stop at the target boundary.
    if ((*it)->AsFunctionCall()) {
      break;
    }
  }
  return false;
}

bool TreeNode::is_modification() const {
  if (const auto* op = node()->AsBinaryOp()) {
    return op->op().type() == Token::PLUS_EQUALS ||
           op->op().type() == Token::MINUS_EQUALS;
  }
  return false;
}

void TreeNode::add_todo(EditState& state, const EditTarget& target) const {
  const std::vector<std::string> lines = {
      "# TODO(gn edit: " + state.context + "):",
      "# This would normally be deleted but is conditional.",
      "# Manual intervention is required to decide whether it should "
      "actually be deleted.",
  };
  for (const auto& line : lines) {
    StringAtom atom(line);
    Token comment_token(node()->GetRange().begin(), Token::LINE_COMMENT,
                        atom.str());
    node()->comments_mutable()->append_before(std::move(comment_token));
  }
  state.needs_manual_review.insert(target.label);
}

void TreeNode::RemoveSelf(EditState& state, const EditTarget& target) const {
  if (is_conditional()) {
    add_todo(state, target);
  } else {
    RemoveSelfUnconditionally();
  }
}

TreeNode::NodeList& TreeNode::container() const {
  DCHECK(parent());
  if (auto* block = parent()->AsBlockMut()) {
    return block->statements();
  } else if (auto* list = parent()->AsListMut()) {
    return list->contents();
  } else {
    NOTREACHED() << "Unsupported parent type in container";
  }
}

TreeNode::NodeLocation TreeNode::node_location() const {
  auto& c = container();
  auto it = std::find_if(c.begin(), c.end(),
                         [this](const auto& p) { return p.get() == node(); });
  CHECK(it != c.end()) << "child node not found in parent container";
  return {c, it};
}

void TreeNode::RemoveSelfUnconditionally() const {
  auto [container, it] = node_location();
  container.erase(it);
}

LabelMatcher::LabelMatcher(SourceDir source_dir,
                           const std::vector<LabelPattern>& patterns)
    : source_dir_(std::move(source_dir)), globbed_(false) {
  for (const auto& pattern : patterns) {
    if (pattern.type() == LabelPattern::RECURSIVE_DIRECTORY &&
        source_dir_.value().starts_with(pattern.dir().value())) {
      globbed_ = true;
    } else if (pattern.type() == LabelPattern::DIRECTORY &&
               source_dir_ == pattern.dir()) {
      globbed_ = true;
    } else if (pattern.type() == LabelPattern::MATCH &&
               pattern.dir() == source_dir_) {
      if (!used_.contains(pattern.name())) {
        explicit_names_.push_back(pattern.name());
        used_[pattern.name()] = false;
      }
    }
  }
}

LabelMatcher::MatchType LabelMatcher::matches(const std::string& name) {
  if (auto it = used_.find(name); it != used_.end()) {
    it->second = true;  // Mark as used.
    return EXACT;
  }
  return globbed_ ? GLOB : NONE;
}

Result<std::vector<std::string>> LabelMatcher::explicit_target_names() {
  if (globbed_) {
    return Err(Location(),
               "Explicit target label required (wildcard patterns are not "
               "supported for this command).");
  }
  for (const auto& name : explicit_names_) {
    used_[name] = true;
  }
  return explicit_names_;
}

Err LabelMatcher::done() const {
  std::vector<std::string> unused;
  for (const auto& [name, used] : used_) {
    if (!used) {
      unused.push_back(name);
    }
  }
  if (!unused.empty()) {
    std::sort(unused.begin(), unused.end());
    std::string msg = "Target(s) not found: ";
    for (size_t i = 0; i < unused.size(); ++i) {
      if (i > 0)
        msg += ", ";
      msg += Label(source_dir_, unused[i]).GetUserVisibleName(false);
    }
    return Err(Location(), msg);
  }
  return Ok();
}

std::vector<TreeNode> EditTarget::assignments(std::string_view attr) const {
  return FindStatement<TreeNode>(
      block, [attr](TreeNode& node_ref) -> std::optional<TreeNode> {
        if (const auto* op = node_ref->AsBinaryOp()) {
          if (op->op().type() == Token::EQUAL ||
              op->op().type() == Token::PLUS_EQUALS ||
              op->op().type() == Token::MINUS_EQUALS) {
            if (const auto* left = op->left()->AsIdentifier()) {
              if (left->value().value() == attr) {
                return node_ref;
              }
            }
          }
        }
        return std::nullopt;
      });
}

void EditTarget::add_warning(EditState& state, std::string_view message) const {
  std::string full_message = "Target \"" + label.GetUserVisibleName(false) +
                             "\" " + std::string(message);
  state.warnings.push_back(Err(node.node()->GetRange().begin(), full_message));
}

Result<BuildFile> BuildFile::Create(const BuildSettings* build_settings,
                                    const SourceFile& source_file,
                                    const std::vector<LabelPattern>& patterns) {
  auto input_file = std::make_unique<InputFile>(source_file);
  base::FilePath full_path = build_settings->GetFullPath(source_file);
  if (!input_file->Load(full_path)) {
    return Err(Location(), "Could not load file: " + source_file.value());
  }

  Err err;
  std::vector<Token> tokens = Tokenizer::Tokenize(input_file.get(), &err);
  RETURN_IF_ERROR(err);

  std::unique_ptr<ParseNode> tree_root = Parser::Parse(tokens, &err);
  RETURN_IF_ERROR(err);

  LabelMatcher label_matcher(source_file.GetDir(), patterns);
  return BuildFile(build_settings, source_file, std::move(input_file),
                   std::move(tree_root), std::move(label_matcher));
}

Location BuildFile::location() const {
  return Location(input_file_.get(), 1, 1);
}

std::vector<EditTarget> BuildFile::targets(
    std::function<bool(EditTarget&)> filter) {
  if (!filter) {
    filter = [this](EditTarget& t) {
      switch (label_matcher_.matches(t.label.name())) {
        case LabelMatcher::NONE:
          return false;
        case LabelMatcher::EXACT:
          return true;
        case LabelMatcher::GLOB:
          t.is_explicit = false;
          return true;
      }
      NOTREACHED();
    };
  }
  return FindStatement<EditTarget>(
      tree_root_.get(),
      [this, &filter](TreeNode& node_ref) -> std::optional<EditTarget> {
        if (auto* func = node_ref->AsFunctionCallMut()) {
          if (func->block() && func->args() &&
              func->args()->contents().size() == 1) {
            if (auto name =
                    AsStringLiteral(func->args()->contents()[0].get())) {
              EditTarget target{
                  .is_explicit = true,
                  .label = Label(source_file_.GetDir(), *name),
                  .node = node_ref,
                  .block = func->block(),
              };
              if (filter(target)) {
                return target;
              }
            }
          }
        }
        return std::nullopt;
      });
}

std::optional<EditTarget> BuildFile::find_target(std::string_view target_name) {
  auto found = targets([target_name](const EditTarget& t) {
    return t.label.name() == target_name;
  });
  if (!found.empty()) {
    return std::move(found.front());
  }
  return std::nullopt;
}

std::unique_ptr<ParseNode> BuildFile::to_node(const Value& value) {
  auto file = std::make_unique<InputFile>(SourceFile("//dummy"));
  file->SetContents(value.ToString(true));

  Err err;
  std::vector<Token> tokens = Tokenizer::Tokenize(file.get(), &err);
  for (auto& token : tokens) {
    token.set_location(this->location());
  }
  auto parsed = Parser::ParseExpression(tokens, &err);
  extra_files_.push_back(std::move(file));
  // value.ToString() must return something parsable as input to GN.
  DCHECK(!err.has_error());
  return parsed;
}

std::unique_ptr<IdentifierNode> BuildFile::create_identifier(
    std::string_view value) {
  StringAtom atom(value);
  return std::make_unique<IdentifierNode>(
      Token(location(), Token::IDENTIFIER, atom.str()));
}

std::unique_ptr<BinaryOpNode> BuildFile::create_assignment(
    std::string_view name,
    std::unique_ptr<ParseNode> value) {
  auto left = create_identifier(name);

  auto assign = std::make_unique<BinaryOpNode>();
  assign->set_op(Token(location(), Token::EQUAL, "="));
  assign->set_left(std::move(left));
  assign->set_right(std::move(value));

  return assign;
}

std::unique_ptr<BlockNode> BuildFile::create_block(
    std::vector<std::unique_ptr<ParseNode>> statements) {
  auto block = std::make_unique<BlockNode>(BlockNode::DISCARDS_RESULT);
  block->set_begin_token(Token(location(), Token::LEFT_BRACE, "{"));
  block->set_end(
      std::make_unique<EndNode>(Token(location(), Token::RIGHT_BRACE, "}")));
  block->statements() = std::move(statements);
  return block;
}

std::unique_ptr<FunctionCallNode> BuildFile::create_target(
    std::string_view type,
    std::string_view name,
    std::unique_ptr<BlockNode> block) {
  auto func = std::make_unique<FunctionCallNode>();
  func->set_function(
      Token(location(), Token::IDENTIFIER, StringAtom(type).str()));

  auto args = std::make_unique<ListNode>();
  args->set_begin_token(Token(location(), Token::LEFT_PAREN, "("));
  args->set_end(
      std::make_unique<EndNode>(Token(location(), Token::RIGHT_PAREN, ")")));
  args->append_item(to_node(Value(nullptr, std::string(name))));
  func->set_args(std::move(args));

  func->set_block(std::move(block));
  return func;
}

Result<bool> BuildFile::Write() {
  ASSIGN_OR_RETURN(std::string formatted, commands::FormatNodeToString(root()));
  if (input_file_->contents() == formatted) {
    return false;
  }
  base::FilePath file_path = build_settings_->GetFullPath(source_file());
  if (base::WriteFile(file_path, formatted.data(),
                      static_cast<int>(formatted.size())) == -1) {
    return Err(Location(),
               "Failed to write to file: " + FilePathToUTF8(file_path));
  }
  return true;
}

BuildFile::BuildFile(const BuildSettings* build_settings,
                     SourceFile source_file,
                     std::unique_ptr<InputFile> input_file,
                     std::unique_ptr<ParseNode> tree_root,
                     LabelMatcher label_matcher)
    : build_settings_(build_settings),
      source_file_(std::move(source_file)),
      input_file_(std::move(input_file)),
      tree_root_(std::move(tree_root)),
      label_matcher_(std::move(label_matcher)) {}

Result<std::vector<BuildFile>> ResolvePatternsToBuildFiles(
    const BuildSettings* build_settings,
    const Loader* loader,
    const std::vector<LabelPattern>& patterns) {
  std::set<SourceFile> seen;
  std::vector<BuildFile> result;

  for (const LabelPattern& pattern : patterns) {
    ASSIGN_OR_RETURN(auto files,
                     ResolvePatternToFiles(build_settings, loader, pattern));

    for (const SourceFile& file : files) {
      if (seen.insert(file).second) {
        ASSIGN_OR_RETURN(auto parsed,
                         BuildFile::Create(build_settings, file, patterns));
        result.push_back(std::move(parsed));
      }
    }
  }
  return result;
}
