package models

import (
	"time"

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

// Workload kinds.
const (
	WorkloadContainer = "container"
	WorkloadUnit      = "unit"
)

// Control actions.
const (
	WorkloadStart   = "start"
	WorkloadStop    = "stop"
	WorkloadRestart = "restart"
)

// Workload is one container or one systemd unit.
type Workload struct {
	Kind string `bson:"kind" json:"kind"` // container | unit
	ID   string `bson:"id" json:"id"`     // container id, or unit name
	Name string `bson:"name" json:"name"`

	// State is deliberately NOT collapsed into a shared vocabulary across the
	// two kinds. Containers report running/exited/paused/restarting/created;
	// units report active/inactive/failed/activating. A failed unit and an
	// exited container mean different things, and flattening them loses the
	// distinction the operator needs.
	State  string `bson:"state" json:"state"`
	Health string `bson:"health,omitempty" json:"health,omitempty"`

	Image string   `bson:"image,omitempty" json:"image,omitempty"`
	Stack string   `bson:"stack,omitempty" json:"stack,omitempty"` // compose project label
	Ports []string `bson:"ports,omitempty" json:"ports,omitempty"`

	Restarts  int       `bson:"restarts,omitempty" json:"restarts,omitempty"`
	StartedAt time.Time `bson:"started_at,omitempty" json:"started_at,omitempty"`

	// Protected is computed agent-side and reported so the UI can render the
	// action disabled with a reason rather than offering a button whose refusal
	// is already known. The field is the courtesy; the agent's own check is the
	// boundary.
	Protected bool `bson:"protected" json:"protected"`
}

// ServerWorkloads holds one server's whole workload list in ONE document.
type ServerWorkloads struct {
	ID          bson.ObjectID `bson:"_id,omitempty" json:"-"`
	InstanceID  string        `bson:"instance_id" json:"-"`
	ServerID    string        `bson:"server_id" json:"server_id"`
	Hash        string        `bson:"hash" json:"hash"`
	Workloads   []Workload    `bson:"workloads" json:"workloads"`
	CollectedAt time.Time     `bson:"collected_at" json:"collected_at"`

	// A host with no Docker and a host with Docker running nothing both produce
	// an empty list. One should read "not in use here", the other "nothing
	// running", and only the second deserves any alarm.
	//
	// The error strings separate a third case the booleans cannot: installed
	// with the daemon down. "Not installed" and "installed but not responding"
	// are different problems with different fixes.
	DockerOK     bool   `bson:"docker_ok" json:"docker_ok"`
	DockerError  string `bson:"docker_error,omitempty" json:"docker_error,omitempty"`
	SystemdOK    bool   `bson:"systemd_ok" json:"systemd_ok"`
	SystemdError string `bson:"systemd_error,omitempty" json:"systemd_error,omitempty"`
}
