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

void TreeNode::RemoveSelfUnconditionally() const {
  DCHECK(parent());
  if (auto* block = parent()->AsBlockMut()) {
    auto& stmts = block->statements();
    for (auto it = stmts.begin(); it != stmts.end(); ++it) {
      if (it->get() == node()) {
        stmts.erase(it);
        return;
      }
    }
  } else if (auto* list = parent()->AsListMut()) {
    auto& items = list->contents();
    for (auto it = items.begin(); it != items.end(); ++it) {
      if (it->get() == node()) {
        items.erase(it);
        return;
      }
    }
  } else {
    CHECK(false) << "Unsupported type to remove from";
  }
  CHECK(false) << "child node not found in parent's children";
}

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_) {
      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;
}

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() {
  return FindStatement<EditTarget>(
      tree_root_.get(),
      [this](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())) {
              auto match_type = label_matcher_.matches(*name);
              if (match_type != LabelMatcher::NONE) {
                return EditTarget{
                    .is_explicit = match_type == LabelMatcher::EXACT,
                    .label = Label(source_file_.GetDir(), *name),
                    .node = node_ref,
                    .block = func->block(),
                };
              }
            }
          }
        }
        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;
}

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