import os
import re
import ast
from collections import Counter

class ScopeAuditor(ast.NodeVisitor):
 def __init__(self, findings):
  self.scope_stack = [([], "")]
  self.findings = findings

 def visit_ClassDef(self, node):
  self.scope_stack[-1][0].append(node.name)
  parent_label = self.scope_stack[-1][1]
  new_label = f"{parent_label}.{node.name}" if parent_label else node.name
  self.scope_stack.append(([], new_label))
  self.generic_visit(node)
  defs, label = self.scope_stack.pop()
  self.check_duplicates(defs, label)

 def visit_FunctionDef(self, node):
  self.scope_stack[-1][0].append(node.name)
  parent_label = self.scope_stack[-1][1]
  new_label = f"{parent_label}.{node.name}" if parent_label else node.name
  self.scope_stack.append(([], new_label))
  self.generic_visit(node)
  defs, label = self.scope_stack.pop()
  self.check_duplicates(defs, label)

 def visit_AsyncFunctionDef(self, node):
  self.visit_FunctionDef(node)

 def check_duplicates(self, defs, label):
  counts = Counter(defs)
  for name, count in counts.items():
   if count > 1:
    scope_str = f" in scope '{label}'" if label else " at top-level"
    self.findings.append(f"Duplicate definition{scope_str}: '{name}' ({count} times)")

def audit_file(path):
 with open(path, 'r', encoding='utf-8') as f:
  lines = f.readlines()
 content = "".join(lines)

 findings = []

 # 1. Detect multiple identical import lines
 imports = [line.strip() for line in lines if line.strip().startswith('import ')]
 import_counts = Counter(imports)
 for imp, count in import_counts.items():
  if count > 1:
   findings.append(f"Duplicate import: '{imp}' ({count} times)")

 # 2. Detect multiple 'from X import Y' lines for the same module X and symbol Y
 from_imports = [line.strip() for line in lines if line.strip().startswith('from ')]
 from_counts = Counter(from_imports)
 for imp, count in from_counts.items():
  if count > 1:
   findings.append(f"Duplicate from-import: '{imp}' ({count} times)")

 # 3. Detect mixed indentation (look for 4-space blocks)
 four_spaces = "    "
 for i, line in enumerate(lines):
  if line.startswith(four_spaces):
   findings.append(f"Mixed indentation: 4-space block found at line {i+1}")
   break # Only report once per file

 # 4. List all functions and classes that appear more than once in the same scope
 try:
  tree = ast.parse(content)
  auditor = ScopeAuditor(findings)
  auditor.visit(tree)
  if auditor.scope_stack:
   defs, label = auditor.scope_stack.pop()
   auditor.check_duplicates(defs, label)
 except Exception as e:
  findings.append(f"AST Parse Error: {e}")

 return findings

def main():
 src_dir = 'src'
 if not os.path.exists(src_dir):
  print(f"Directory {src_dir} not found.")
  return

 for root, dirs, files in os.walk(src_dir):
  for file in files:
   if file.endswith('.py'):
    path = os.path.join(root, file)
    findings = audit_file(path)
    if findings:
     print(f"--- {path} ---")
     for f in findings:
      print(f"  {f}")
     print()

if __name__ == "__main__":
 main()
