package quests

import (
	"fmt"
	"strings"
)

// Action management methods for Quest

// AddCompleteAction adds a completion action for a step
func (q *Quest) AddCompleteAction(stepID int32, action string) {
	q.completeActionsMutex.Lock()
	defer q.completeActionsMutex.Unlock()
	q.CompleteActions[stepID] = action
	q.SetSaveNeeded(true)
}

// AddProgressAction adds a progress action for a step
func (q *Quest) AddProgressAction(stepID int32, action string) {
	q.progressActionsMutex.Lock()
	defer q.progressActionsMutex.Unlock()
	q.ProgressActions[stepID] = action
	q.SetSaveNeeded(true)
}

// AddFailedAction adds a failure action for a step
func (q *Quest) AddFailedAction(stepID int32, action string) {
	q.failedActionsMutex.Lock()
	defer q.failedActionsMutex.Unlock()
	q.FailedActions[stepID] = action
	q.SetSaveNeeded(true)
}

// RemoveCompleteAction removes a completion action for a step
func (q *Quest) RemoveCompleteAction(stepID int32) bool {
	q.completeActionsMutex.Lock()
	defer q.completeActionsMutex.Unlock()

	if _, exists := q.CompleteActions[stepID]; exists {
		delete(q.CompleteActions, stepID)
		q.SetSaveNeeded(true)
		return true
	}
	return false
}

// RemoveProgressAction removes a progress action for a step
func (q *Quest) RemoveProgressAction(stepID int32) bool {
	q.progressActionsMutex.Lock()
	defer q.progressActionsMutex.Unlock()

	if _, exists := q.ProgressActions[stepID]; exists {
		delete(q.ProgressActions, stepID)
		q.SetSaveNeeded(true)
		return true
	}
	return false
}

// RemoveFailedAction removes a failure action for a step
func (q *Quest) RemoveFailedAction(stepID int32) bool {
	q.failedActionsMutex.Lock()
	defer q.failedActionsMutex.Unlock()

	if _, exists := q.FailedActions[stepID]; exists {
		delete(q.FailedActions, stepID)
		q.SetSaveNeeded(true)
		return true
	}
	return false
}

// GetCompleteAction returns the completion action for a step
func (q *Quest) GetCompleteAction(stepID int32) (string, bool) {
	q.completeActionsMutex.RLock()
	defer q.completeActionsMutex.RUnlock()

	action, exists := q.CompleteActions[stepID]
	return action, exists
}

// GetProgressAction returns the progress action for a step
func (q *Quest) GetProgressAction(stepID int32) (string, bool) {
	q.progressActionsMutex.RLock()
	defer q.progressActionsMutex.RUnlock()

	action, exists := q.ProgressActions[stepID]
	return action, exists
}

// GetFailedAction returns the failure action for a step
func (q *Quest) GetFailedAction(stepID int32) (string, bool) {
	q.failedActionsMutex.RLock()
	defer q.failedActionsMutex.RUnlock()

	action, exists := q.FailedActions[stepID]
	return action, exists
}

// HasCompleteAction checks if a step has a completion action
func (q *Quest) HasCompleteAction(stepID int32) bool {
	q.completeActionsMutex.RLock()
	defer q.completeActionsMutex.RUnlock()

	_, exists := q.CompleteActions[stepID]
	return exists
}

// HasProgressAction checks if a step has a progress action
func (q *Quest) HasProgressAction(stepID int32) bool {
	q.progressActionsMutex.RLock()
	defer q.progressActionsMutex.RUnlock()

	_, exists := q.ProgressActions[stepID]
	return exists
}

// HasFailedAction checks if a step has a failure action
func (q *Quest) HasFailedAction(stepID int32) bool {
	q.failedActionsMutex.RLock()
	defer q.failedActionsMutex.RUnlock()

	_, exists := q.FailedActions[stepID]
	return exists
}

// SetCompleteAction sets the general quest completion action
func (q *Quest) SetCompleteAction(action string) {
	q.CompleteAction = action
	q.SetSaveNeeded(true)
}

// GetQuestCompleteAction returns the general quest completion action
func (q *Quest) GetQuestCompleteAction() string {
	return q.CompleteAction
}

// ClearAllActions removes all actions for all steps
func (q *Quest) ClearAllActions() {
	q.completeActionsMutex.Lock()
	q.CompleteActions = make(map[int32]string)
	q.completeActionsMutex.Unlock()

	q.progressActionsMutex.Lock()
	q.ProgressActions = make(map[int32]string)
	q.progressActionsMutex.Unlock()

	q.failedActionsMutex.Lock()
	q.FailedActions = make(map[int32]string)
	q.failedActionsMutex.Unlock()

	q.CompleteAction = ""
	q.SetSaveNeeded(true)
}

// ClearStepActions removes all actions for a specific step
func (q *Quest) ClearStepActions(stepID int32) {
	q.RemoveCompleteAction(stepID)
	q.RemoveProgressAction(stepID)
	q.RemoveFailedAction(stepID)
}

// GetAllCompleteActions returns a copy of all completion actions
func (q *Quest) GetAllCompleteActions() map[int32]string {
	q.completeActionsMutex.RLock()
	defer q.completeActionsMutex.RUnlock()

	actions := make(map[int32]string)
	for stepID, action := range q.CompleteActions {
		actions[stepID] = action
	}
	return actions
}

// GetAllProgressActions returns a copy of all progress actions
func (q *Quest) GetAllProgressActions() map[int32]string {
	q.progressActionsMutex.RLock()
	defer q.progressActionsMutex.RUnlock()

	actions := make(map[int32]string)
	for stepID, action := range q.ProgressActions {
		actions[stepID] = action
	}
	return actions
}

// GetAllFailedActions returns a copy of all failure actions
func (q *Quest) GetAllFailedActions() map[int32]string {
	q.failedActionsMutex.RLock()
	defer q.failedActionsMutex.RUnlock()

	actions := make(map[int32]string)
	for stepID, action := range q.FailedActions {
		actions[stepID] = action
	}
	return actions
}

// ExecuteCompleteAction executes a completion action for a step
func (q *Quest) ExecuteCompleteAction(stepID int32) error {
	action, exists := q.GetCompleteAction(stepID)
	if !exists || action == "" {
		return fmt.Errorf("no completion action for step %d", stepID)
	}

	// TODO: Execute Lua script with action
	// This would integrate with the Lua interface when available
	return q.executeLuaAction("complete", stepID, action)
}

// ExecuteProgressAction executes a progress action for a step
func (q *Quest) ExecuteProgressAction(stepID int32, progressAmount int32) error {
	action, exists := q.GetProgressAction(stepID)
	if !exists || action == "" {
		return fmt.Errorf("no progress action for step %d", stepID)
	}

	// TODO: Execute Lua script with action and progress amount
	return q.executeLuaActionWithProgress("progress", stepID, action, progressAmount)
}

// ExecuteFailedAction executes a failure action for a step
func (q *Quest) ExecuteFailedAction(stepID int32) error {
	action, exists := q.GetFailedAction(stepID)
	if !exists || action == "" {
		return fmt.Errorf("no failure action for step %d", stepID)
	}

	// TODO: Execute Lua script with action
	return q.executeLuaAction("failed", stepID, action)
}

// ExecuteQuestCompleteAction executes the general quest completion action
func (q *Quest) ExecuteQuestCompleteAction() error {
	if q.CompleteAction == "" {
		return nil // No action to execute
	}

	// TODO: Execute Lua script with quest completion action
	return q.executeLuaAction("quest_complete", 0, q.CompleteAction)
}

// Placeholder methods for Lua integration (to be implemented when Lua interface is available)

// executeLuaAction executes a Lua action script
func (q *Quest) executeLuaAction(actionType string, stepID int32, action string) error {
	// TODO: Implement Lua script execution
	// This is a placeholder that would integrate with the Lua interface
	// when it becomes available in the Go codebase

	// For now, just log the action that would be executed
	fmt.Printf("Quest %d: Would execute %s action for step %d: %s\n", q.ID, actionType, stepID, action)
	return nil
}

// executeLuaActionWithProgress executes a Lua action script with progress information
func (q *Quest) executeLuaActionWithProgress(actionType string, stepID int32, action string, progress int32) error {
	// TODO: Implement Lua script execution with progress parameter
	// This is a placeholder that would integrate with the Lua interface

	// For now, just log the action that would be executed
	fmt.Printf("Quest %d: Would execute %s action for step %d with progress %d: %s\n", q.ID, actionType, stepID, progress, action)
	return nil
}

// Action validation methods

// ValidateActions validates all quest actions
func (q *Quest) ValidateActions() error {
	// Validate completion actions
	q.completeActionsMutex.RLock()
	for stepID, action := range q.CompleteActions {
		if err := q.validateAction(stepID, action, "completion"); err != nil {
			q.completeActionsMutex.RUnlock()
			return err
		}
	}
	q.completeActionsMutex.RUnlock()

	// Validate progress actions
	q.progressActionsMutex.RLock()
	for stepID, action := range q.ProgressActions {
		if err := q.validateAction(stepID, action, "progress"); err != nil {
			q.progressActionsMutex.RUnlock()
			return err
		}
	}
	q.progressActionsMutex.RUnlock()

	// Validate failure actions
	q.failedActionsMutex.RLock()
	for stepID, action := range q.FailedActions {
		if err := q.validateAction(stepID, action, "failure"); err != nil {
			q.failedActionsMutex.RUnlock()
			return err
		}
	}
	q.failedActionsMutex.RUnlock()

	// Validate quest completion action
	if q.CompleteAction != "" {
		if err := q.validateAction(0, q.CompleteAction, "quest completion"); err != nil {
			return err
		}
	}

	return nil
}

// validateAction validates a single action
func (q *Quest) validateAction(stepID int32, action, actionType string) error {
	if action == "" {
		return fmt.Errorf("empty %s action for step %d", actionType, stepID)
	}

	if len(action) > MaxCompleteActionLength {
		return fmt.Errorf("%s action too long for step %d (max %d)", actionType, stepID, MaxCompleteActionLength)
	}

	// Validate that the step exists (except for quest completion action)
	if stepID > 0 {
		if step := q.GetQuestStep(stepID); step == nil {
			return fmt.Errorf("%s action references non-existent step %d", actionType, stepID)
		}
	}

	// Basic Lua syntax validation (very basic check)
	if err := q.validateLuaSyntax(action); err != nil {
		return fmt.Errorf("invalid Lua syntax in %s action for step %d: %w", actionType, stepID, err)
	}

	return nil
}

// validateLuaSyntax performs basic Lua syntax validation
func (q *Quest) validateLuaSyntax(luaCode string) error {
	// TODO: Implement proper Lua syntax validation
	// This is a placeholder that does very basic checks

	// Check for balanced parentheses, brackets, and braces
	if err := q.checkBalancedDelimiters(luaCode); err != nil {
		return err
	}

	// Check for obviously invalid syntax patterns
	invalidPatterns := []string{
		"--[[",      // Unfinished multi-line comments
		"function(", // Function without closing
	}

	for _, pattern := range invalidPatterns {
		if strings.Contains(luaCode, pattern) {
			// Do more thorough checking for these patterns
			// This is just a basic check - real validation would be more sophisticated
		}
	}

	return nil
}

// checkBalancedDelimiters checks if delimiters are balanced in Lua code
func (q *Quest) checkBalancedDelimiters(code string) error {
	stack := make([]rune, 0)
	pairs := map[rune]rune{
		')': '(',
		']': '[',
		'}': '{',
	}

	inString := false
	inComment := false
	var stringChar rune

	for i, char := range code {
		// Handle string literals
		if (char == '"' || char == '\'') && !inComment {
			if !inString {
				inString = true
				stringChar = char
			} else if char == stringChar {
				inString = false
			}
			continue
		}

		// Skip everything inside strings
		if inString {
			continue
		}

		// Handle line comments
		if i > 0 && code[i-1] == '-' && char == '-' && !inComment {
			inComment = true
			continue
		}

		// End line comment at newline
		if inComment && char == '\n' {
			inComment = false
			continue
		}

		// Skip everything in comments
		if inComment {
			continue
		}

		// Check delimiters
		switch char {
		case '(', '[', '{':
			stack = append(stack, char)
		case ')', ']', '}':
			if len(stack) == 0 {
				return fmt.Errorf("unmatched closing delimiter '%c'", char)
			}

			expected := pairs[char]
			if stack[len(stack)-1] != expected {
				return fmt.Errorf("mismatched delimiter: expected '%c', got '%c'", expected, char)
			}

			stack = stack[:len(stack)-1]
		}
	}

	if len(stack) > 0 {
		return fmt.Errorf("unclosed delimiter '%c'", stack[len(stack)-1])
	}

	return nil
}
