require "./inspection"
require "compiler/crystal/syntax"

module Lattice
  module Inspections
    # Warns whenever a debug-output call is left in the source.
    #
    # Detected patterns:
    #   pp  <expr>
    #   pp! <expr>  (Crystal 1.10+)
    #   p   <expr>
    #   p!  <expr>
    #
    # Enabled via `.lattice.yml`:
    #
    #   warn_on_debug_calls: true
    #
    # Disabled by default (default: false).
    #
    # The check is a pattern match over raw source lines — no AST walk — so
    # it is intentionally cheap and never requires a valid parse tree.
    class WarnOnDebugCallsInspection < Inspection
      property enabled : Bool = false

      # Pattern: optional leading whitespace, then pp!, pp, p!, or p followed
      # by whitespace or end-of-line.  We anchor on word boundaries so that
      # identifiers such as `pp_value` do not trigger the rule.
      DEBUG_RE = /^\s*(?:pp!|pp|p!|p)\b/

      def run(
        uri : String,
        source : String,
        lines : Array(String),
        ast : ::Crystal::ASTNode,
      ) : Array(::LSP::Diagnostic)
        return [] of ::LSP::Diagnostic unless enabled

        diagnostics = [] of ::LSP::Diagnostic

        lines.each_with_index do |line, line_num|
          next unless line.match(DEBUG_RE)
          # Skip comment lines.
          next if line.lstrip.starts_with?('#')

          call_name = line.match(/^\s*(pp!|pp|p!|p)\b/).try(&.[1]?) || "pp"

          diagnostics << diagnostic(
            "Debug call '#{call_name}' left in source",
            line_num,
            line.index(call_name) || 0,
            line_num,
            (line.index(call_name) || 0) + call_name.size,
            ::LSP::DiagnosticSeverity::Warning,
            "lattice",
          )
        end

        diagnostics
      end
    end
  end
end
