package fallback

import (
	"context"
	"path/filepath"
	"regexp"
	"strings"

	contractevents "bit.admedia.com/scm/ad/adpilot-indexing-code-parser.com/internal/contracts/events"
	"bit.admedia.com/scm/ad/adpilot-indexing-code-parser.com/internal/contracts/graph"
	"bit.admedia.com/scm/ad/adpilot-indexing-code-parser.com/internal/service/parser/analyzers/common"
)

// Analyzer provides tiered fallback parsing for unsupported languages.
type Analyzer struct{}

func NewAnalyzer() *Analyzer {
	return &Analyzer{}
}

func (a *Analyzer) IsFallback() bool { return true }

func (a *Analyzer) ParseFile(ctx context.Context, source []byte, filePath, language string) (*graph.Artifact, []contractevents.CodeChunk, error) {
	_ = ctx
	if language == "" {
		language = inferLanguage(filePath)
	}

	b := common.NewBuilder(filePath, language)
	level := applyRegexSymbols(b, source)

	b.EnsureLineWindowChunks(source)
	b.SetFallbackLevel(level)

	return b.Artifact(), b.Chunks(), nil
}

func applyRegexSymbols(b *common.Builder, source []byte) string {
	lines := common.Lines(source)
	found := false

	funcPatterns := []*regexp.Regexp{
		regexp.MustCompile(`^\s*(?:public|private|protected|static|\s)*[\w<>\[\],\s]+\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(`),
		regexp.MustCompile(`^\s*(?:async\s+)?function\s+([A-Za-z_$][A-Za-z0-9_$]*)`),
		regexp.MustCompile(`^\s*(?:async\s+)?def\s+([A-Za-z_][A-Za-z0-9_]*)`),
		regexp.MustCompile(`^\s*func\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(`),
	}
	classPatterns := []*regexp.Regexp{
		regexp.MustCompile(`^\s*class\s+([A-Za-z_][A-Za-z0-9_]*)`),
		regexp.MustCompile(`^\s*(?:public\s+)?(?:class|struct|interface)\s+([A-Za-z_][A-Za-z0-9_]*)`),
	}
	importPatterns := []*regexp.Regexp{
		regexp.MustCompile(`^\s*import\s+(.+)`),
		regexp.MustCompile(`^\s*#include\s+[<"]([^">]+)[">]`),
		regexp.MustCompile(`^\s*use\s+([\w\\]+)`),
	}

	for i, line := range lines {
		trimmed := strings.TrimSpace(line)
		for _, p := range importPatterns {
			if m := p.FindStringSubmatch(trimmed); len(m) > 1 {
				b.AddImport(strings.TrimSpace(m[1]), i+1)
				found = true
			}
		}
		for _, p := range classPatterns {
			if m := p.FindStringSubmatch(trimmed); len(m) > 1 {
				b.AddSymbol(m[1], contractevents.SymbolTypeType, i+1, i+1, map[string]string{"fallback": "regex"})
				found = true
			}
		}
		for _, p := range funcPatterns {
			if m := p.FindStringSubmatch(trimmed); len(m) > 1 {
				if m[1] == "if" || m[1] == "for" || m[1] == "while" {
					continue
				}
				b.AddSymbol(m[1], contractevents.SymbolTypeFunction, i+1, i+1, map[string]string{"fallback": "regex"})
				found = true
			}
		}
	}

	if found {
		return "regex"
	}
	return "text"
}

func inferLanguage(filePath string) string {
	ext := strings.ToLower(filepath.Ext(filePath))
	if ext == "" {
		return "unknown"
	}
	return strings.TrimPrefix(ext, ".")
}
