package automation

import (
	"context"
	"encoding/json"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/automation/dsl"
	"github.com/tidbcloud/AgentTeam/internal/service/automation/runtime"
	automationstore "github.com/tidbcloud/AgentTeam/internal/store/automation"
)

func (s *AutomationsService) automationRunnerCallbackRedactor(ctx context.Context, workspaceID string, job automationstore.AutomationJob) (*runtime.SecretRedactor, error) {
	jobRun, err := s.store.GetJobRun(ctx, strings.TrimSpace(workspaceID), job.JobRunID)
	if err != nil {
		return nil, err
	}
	return s.automationRunnerCallbackRedactorForJobRun(ctx, workspaceID, jobRun)
}

func (s *AutomationsService) automationRunnerCallbackRedactorForJobRun(ctx context.Context, workspaceID string, jobRun automationstore.AutomationJobRun) (*runtime.SecretRedactor, error) {
	if strings.TrimSpace(jobRun.InputJSON) == "" {
		return nil, nil
	}
	var spec dsl.JobSpec
	if err := json.Unmarshal([]byte(jobRun.InputJSON), &spec); err != nil {
		return nil, invalidArgument("Automation runner job input is invalid")
	}
	refs, err := dsl.JobEnvReferences(spec)
	if err != nil {
		return nil, invalidArgument("Automation runner job env is invalid")
	}
	if len(refs.SecretNames) == 0 {
		return nil, nil
	}
	run, err := s.store.GetRun(ctx, strings.TrimSpace(workspaceID), jobRun.RunID)
	if err != nil {
		return nil, err
	}
	secrets, err := runtime.ResolveAutomationSecrets(ctx, s.store, s.credentialsKey, run, refs.SecretNames)
	if err != nil {
		return nil, err
	}
	return runtime.NewSecretRedactor(secrets), nil
}

func redactAutomationRunnerJSON(raw string, redactor *runtime.SecretRedactor) (string, error) {
	if redactor == nil || strings.TrimSpace(raw) == "" {
		return raw, nil
	}
	var payload any
	if err := json.Unmarshal([]byte(raw), &payload); err != nil {
		return "", err
	}
	return automationRunnerJSON(redactAutomationRunnerJSONValue(payload, redactor)), nil
}

func redactAutomationRunnerJSONValue(value any, redactor *runtime.SecretRedactor) any {
	switch typed := value.(type) {
	case string:
		return redactor.RedactString(typed)
	case []any:
		for idx := range typed {
			typed[idx] = redactAutomationRunnerJSONValue(typed[idx], redactor)
		}
		return typed
	case map[string]any:
		for key, item := range typed {
			typed[key] = redactAutomationRunnerJSONValue(item, redactor)
		}
		return typed
	default:
		return value
	}
}
