package cssanalyzer

import (
	"context"
	"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"
)

type Analyzer struct{}

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

func (a *Analyzer) SupportedLanguages() []string {
	return []string{"css", "scss", "sass", "less"}
}

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

	b := common.NewBuilder(filePath, language)
	lines := common.Lines(source)

	selectorPattern := regexp.MustCompile(`^([^{]+)\{`)
	importPattern := regexp.MustCompile(`@import\s+(?:url\()?['"]?([^'")\s;]+)`)
	varPattern := regexp.MustCompile(`(--[A-Za-z0-9_-]+)\s*:`)
	mediaPattern := regexp.MustCompile(`^@media\s+(.+)\{`)

	for i, line := range lines {
		trimmed := strings.TrimSpace(line)
		if m := importPattern.FindStringSubmatch(trimmed); len(m) > 1 {
			b.AddImport(m[1], i+1)
		}
		if m := mediaPattern.FindStringSubmatch(trimmed); len(m) > 1 {
			b.AddSymbol("@media "+strings.TrimSpace(m[1]), contractevents.SymbolTypeType, i+1, i+1, map[string]string{"kind": "media_query"})
		}
		if m := varPattern.FindStringSubmatch(trimmed); len(m) > 1 {
			b.AddSymbol(m[1], contractevents.SymbolTypeVariable, i+1, i+1, map[string]string{"kind": "design_token"})
		}
		if m := selectorPattern.FindStringSubmatch(trimmed); len(m) > 1 {
			selector := strings.TrimSpace(m[1])
			if selector != "" && !strings.HasPrefix(selector, "@") {
				end := findCSSBlockEnd(lines, i)
				b.AddSymbol(selector, contractevents.SymbolTypeType, i+1, end, map[string]string{"kind": "selector"})
			}
		}
	}

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

func inferCSSLang(filePath string) string {
	lower := strings.ToLower(filePath)
	switch {
	case strings.HasSuffix(lower, ".scss"):
		return "scss"
	case strings.HasSuffix(lower, ".sass"):
		return "sass"
	case strings.HasSuffix(lower, ".less"):
		return "less"
	default:
		return "css"
	}
}

func findCSSBlockEnd(lines []string, start int) int {
	depth := 0
	started := false
	for i := start; i < len(lines); i++ {
		for _, ch := range lines[i] {
			switch ch {
			case '{':
				depth++
				started = true
			case '}':
				depth--
				if started && depth == 0 {
					return i + 1
				}
			}
		}
	}
	return start + 1
}
