package automation

import (
	"fmt"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/store/model"
)

type jobRunStatusSummary struct {
	Total     int
	Terminal  int
	Succeeded int
	Failed    int
	Blocked   int
	Skipped   int
	Canceled  int
}

func summarizeJobRunStatuses(jobRuns []AutomationJobRun) jobRunStatusSummary {
	var summary jobRunStatusSummary
	for _, jobRun := range jobRuns {
		summary.Total++
		if isTerminalJobRunStatus(jobRun.Status) {
			summary.Terminal++
		}
		switch jobRun.Status {
		case AutomationJobRunStatusSucceeded:
			summary.Succeeded++
		case AutomationJobRunStatusFailed:
			summary.Failed++
		case AutomationJobRunStatusBlocked:
			summary.Blocked++
		case AutomationJobRunStatusSkipped:
			summary.Skipped++
		case AutomationJobRunStatusCanceled:
			summary.Canceled++
		}
	}
	return summary
}

type automationRunKey struct {
	WorkspaceID string
	RunID       string
}

func activeAutomationRunStatuses() []string {
	return []string{AutomationRunStatusQueued, AutomationRunStatusRunning, AutomationRunStatusWaiting, AutomationRunStatusBlocked}
}

func terminalAutomationJobRunStatuses() []string {
	return []string{AutomationJobRunStatusBlocked, AutomationJobRunStatusFailed, AutomationJobRunStatusSucceeded, AutomationJobRunStatusSkipped, AutomationJobRunStatusCanceled}
}

func nonTerminalAutomationJobRunStatuses() []string {
	return []string{AutomationJobRunStatusPending, AutomationJobRunStatusReady, AutomationJobRunStatusQueued, AutomationJobRunStatusLeased, AutomationJobRunStatusRunning, AutomationJobRunStatusWaiting}
}

func stringSet(values []string) map[string]struct{} {
	out := make(map[string]struct{}, len(values))
	for _, value := range values {
		if value = strings.TrimSpace(value); value != "" {
			out[value] = struct{}{}
		}
	}
	return out
}

func decodeJobRunDependencies(raw string) []string {
	if strings.TrimSpace(raw) == "" {
		return nil
	}
	var deps []string
	if err := model.UnmarshalJSONString("automation job dependencies", raw, &deps); err != nil {
		return nil
	}
	out := deps[:0]
	for _, dep := range deps {
		if dep = strings.TrimSpace(dep); dep != "" {
			out = append(out, dep)
		}
	}
	return out
}

func automationEvent(eventType string, jobRun AutomationJobRun, summary string, metadataJSON string, now time.Time) AutomationEvent {
	return AutomationEvent{
		ID:           automationEventID(eventType, jobRun.ID, now),
		WorkspaceID:  jobRun.WorkspaceID,
		RunID:        jobRun.RunID,
		JobRunID:     jobRun.ID,
		EventType:    eventType,
		Summary:      summary,
		MetadataJSON: metadataJSON,
		CreatedAt:    now,
	}
}

func automationEventID(eventType string, seed string, now time.Time) string {
	suffix := seed
	if len(suffix) > 16 {
		suffix = suffix[len(suffix)-16:]
	}
	return fmt.Sprintf("wfe_%s_%s_%d", eventType, suffix, now.UnixNano())
}

func automationJSON(value any) string {
	encoded, _ := model.MarshalJSONString("automation persistence value", value)
	return encoded
}

func normalizeJSONForStore(value string) string {
	value = strings.TrimSpace(value)
	if value == "" {
		return "{}"
	}
	var payload any
	if err := model.UnmarshalJSONString("automation persistence value", value, &payload); err != nil {
		return automationJSON(map[string]any{"value": value})
	}
	return automationJSON(payload)
}

func isTerminalRunStatus(status string) bool {
	return status == AutomationRunStatusSucceeded || status == AutomationRunStatusFailed || status == AutomationRunStatusCanceled
}

func isTerminalJobRunStatus(status string) bool {
	return status == AutomationJobRunStatusBlocked || status == AutomationJobRunStatusSucceeded || status == AutomationJobRunStatusFailed || status == AutomationJobRunStatusSkipped || status == AutomationJobRunStatusCanceled
}
