package extractor

import (
	"context"
	"strings"

	"github.com/tidbcloud/AgentTeam/kits/agentteam-insight/internal/graphbuilder/scanner"
)

type Extractor interface {
	Extract(context.Context, scanner.FileInfo) (StructuralAnalysis, error)
}

type StructuralAnalysis struct {
	FilePath              string
	Language              string
	ContentHash           string
	TotalLines            int
	HasStructuralAnalysis bool
	PackageName           string
	Functions             []Function
	Types                 []Type
	Imports               []Import
	Exports               []string
	Calls                 []Call
	SubNodes              []SubNode
}

type Function struct {
	Name       string
	Receiver   string
	Params     []string
	ReturnType string
	DocComment string
	Exported   bool
	LineRange  [2]int
}

type Type struct {
	Name       string
	Kind       string
	DocComment string
	Exported   bool
	LineRange  [2]int
	Methods    []string
}

type Import struct {
	Path       string
	Alias      string
	Specifiers []string
}

type Call struct {
	Caller string
	Callee string
	Line   int
}

type SubNode struct {
	Type          string
	Name          string
	Summary       string
	Tags          []string
	LineRange     [2]int
	LanguageNotes string
}

func SortAnalyses(analyses []StructuralAnalysis) {
	// Placeholder for callers that need deterministic order; scanner already supplies stable order.
}

func TypeNodeKind(kind string) string {
	kind = strings.TrimSpace(kind)
	if kind == "" {
		return "type"
	}
	return kind
}

// FunctionNeedsSemanticEnrichment owns the significance rule shared by the
// batch cost model and the file-analyzer evidence contract.
func FunctionNeedsSemanticEnrichment(fn Function) bool {
	return fn.Exported || LineRangeSpan(fn.LineRange) >= 10
}

// TypeNeedsSemanticEnrichment owns the significance rule shared by the batch
// cost model and the file-analyzer evidence contract.
func TypeNeedsSemanticEnrichment(typ Type) bool {
	return typ.Exported || LineRangeSpan(typ.LineRange) >= 20 || len(typ.Methods) >= 2
}

func LineRangeSpan(lineRange [2]int) int {
	if lineRange[0] <= 0 || lineRange[1] < lineRange[0] {
		return 0
	}
	return lineRange[1] - lineRange[0] + 1
}
