package runtime

import (
	"context"
	"time"

	"chorus.services/bzzz/api"
	"chorus.services/bzzz/coordinator"
	"chorus.services/bzzz/logging"
	"chorus.services/bzzz/p2p"
	"chorus.services/bzzz/pkg/config"
	"chorus.services/bzzz/pkg/dht"
	"chorus.services/bzzz/pkg/election"
	"chorus.services/bzzz/pkg/health"
	"chorus.services/bzzz/pkg/shutdown"
	"chorus.services/bzzz/pkg/ucxi"
	"chorus.services/bzzz/pkg/ucxl"
	"chorus.services/bzzz/pubsub"
	"chorus.services/hmmm/pkg/hmmm"
)

// BinaryType defines the type of binary being executed
type BinaryType int

const (
	BinaryTypeAgent BinaryType = iota
	BinaryTypeHAP
)

func (bt BinaryType) String() string {
	switch bt {
	case BinaryTypeAgent:
		return "agent"
	case BinaryTypeHAP:
		return "hap"
	default:
		return "unknown"
	}
}

// PortConfig holds port configuration for different binary types
type PortConfig struct {
	HTTPPort    int `yaml:"http_port"`
	HealthPort  int `yaml:"health_port"`
	UCXIPort    int `yaml:"ucxi_port"`
	AdminUIPort int `yaml:"admin_ui_port,omitempty"`
}

// RuntimeConfig holds configuration for runtime initialization
type RuntimeConfig struct {
	ConfigPath      string
	BinaryType      BinaryType
	EnableSetupMode bool
	CustomPorts     PortConfig
}

// RuntimeServices holds all initialized services
type RuntimeServices struct {
	Config            *config.Config
	Node              *p2p.Node
	PubSub            *pubsub.PubSub
	DHT               *dht.LibP2PDHT
	EncryptedStorage  *dht.EncryptedDHTStorage
	ElectionManager   *election.ElectionManager
	HealthManager     *health.Manager
	ShutdownManager   *shutdown.Manager
	DecisionPublisher *ucxl.DecisionPublisher
	UCXIServer        *ucxi.Server
	HTTPServer        *api.HTTPServer
	TaskCoordinator   *coordinator.TaskCoordinator
	HmmmRouter        *hmmm.Router
	Logger            logging.Logger
	MDNSDiscovery     interface{} // Using interface{} to avoid import cycles
}

// Runtime interface defines the main runtime operations
type Runtime interface {
	Initialize(ctx context.Context, cfg RuntimeConfig) (*RuntimeServices, error)
	Start(ctx context.Context, services *RuntimeServices) error
	Stop(ctx context.Context, services *RuntimeServices) error
	GetHealthStatus() *health.Status
}

// RuntimeService interface for individual services
type RuntimeService interface {
	Name() string
	Initialize(ctx context.Context, config *config.Config) error
	Start(ctx context.Context) error
	Stop(ctx context.Context) error
	IsHealthy() bool
	Dependencies() []string
}

// ServiceManager interface for managing runtime services
type ServiceManager interface {
	Register(service RuntimeService)
	Start(ctx context.Context) error
	Stop(ctx context.Context) error
	GetService(name string) RuntimeService
	GetHealthStatus() map[string]bool
}

// ExecutionMode interface for binary-specific execution
type ExecutionMode interface {
	Run(ctx context.Context, services *RuntimeServices) error
	Stop(ctx context.Context) error
	GetType() BinaryType
}

// SimpleTaskTracker interface for task tracking
type SimpleTaskTracker interface {
	GetActiveTasks() []string
	GetMaxTasks() int
	AddTask(taskID string)
	RemoveTask(taskID string)
	CompleteTaskWithDecision(taskID string, success bool, summary string, filesModified []string)
	SetDecisionPublisher(publisher *ucxl.DecisionPublisher)
}

// RuntimeError represents a runtime-specific error
type RuntimeError struct {
	Code        ErrorCode
	Message     string
	BinaryType  BinaryType
	ServiceName string
	Timestamp   time.Time
	Cause       error
}

func (e *RuntimeError) Error() string {
	return e.Message
}

// ErrorCode represents different error types
type ErrorCode int

const (
	ErrConfigInvalid ErrorCode = iota
	ErrP2PInitFailed
	ErrDHTUnavailable
	ErrElectionFailed
	ErrServiceStartFailed
	ErrShutdownTimeout
)

// NewRuntimeError creates a new runtime error
func NewRuntimeError(code ErrorCode, service string, binType BinaryType, msg string, cause error) *RuntimeError {
	return &RuntimeError{
		Code:        code,
		Message:     msg,
		BinaryType:  binType,
		ServiceName: service,
		Timestamp:   time.Now(),
		Cause:       cause,
	}
}