// 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;
}

// 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::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;
}

std::vector<TreeNode> FindAllListElements(const TreeNode& assignment) {
  auto* op = assignment.AsAssignment();
  if (!op)
    return {};
  return FindExpression<TreeNode>(
      assignment.Descend(op->right()),
      [](TreeNode& node_ref) -> std::optional<TreeNode> {
        if (node_ref.parent() && node_ref.parent()->AsList()) {
          return node_ref;
        }
        return std::nullopt;
      });
}

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,
                        std::string_view message) const {
  std::string line =
      "# TODO(gn edit: " + state.context + "): " + std::string(message);
  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,
             "This would normally be deleted but is conditional. Manual "
             "intervention is required to decide whether it should actually be "
             "deleted.");
  } 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> TreeNode::assignments(
    std::initializer_list<std::string_view> attrs) const {
  return FindStatement<TreeNode>(
      node(), [attrs](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()) {
              for (auto attr : attrs) {
                if (left->value().value() == attr) {
                  return node_ref;
                }
              }
            }
          }
        }
        return std::nullopt;
      });
}

std::vector<TreeNode> TreeNode::assignments(std::string_view attr) const {
  return assignments({attr});
}

std::vector<TreeNode> EditTarget::assignments(
    std::initializer_list<std::string_view> attrs) const {
  return node.Descend(block).assignments(attrs);
}

std::vector<TreeNode> EditTarget::assignments(std::string_view attr) const {
  return assignments({attr});
}

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;
}
