package models

import (
	"time"

	"go.mongodb.org/mongo-driver/v2/bson"
)

type InputParam struct {
	Name        string `bson:"name" json:"name"`
	Default     string `bson:"default" json:"default"`
	Description string `bson:"description" json:"description"`
}

type WorkflowStep struct {
	ID              bson.ObjectID `bson:"_id,omitempty" json:"-"`
	InstanceID      string        `bson:"instance_id" json:"instance_id"`
	StepID          string        `bson:"step_id" json:"step_id"`
	Name            string        `bson:"name" json:"name"`
	Description     string        `bson:"description" json:"description"`
	Interpreter     string        `bson:"interpreter" json:"interpreter"`
	Script          string        `bson:"script" json:"script"`
	DeclaredOutputs []string      `bson:"declared_outputs" json:"declared_outputs"`
	DeclaredInputs  []InputParam  `bson:"declared_inputs" json:"declared_inputs"`
	SecretRefs      []string      `bson:"secret_refs" json:"secret_refs"`
	Source          string        `bson:"source" json:"source"`
	Slug            string        `bson:"slug,omitempty" json:"slug,omitempty"`
	CreatedAt       time.Time     `bson:"created_at" json:"created_at"`
	UpdatedAt       time.Time     `bson:"updated_at" json:"updated_at"`
}

type WorkflowStepRef struct {
	StepID     string            `bson:"step_id,omitempty" json:"step_id,omitempty"`
	Inline     *WorkflowStep     `bson:"inline,omitempty" json:"inline,omitempty"`
	Order      int               `bson:"order" json:"order"`
	OnFailure  string            `bson:"on_failure" json:"on_failure"`
	MaxRetries int               `bson:"max_retries" json:"max_retries"`
	Overrides  *StepOverride     `bson:"overrides,omitempty" json:"overrides,omitempty"`
	Inputs     map[string]string `bson:"inputs,omitempty" json:"inputs,omitempty"`
}

type StepOverride struct {
	Script     *string  `bson:"script,omitempty" json:"script,omitempty"`
	SecretRefs []string `bson:"secret_refs,omitempty" json:"secret_refs,omitempty"`
}

type Schedule struct {
	Enabled bool   `bson:"enabled" json:"enabled"`
	Cron    string `bson:"cron" json:"cron"` // 5-field: minute hour dom month dow
	TZ      string `bson:"tz" json:"tz"`     // IANA name, e.g. Europe/London
}

// Skip records why an occurrence did not run. Recording a reason nobody reads
// is the same as not recording one, so this is surfaced in the UI.
type Skip struct {
	Reason string    `bson:"reason" json:"reason"` // "missed" | "already_running"
	Due    time.Time `bson:"due" json:"due"`
	At     time.Time `bson:"at" json:"at"`
}

type Workflow struct {
	ID              bson.ObjectID     `bson:"_id,omitempty" json:"-"`
	InstanceID      string            `bson:"instance_id" json:"instance_id"`
	WorkflowID      string            `bson:"workflow_id" json:"workflow_id"`
	Name            string            `bson:"name" json:"name"`
	TargetServerIDs []string          `bson:"target_server_ids" json:"target_server_ids"`
	TargetTags      map[string]string `bson:"target_tags,omitempty" json:"target_tags,omitempty"`
	Steps           []WorkflowStepRef `bson:"steps" json:"steps"`
	Schedule        *Schedule         `bson:"schedule,omitempty" json:"schedule,omitempty"`
	NextRunAt       *time.Time        `bson:"next_run_at,omitempty" json:"next_run_at,omitempty"`
	LastRunAt       *time.Time        `bson:"last_run_at,omitempty" json:"last_run_at,omitempty"`
	LastSkipped     *Skip             `bson:"last_skipped,omitempty" json:"last_skipped,omitempty"`
	CreatedAt       time.Time         `bson:"created_at" json:"created_at"`
	UpdatedAt       time.Time         `bson:"updated_at" json:"updated_at"`
}

type ResolvedStep struct {
	Order       int               `bson:"order" json:"order"`
	Name        string            `bson:"name" json:"name"`
	Interpreter string            `bson:"interpreter" json:"interpreter"`
	Script      string            `bson:"script" json:"script"`
	SecretRefs  []string          `bson:"secret_refs" json:"secret_refs"`
	OnFailure   string            `bson:"on_failure" json:"on_failure"`
	MaxRetries  int               `bson:"max_retries" json:"max_retries"`
	Inputs      map[string]string `bson:"inputs" json:"inputs"`
}

type StepRun struct {
	Order      int               `bson:"order" json:"order"`
	Name       string            `bson:"name" json:"name"`
	Status     string            `bson:"status" json:"status"`
	Attempts   int               `bson:"attempts" json:"attempts"`
	ExitCode   int               `bson:"exit_code" json:"exit_code"`
	LogOffset  int64             `bson:"log_offset" json:"log_offset"`
	OutputEnv  map[string]string `bson:"output_env" json:"output_env"`
	StartedAt  *time.Time        `bson:"started_at,omitempty" json:"started_at,omitempty"`
	FinishedAt *time.Time        `bson:"finished_at,omitempty" json:"finished_at,omitempty"`
}

type ServerRun struct {
	ServerID   string            `bson:"server_id" json:"server_id"`
	Hostname   string            `bson:"hostname" json:"hostname"`
	Status     string            `bson:"status" json:"status"`
	StartedAt  *time.Time        `bson:"started_at,omitempty" json:"started_at,omitempty"`
	FinishedAt *time.Time        `bson:"finished_at,omitempty" json:"finished_at,omitempty"`
	RunEnv     map[string]string `bson:"run_env" json:"run_env"`
	Steps      []StepRun         `bson:"steps" json:"steps"`
}

type WorkflowRun struct {
	ID          bson.ObjectID  `bson:"_id,omitempty" json:"-"`
	InstanceID  string         `bson:"instance_id" json:"instance_id"`
	RunID       string         `bson:"run_id" json:"run_id"`
	WorkflowID  string         `bson:"workflow_id" json:"workflow_id"`
	Name        string         `bson:"name" json:"name"`
	Steps       []ResolvedStep `bson:"steps_snapshot" json:"steps_snapshot"`
	Status      string         `bson:"status" json:"status"`
	TriggeredBy string         `bson:"triggered_by" json:"triggered_by"`
	StartedAt   time.Time      `bson:"started_at" json:"started_at"`
	FinishedAt  *time.Time     `bson:"finished_at,omitempty" json:"finished_at,omitempty"`
	ServerRuns  []ServerRun    `bson:"server_runs" json:"server_runs"`
}
