package generic

import (
	"context"
	"os"
	"strings"

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

type Extractor struct{}

func New() Extractor { return Extractor{} }

func (Extractor) Extract(ctx context.Context, file scanner.FileInfo) (extractor.StructuralAnalysis, error) {
	if err := ctx.Err(); err != nil {
		return extractor.StructuralAnalysis{}, err
	}
	content, err := os.ReadFile(file.AbsPath)
	if err != nil {
		return extractor.StructuralAnalysis{}, err
	}
	text := string(content)
	analysis := extractor.StructuralAnalysis{
		FilePath:    file.Path,
		Language:    normalizedLanguage(file.Language, file.Path),
		ContentHash: file.ContentHash,
		TotalLines:  file.Lines,
	}

	switch languageFamily(analysis.Language) {
	case "typescript-javascript":
		extractTypeScriptJavaScript(&analysis, text)
	case "python":
		extractPython(&analysis, text)
	case "rust":
		extractRust(&analysis, text)
	case "java":
		extractJavaLike(&analysis, text, "java")
	case "kotlin":
		extractJavaLike(&analysis, text, "kotlin")
	case "csharp":
		extractJavaLike(&analysis, text, "csharp")
	case "php":
		extractPHP(&analysis, text)
	case "c-cpp":
		extractC(analysis.Language, &analysis, text)
	case "ruby":
		extractRuby(&analysis, text)
	case "sql":
		extractSQL(&analysis, text)
	case "yaml":
		extractYAML(file.Path, &analysis, text)
	case "json":
		extractJSON(file.Path, &analysis, text)
	case "markdown":
		extractMarkdown(&analysis, text)
	case "protobuf":
		extractProto(&analysis, text)
	case "graphql":
		extractGraphQL(&analysis, text)
	case "docker":
		extractDockerfile(&analysis, text)
	}
	finalize(&analysis)
	return analysis, nil
}

func normalizedLanguage(language string, path string) string {
	language = strings.ToLower(strings.TrimSpace(language))
	if language == "" {
		language, _ = scanner.ClassifyPath(path)
		language = strings.ToLower(strings.TrimSpace(language))
	}
	switch language {
	case "js", "jsx", "mjs", "cjs":
		return "javascript"
	case "ts", "tsx":
		return "typescript"
	case "py":
		return "python"
	case "rs":
		return "rust"
	case "kt", "kts":
		return "kotlin"
	case "cs":
		return "csharp"
	case "rb":
		return "ruby"
	case "yml":
		return "yaml"
	case "proto":
		return "protobuf"
	case "gql":
		return "graphql"
	default:
		return language
	}
}

func languageFamily(language string) string {
	switch language {
	case "typescript", "javascript":
		return "typescript-javascript"
	case "python":
		return "python"
	case "rust":
		return "rust"
	case "java":
		return "java"
	case "kotlin":
		return "kotlin"
	case "csharp":
		return "csharp"
	case "php":
		return "php"
	case "c", "cpp":
		return "c-cpp"
	case "ruby":
		return "ruby"
	case "sql":
		return "sql"
	case "yaml":
		return "yaml"
	case "json":
		return "json"
	case "markdown":
		return "markdown"
	case "protobuf":
		return "protobuf"
	case "graphql":
		return "graphql"
	case "docker":
		return "docker"
	default:
		return ""
	}
}
