package plugin

import (
	"errors"
	"time"
)

const (
	// Keep exactly the last 10 successful and last 10 error runs per job type.
	MaxSuccessfulRunHistory = 10
	MaxErrorRunHistory      = 10
)

var ErrJobNotFound = errors.New("job not found")

type RunOutcome string

const (
	RunOutcomeSuccess RunOutcome = "success"
	RunOutcomeError   RunOutcome = "error"
)

type JobRunRecord struct {
	RunID       string     `json:"run_id"`
	JobID       string     `json:"job_id"`
	JobType     string     `json:"job_type"`
	WorkerID    string     `json:"worker_id"`
	Outcome     RunOutcome `json:"outcome"`
	Message     string     `json:"message,omitempty"`
	DurationMs  int64      `json:"duration_ms,omitempty"`
	CompletedAt *time.Time `json:"completed_at,omitempty"`
}

type JobTypeRunHistory struct {
	JobType         string         `json:"job_type"`
	SuccessfulRuns  []JobRunRecord `json:"successful_runs"`
	ErrorRuns       []JobRunRecord `json:"error_runs"`
	LastUpdatedTime *time.Time     `json:"last_updated_time,omitempty"`
}

type TrackedJob struct {
	JobID              string                 `json:"job_id"`
	JobType            string                 `json:"job_type"`
	RequestID          string                 `json:"request_id"`
	WorkerID           string                 `json:"worker_id"`
	DedupeKey          string                 `json:"dedupe_key,omitempty"`
	Summary            string                 `json:"summary,omitempty"`
	Detail             string                 `json:"detail,omitempty"`
	Parameters         map[string]interface{} `json:"parameters,omitempty"`
	Labels             map[string]string      `json:"labels,omitempty"`
	State              string                 `json:"state"`
	Progress           float64                `json:"progress"`
	Stage              string                 `json:"stage,omitempty"`
	Message            string                 `json:"message,omitempty"`
	Attempt            int32                  `json:"attempt,omitempty"`
	CreatedAt          *time.Time             `json:"created_at,omitempty"`
	UpdatedAt          *time.Time             `json:"updated_at,omitempty"`
	CompletedAt        *time.Time             `json:"completed_at,omitempty"`
	ErrorMessage       string                 `json:"error_message,omitempty"`
	ResultSummary      string                 `json:"result_summary,omitempty"`
	ResultOutputValues map[string]interface{} `json:"result_output_values,omitempty"`
}

type JobActivity struct {
	JobID      string                 `json:"job_id"`
	JobType    string                 `json:"job_type"`
	RequestID  string                 `json:"request_id,omitempty"`
	WorkerID   string                 `json:"worker_id,omitempty"`
	Source     string                 `json:"source"`
	Message    string                 `json:"message"`
	Stage      string                 `json:"stage,omitempty"`
	Details    map[string]interface{} `json:"details,omitempty"`
	OccurredAt *time.Time             `json:"occurred_at,omitempty"`
}

type JobDetail struct {
	Job         *TrackedJob   `json:"job"`
	RunRecord   *JobRunRecord `json:"run_record,omitempty"`
	Activities  []JobActivity `json:"activities"`
	RelatedJobs []TrackedJob  `json:"related_jobs,omitempty"`
	LastUpdated *time.Time    `json:"last_updated,omitempty"`
}

type SchedulerJobTypeState struct {
	JobType                       string     `json:"job_type"`
	Lane                          string     `json:"lane"`
	Enabled                       bool       `json:"enabled"`
	PolicyError                   string     `json:"policy_error,omitempty"`
	DetectionInFlight             bool       `json:"detection_in_flight"`
	NextDetectionAt               *time.Time `json:"next_detection_at,omitempty"`
	DetectionIntervalMinutes      int32      `json:"detection_interval_minutes,omitempty"`
	DetectionTimeoutSeconds       int32      `json:"detection_timeout_seconds,omitempty"`
	ExecutionTimeoutSeconds       int32      `json:"execution_timeout_seconds,omitempty"`
	JobTypeMaxRuntimeSeconds      int32      `json:"job_type_max_runtime_seconds,omitempty"`
	MaxJobsPerDetection           int32      `json:"max_jobs_per_detection,omitempty"`
	GlobalExecutionConcurrency    int        `json:"global_execution_concurrency,omitempty"`
	PerWorkerExecutionConcurrency int        `json:"per_worker_execution_concurrency,omitempty"`
	RetryLimit                    int        `json:"retry_limit,omitempty"`
	RetryBackoffSeconds           int32      `json:"retry_backoff_seconds,omitempty"`
	DetectorAvailable             bool       `json:"detector_available"`
	DetectorWorkerID              string     `json:"detector_worker_id,omitempty"`
	ExecutorWorkerCount           int        `json:"executor_worker_count"`
	LastRunStartedAt              *time.Time `json:"last_run_started_at,omitempty"`
	LastRunCompletedAt            *time.Time `json:"last_run_completed_at,omitempty"`
	LastRunStatus                 string     `json:"last_run_status,omitempty"`
}

func timeToPtr(t time.Time) *time.Time {
	if t.IsZero() {
		return nil
	}
	return &t
}
