package mapper // ApplyQueryMappings applies the specified mapping rules to a JSON object

import (
	"encoding/json"
	"fmt"

	"github.com/KorAP/KoralPipe-TermMapper/ast"
	"github.com/KorAP/KoralPipe-TermMapper/matcher"
	"github.com/KorAP/KoralPipe-TermMapper/parser"
)

// ApplyQueryMappings applies the specified mapping rules to a JSON object
func (m *Mapper) ApplyQueryMappings(mappingID string, opts MappingOptions, jsonData any) (any, error) {
	// Validate mapping ID
	if _, exists := m.mappingLists[mappingID]; !exists {
		return nil, fmt.Errorf("mapping list with ID %s not found", mappingID)
	}

	// Get the parsed rules
	rules := m.parsedRules[mappingID]

	// Check if we have a wrapper object with a "query" field
	var queryData any
	var hasQueryWrapper bool

	if jsonMap, ok := jsonData.(map[string]any); ok {
		if query, exists := jsonMap["query"]; exists {
			queryData = query
			hasQueryWrapper = true
		}
	}

	// If no query wrapper was found, use the entire input
	if !hasQueryWrapper {
		// If the input itself is not a valid query object, return it as is
		if !isValidQueryObject(jsonData) {
			return jsonData, nil
		}
		queryData = jsonData
	} else if queryData == nil || !isValidQueryObject(queryData) {
		// If we have a query wrapper but the query is nil or not a valid object,
		// return the original data
		return jsonData, nil
	}

	// Store rewrites if they exist
	var oldRewrites any
	if queryMap, ok := queryData.(map[string]any); ok {
		if rewrites, exists := queryMap["rewrites"]; exists {
			oldRewrites = rewrites
			delete(queryMap, "rewrites")
		}
	}

	// Convert input JSON to AST
	jsonBytes, err := json.Marshal(queryData)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal input JSON: %w", err)
	}

	node, err := parser.ParseJSON(jsonBytes)
	if err != nil {
		return nil, fmt.Errorf("failed to parse JSON into AST: %w", err)
	}

	// Store whether the input was a Token
	isToken := false
	var tokenWrap ast.Node
	if token, ok := node.(*ast.Token); ok {
		isToken = true
		tokenWrap = token.Wrap
		node = tokenWrap
	}

	// Store original node for rewrite if needed
	var originalNode ast.Node
	if opts.AddRewrites {
		originalNode = node.Clone()
	}

	// Pre-check foundry/layer overrides to optimize processing
	var patternFoundry, patternLayer, replacementFoundry, replacementLayer string
	if opts.Direction { // true means AtoB
		patternFoundry, patternLayer = opts.FoundryA, opts.LayerA
		replacementFoundry, replacementLayer = opts.FoundryB, opts.LayerB
	} else {
		patternFoundry, patternLayer = opts.FoundryB, opts.LayerB
		replacementFoundry, replacementLayer = opts.FoundryA, opts.LayerA
	}

	// Create a pattern cache key for memoization
	type patternCacheKey struct {
		ruleIndex     int
		foundry       string
		layer         string
		isReplacement bool
	}
	patternCache := make(map[patternCacheKey]ast.Node)

	// Apply each rule to the AST
	for i, rule := range rules {
		// Create pattern and replacement based on direction
		var pattern, replacement ast.Node
		if opts.Direction { // true means AtoB
			pattern = rule.Upper
			replacement = rule.Lower
		} else {
			pattern = rule.Lower
			replacement = rule.Upper
		}

		// Extract the inner nodes from the pattern and replacement tokens
		if token, ok := pattern.(*ast.Token); ok {
			pattern = token.Wrap
		}
		if token, ok := replacement.(*ast.Token); ok {
			replacement = token.Wrap
		}

		// First, quickly check if the pattern could match without creating a full matcher
		// This is a lightweight pre-check to avoid expensive operations
		if !m.couldPatternMatch(node, pattern) {
			continue
		}

		// Get or create pattern with overrides
		patternKey := patternCacheKey{ruleIndex: i, foundry: patternFoundry, layer: patternLayer, isReplacement: false}
		processedPattern, exists := patternCache[patternKey]
		if !exists {
			// Clone pattern only when needed
			processedPattern = pattern.Clone()
			// Apply foundry and layer overrides only if they're non-empty
			if patternFoundry != "" || patternLayer != "" {
				ast.ApplyFoundryAndLayerOverrides(processedPattern, patternFoundry, patternLayer)
			}
			patternCache[patternKey] = processedPattern
		}

		// Create a temporary matcher to check for actual matches
		tempMatcher, err := matcher.NewMatcher(ast.Pattern{Root: processedPattern}, ast.Replacement{Root: &ast.Term{}})
		if err != nil {
			return nil, fmt.Errorf("failed to create temporary matcher: %w", err)
		}

		// Only proceed if there's an actual match
		if !tempMatcher.Match(node) {
			continue
		}

		// Get or create replacement with overrides (lazy evaluation)
		replacementKey := patternCacheKey{ruleIndex: i, foundry: replacementFoundry, layer: replacementLayer, isReplacement: true}
		processedReplacement, exists := patternCache[replacementKey]
		if !exists {
			// Clone replacement only when we have a match
			processedReplacement = replacement.Clone()
			// Apply foundry and layer overrides only if they're non-empty
			if replacementFoundry != "" || replacementLayer != "" {
				ast.ApplyFoundryAndLayerOverrides(processedReplacement, replacementFoundry, replacementLayer)
			}
			patternCache[replacementKey] = processedReplacement
		}

		// Create the actual matcher and apply replacement
		actualMatcher, err := matcher.NewMatcher(ast.Pattern{Root: processedPattern}, ast.Replacement{Root: processedReplacement})
		if err != nil {
			return nil, fmt.Errorf("failed to create matcher: %w", err)
		}
		node = actualMatcher.Replace(node)
	}

	// Wrap the result in a token if the input was a token
	var result ast.Node
	if isToken {
		result = &ast.Token{Wrap: node}
	} else {
		result = node
	}

	// Convert AST back to JSON
	resultBytes, err := parser.SerializeToJSON(result)
	if err != nil {
		return nil, fmt.Errorf("failed to serialize AST to JSON: %w", err)
	}

	// Parse the JSON string back into
	var resultData any
	if err := json.Unmarshal(resultBytes, &resultData); err != nil {
		return nil, fmt.Errorf("failed to parse result JSON: %w", err)
	}

	// Add rewrites if enabled and node was changed
	if opts.AddRewrites && !ast.NodesEqual(node, originalNode) {
		// Create rewrite object
		rewrite := map[string]any{
			"@type":  "koral:rewrite",
			"editor": "termMapper",
		}

		// Check if the node types are different (structural change)
		if originalNode.Type() != node.Type() {
			// Full node replacement
			originalBytes, err := parser.SerializeToJSON(originalNode)
			if err != nil {
				return nil, fmt.Errorf("failed to serialize original node for rewrite: %w", err)
			}
			var originalJSON any
			if err := json.Unmarshal(originalBytes, &originalJSON); err != nil {
				return nil, fmt.Errorf("failed to parse original node JSON for rewrite: %w", err)
			}
			rewrite["original"] = originalJSON
		} else if term, ok := originalNode.(*ast.Term); ok && ast.IsTermNode(node) {
			// Check which attributes changed
			newTerm := node.(*ast.Term)
			if term.Foundry != newTerm.Foundry {
				rewrite["scope"] = "foundry"
				rewrite["original"] = term.Foundry
			} else if term.Layer != newTerm.Layer {
				rewrite["scope"] = "layer"
				rewrite["original"] = term.Layer
			} else if term.Key != newTerm.Key {
				rewrite["scope"] = "key"
				rewrite["original"] = term.Key
			} else if term.Value != newTerm.Value {
				rewrite["scope"] = "value"
				rewrite["original"] = term.Value
			} else {
				// No specific attribute changed, use full node replacement
				originalBytes, err := parser.SerializeToJSON(originalNode)
				if err != nil {
					return nil, fmt.Errorf("failed to serialize original node for rewrite: %w", err)
				}
				var originalJSON any
				if err := json.Unmarshal(originalBytes, &originalJSON); err != nil {
					return nil, fmt.Errorf("failed to parse original node JSON for rewrite: %w", err)
				}
				rewrite["original"] = originalJSON
			}
		} else {
			// Full node replacement
			originalBytes, err := parser.SerializeToJSON(originalNode)
			if err != nil {
				return nil, fmt.Errorf("failed to serialize original node for rewrite: %w", err)
			}
			var originalJSON any
			if err := json.Unmarshal(originalBytes, &originalJSON); err != nil {
				return nil, fmt.Errorf("failed to parse original node JSON for rewrite: %w", err)
			}
			rewrite["original"] = originalJSON
		}

		// Add rewrite to the node
		if resultMap, ok := resultData.(map[string]any); ok {
			if wrapMap, ok := resultMap["wrap"].(map[string]any); ok {
				rewrites, exists := wrapMap["rewrites"]
				if !exists {
					rewrites = []any{}
				}
				if rewritesList, ok := rewrites.([]any); ok {
					wrapMap["rewrites"] = append(rewritesList, rewrite)
				} else {
					wrapMap["rewrites"] = []any{rewrite}
				}
			}
		}
	}

	// Restore rewrites if they existed
	if oldRewrites != nil {
		// Process old rewrites through AST to ensure backward compatibility
		if rewritesList, ok := oldRewrites.([]any); ok {
			processedRewrites := make([]any, len(rewritesList))
			for i, rewriteData := range rewritesList {
				// Marshal and unmarshal each rewrite to apply backward compatibility
				rewriteBytes, err := json.Marshal(rewriteData)
				if err != nil {
					return nil, fmt.Errorf("failed to marshal old rewrite %d: %w", i, err)
				}
				var rewrite ast.Rewrite
				if err := json.Unmarshal(rewriteBytes, &rewrite); err != nil {
					return nil, fmt.Errorf("failed to unmarshal old rewrite %d: %w", i, err)
				}
				// Marshal back to get the transformed version
				transformedBytes, err := json.Marshal(&rewrite)
				if err != nil {
					return nil, fmt.Errorf("failed to marshal transformed rewrite %d: %w", i, err)
				}
				var transformedRewrite any
				if err := json.Unmarshal(transformedBytes, &transformedRewrite); err != nil {
					return nil, fmt.Errorf("failed to unmarshal transformed rewrite %d: %w", i, err)
				}
				processedRewrites[i] = transformedRewrite
			}
			if resultMap, ok := resultData.(map[string]any); ok {
				resultMap["rewrites"] = processedRewrites
			}
		} else {
			// If it's not a list, restore as-is
			if resultMap, ok := resultData.(map[string]any); ok {
				resultMap["rewrites"] = oldRewrites
			}
		}
	}

	// If we had a query wrapper, put the transformed data back in it
	if hasQueryWrapper {
		if wrapper, ok := jsonData.(map[string]any); ok {
			wrapper["query"] = resultData
			return wrapper, nil
		}
	}

	return resultData, nil
}

// isValidQueryObject checks if the query data is a valid object that can be processed
func isValidQueryObject(data any) bool {
	// Check if it's a map
	queryMap, ok := data.(map[string]any)
	if !ok {
		return false
	}

	// Check if it has the required @type field
	if _, ok := queryMap["@type"]; !ok {
		return false
	}

	return true
}

// couldPatternMatch performs a lightweight check to see if a pattern could potentially match a node
// This is an optimization to avoid expensive operations when there's clearly no match possible
func (m *Mapper) couldPatternMatch(node, pattern ast.Node) bool {
	if pattern == nil {
		return true
	}
	if node == nil {
		return false
	}

	// Handle Token wrappers
	if token, ok := pattern.(*ast.Token); ok {
		pattern = token.Wrap
	}
	if token, ok := node.(*ast.Token); ok {
		node = token.Wrap
	}

	// For simple terms, check basic compatibility
	if patternTerm, ok := pattern.(*ast.Term); ok {
		// Check if there's any term in the node structure that could match
		return m.hasMatchingTerm(node, patternTerm)
	}

	// For TermGroups, we need to check all possible matches
	if patternGroup, ok := pattern.(*ast.TermGroup); ok {
		if patternGroup.Relation == ast.OrRelation {
			// For OR relations, any operand could match
			for _, op := range patternGroup.Operands {
				if m.couldPatternMatch(node, op) {
					return true
				}
			}
			return false
		} else {
			// For AND relations, all operands must have potential matches
			for _, op := range patternGroup.Operands {
				if !m.couldPatternMatch(node, op) {
					return false
				}
			}
			return true
		}
	}

	// For other cases, assume they could match (conservative approach)
	return true
}

// hasMatchingTerm checks if there's any term in the node structure that could match the pattern term
func (m *Mapper) hasMatchingTerm(node ast.Node, patternTerm *ast.Term) bool {
	if node == nil {
		return false
	}

	switch n := node.(type) {
	case *ast.Term:
		// Check if this term could match the pattern
		// We only check key as that's the most distinctive attribute
		return n.Key == patternTerm.Key
	case *ast.TermGroup:
		// Check all operands
		for _, op := range n.Operands {
			if m.hasMatchingTerm(op, patternTerm) {
				return true
			}
		}
		return false
	case *ast.Token:
		return m.hasMatchingTerm(n.Wrap, patternTerm)
	case *ast.CatchallNode:
		if n.Wrap != nil && m.hasMatchingTerm(n.Wrap, patternTerm) {
			return true
		}
		for _, op := range n.Operands {
			if m.hasMatchingTerm(op, patternTerm) {
				return true
			}
		}
		return false
	default:
		return false
	}
}
