package executionpool

import (
	"context"
	"io"
	"time"
)

const ProtocolVersion = "v1"

type PoolState string

const (
	PoolActive   PoolState = "active"
	PoolDraining PoolState = "draining"
	PoolDisabled PoolState = "disabled"
)

type RouteState string

const (
	RouteHealthy     RouteState = "healthy"
	RouteDegraded    RouteState = "degraded"
	RouteUnreachable RouteState = "unreachable"
	RouteUnknown     RouteState = "unknown"
)

type ExecutionPool struct {
	ID           string
	Labels       map[string]string
	Capabilities map[string]any
	State        PoolState
	UpdatedAt    time.Time
}

type WorkerDescriptor struct {
	WorkerID        string
	InstanceID      string
	PoolID          string
	Endpoint        string
	ProtocolVersion string
	Revision        string
	Capabilities    map[string]any
	Allocated       int
	SafeCapacity    int
	HeavyCapacity   int
	ActiveTasks     int
	PressureState   string
	HeartbeatAt     time.Time
	LoadSampledAt   time.Time
}

func (w WorkerDescriptor) AvailableCapacity() int {
	limit := w.Allocated
	if w.SafeCapacity < limit {
		limit = w.SafeCapacity
	}
	if limit < 0 {
		return 0
	}
	available := limit - w.ActiveTasks
	if available < 0 {
		return 0
	}
	return available
}

type RouteProfile struct {
	Key            string
	Provider       string
	Protocol       string
	EndpointHost   string
	ProxyMode      string
	ConfigRevision string
}

type RouteHealth struct {
	PoolID               string
	RouteProfileKey      string
	State                RouteState
	SuccessRate          float64
	ConnectTLSP95        time.Duration
	FirstByteP95         time.Duration
	UploadBytesPerSecond float64
	JitterP95            time.Duration
	ConsecutiveFailures  int
	ConsecutiveSuccesses int
	SampleCount          int
	SampledAt            time.Time
	ExpiresAt            time.Time
}

// RouteObservation contains only transport-phase facts. Model generation time
// is deliberately excluded from this structure and therefore from routing
// quality updates.
type RouteObservation struct {
	PoolID               string
	RouteProfileKey      string
	SampleCount          int
	SuccessCount         int
	ConnectTLSP95        time.Duration
	UploadBytesPerSecond float64
}

type CapacitySnapshot struct {
	PoolID             string
	WorkerCount        int
	Allocated          int
	SafeCapacity       int
	ActiveTasks        int
	HeavyCapacity      int
	HeavyTasks         int
	QueueDepth         int
	EstimatedQueueWait time.Duration
	ResourceHeadroom   float64
	Stability          float64
	Critical           bool
	SampledAt          time.Time
}

type DesiredCapacity struct {
	PoolID     string
	Desired    int
	Reason     string
	ValidUntil time.Time
}

// WorkerDirectory is the platform-neutral discovery boundary. Implementations
// may use PostgreSQL, Consul, etcd, or another registry.
type WorkerDirectory interface {
	ListWorkers(context.Context, time.Time) ([]WorkerDescriptor, error)
}

// ExecutionBroker hides the durable queue implementation from routing code.
type ExecutionBroker interface {
	Publish(context.Context, string, string, time.Time) (int64, error)
}

// ExecutionTransport hides HTTP, gRPC, or service-mesh transport details.
type ExecutionTransport interface {
	Execute(context.Context, WorkerDescriptor, ExecutionRequest) (ExecutionResponse, error)
}

type ExecutionRequest struct {
	TaskID             string
	PoolID             string
	WorkerID           string
	LeaseID            string
	AuthorizationToken string
	Deadline           time.Time
	Stream             bool
}

type ExecutionResponse struct {
	StatusCode int
	Headers    map[string][]string
	Body       io.ReadCloser
}

type RouteHealthRepository interface {
	ListRouteHealth(context.Context, string, time.Time) ([]RouteHealth, error)
	RecordRouteHealth(context.Context, RouteHealth) error
	RecordRouteObservation(context.Context, RouteObservation) error
}

type CapacityProvider interface {
	ListCapacity(context.Context, time.Time) ([]CapacitySnapshot, error)
	PublishDesiredCapacity(context.Context, DesiredCapacity) error
}
