//go:build ignore
// +build ignore

package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"log"
	"os"
	"path/filepath"
	"strings"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run cleanup_unused.go <directory>")
		os.Exit(1)
	}

	rootDir := os.Args[1]
	err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if !strings.HasSuffix(path, ".go") || strings.Contains(path, "_test.go") {
			return nil
		}

		// Skip vendor and generated files
		if strings.Contains(path, "vendor/") || strings.Contains(path, "generated/") {
			return nil
		}

		cleanupFile(path)
		return nil
	})

	if err != nil {
		log.Fatal(err)
	}
}

func cleanupFile(filename string) {
	fset := token.NewFileSet()
	node, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
	if err != nil {
		log.Printf("Error parsing %s: %v", filename, err)
		return
	}

	// Find all exported identifiers
	exportedIdents := make(map[string]bool)
	ast.Inspect(node, func(n ast.Node) bool {
		switch x := n.(type) {
		case *ast.GenDecl:
			for _, spec := range x.Specs {
				switch s := spec.(type) {
				case *ast.TypeSpec:
					if ast.IsExported(s.Name.Name) {
						exportedIdents[s.Name.Name] = true
					}
				case *ast.ValueSpec:
					for _, name := range s.Names {
						if ast.IsExported(name.Name) {
							exportedIdents[name.Name] = true
						}
					}
				}
			}
		case *ast.FuncDecl:
			if x.Recv == nil && ast.IsExported(x.Name.Name) {
				exportedIdents[x.Name.Name] = true
			}
		}
		return true
	})

	// Find all usages
	usedIdents := make(map[string]bool)
	ast.Inspect(node, func(n ast.Node) bool {
		switch x := n.(type) {
		case *ast.Ident:
			if x.Name != "_" && ast.IsExported(x.Name) {
				usedIdents[x.Name] = true
			}
		case *ast.SelectorExpr:
			// x.Sel is always an *ast.Ident in SelectorExpr
			usedIdents[x.Sel.Name] = true
		}
		return true
	})

	// Find unused exports
	var unusedExports []string
	for ident := range exportedIdents {
		if !usedIdents[ident] {
			unusedExports = append(unusedExports, ident)
		}
	}

	if len(unusedExports) > 0 {
		fmt.Printf("Found %d unused exports in %s: %v\n", len(unusedExports), filename, unusedExports)
		// For now, just report. In a real implementation, we'd modify the AST
		// and rewrite the file to remove unused exports
	}
}
