package server

import "time"

const (
	CollectStatusQueued   = "queued"
	CollectStatusRunning  = "running"
	CollectStatusSuccess  = "success"
	CollectStatusFailed   = "failed"
	CollectStatusCanceled = "canceled"
)

type CollectRequest struct {
	Host             string `json:"host"`
	Protocol         string `json:"protocol"`
	Port             int    `json:"port"`
	Username         string `json:"username"`
	AuthType         string `json:"auth_type"`
	Password         string `json:"password,omitempty"`
	Token            string `json:"token,omitempty"`
	TLSMode          string `json:"tls_mode"`
	DebugPayloads bool `json:"debug_payloads,omitempty"`
}

type CollectProbeResponse struct {
	Reachable             bool   `json:"reachable"`
	Protocol              string `json:"protocol,omitempty"`
	HostPowerState string `json:"host_power_state,omitempty"`
	HostPoweredOn  bool   `json:"host_powered_on"`
	Message        string `json:"message,omitempty"`
}

type CollectJobResponse struct {
	JobID     string    `json:"job_id"`
	Status    string    `json:"status"`
	Message   string    `json:"message,omitempty"`
	CreatedAt time.Time `json:"created_at"`
}

type CollectJobStatusResponse struct {
	JobID         string                `json:"job_id"`
	Status        string                `json:"status"`
	Progress      *int                  `json:"progress,omitempty"`
	CurrentPhase  string                `json:"current_phase,omitempty"`
	ETASeconds    *int                  `json:"eta_seconds,omitempty"`
	Logs          []string              `json:"logs,omitempty"`
	Error         string                `json:"error,omitempty"`
	ActiveModules []CollectModuleStatus `json:"active_modules,omitempty"`
	ModuleScores  []CollectModuleStatus `json:"module_scores,omitempty"`
	DebugInfo     *CollectDebugInfo     `json:"debug_info,omitempty"`
	CreatedAt     time.Time             `json:"created_at,omitempty"`
	UpdatedAt     time.Time             `json:"updated_at"`
}

type CollectRequestMeta struct {
	Host     string `json:"host"`
	Protocol string `json:"protocol"`
	Port     int    `json:"port"`
	Username string `json:"username"`
	AuthType string `json:"auth_type"`
	TLSMode  string `json:"tls_mode"`
}

type Job struct {
	ID            string
	Status        string
	Progress      int
	CurrentPhase  string
	ETASeconds    int
	Logs          []string
	Error         string
	ActiveModules []CollectModuleStatus
	ModuleScores  []CollectModuleStatus
	DebugInfo     *CollectDebugInfo
	CreatedAt     time.Time
	UpdatedAt     time.Time
	RequestMeta   CollectRequestMeta
	cancel  func()
	skipFn  func()
}

type CollectModuleStatus struct {
	Name     string `json:"name"`
	Score    int    `json:"score"`
	Active   bool   `json:"active,omitempty"`
	Priority int    `json:"priority,omitempty"`
}

type CollectDebugInfo struct {
	AdaptiveThrottled bool                    `json:"adaptive_throttled"`
	SnapshotWorkers   int                     `json:"snapshot_workers,omitempty"`
	PrefetchWorkers   int                     `json:"prefetch_workers,omitempty"`
	PrefetchEnabled   *bool                   `json:"prefetch_enabled,omitempty"`
	PhaseTelemetry    []CollectPhaseTelemetry `json:"phase_telemetry,omitempty"`
}

type CollectPhaseTelemetry struct {
	Phase     string  `json:"phase"`
	Requests  int     `json:"requests,omitempty"`
	Errors    int     `json:"errors,omitempty"`
	ErrorRate float64 `json:"error_rate,omitempty"`
	AvgMS     int64   `json:"avg_ms,omitempty"`
	P95MS     int64   `json:"p95_ms,omitempty"`
}

func (j *Job) toStatusResponse() CollectJobStatusResponse {
	progress := j.Progress
	resp := CollectJobStatusResponse{
		JobID:         j.ID,
		Status:        j.Status,
		Progress:      &progress,
		CurrentPhase:  j.CurrentPhase,
		Logs:          append([]string(nil), j.Logs...),
		Error:         j.Error,
		ActiveModules: append([]CollectModuleStatus(nil), j.ActiveModules...),
		ModuleScores:  append([]CollectModuleStatus(nil), j.ModuleScores...),
		DebugInfo:     cloneCollectDebugInfo(j.DebugInfo),
		CreatedAt:     j.CreatedAt,
		UpdatedAt:     j.UpdatedAt,
	}
	if j.ETASeconds > 0 {
		eta := j.ETASeconds
		resp.ETASeconds = &eta
	}
	return resp
}

func (j *Job) toJobResponse(message string) CollectJobResponse {
	return CollectJobResponse{
		JobID:     j.ID,
		Status:    j.Status,
		Message:   message,
		CreatedAt: j.CreatedAt,
	}
}

func cloneCollectDebugInfo(in *CollectDebugInfo) *CollectDebugInfo {
	if in == nil {
		return nil
	}
	out := *in
	out.PhaseTelemetry = append([]CollectPhaseTelemetry(nil), in.PhaseTelemetry...)
	if in.PrefetchEnabled != nil {
		value := *in.PrefetchEnabled
		out.PrefetchEnabled = &value
	}
	return &out
}
