package process

import (
	"context"
	"sync"
	"sync/atomic"

	"github.com/host-uk/core/pkg/framework"
)

// Global default service (follows i18n pattern).
var (
	defaultService atomic.Pointer[Service]
	defaultOnce    sync.Once
	defaultErr     error
)

// Default returns the global process service.
// Returns nil if not initialized.
func Default() *Service {
	return defaultService.Load()
}

// SetDefault sets the global process service.
// Thread-safe: can be called concurrently with Default().
func SetDefault(s *Service) {
	if s == nil {
		panic("process: SetDefault called with nil service")
	}
	defaultService.Store(s)
}

// Init initializes the default global service with a Core instance.
// This is typically called during application startup.
func Init(c *framework.Core) error {
	defaultOnce.Do(func() {
		factory := NewService(Options{})
		svc, err := factory(c)
		if err != nil {
			defaultErr = err
			return
		}
		defaultService.Store(svc.(*Service))
	})
	return defaultErr
}

// --- Global convenience functions ---

// Start spawns a new process using the default service.
func Start(ctx context.Context, command string, args ...string) (*Process, error) {
	svc := Default()
	if svc == nil {
		return nil, ErrServiceNotInitialized
	}
	return svc.Start(ctx, command, args...)
}

// Run executes a command and waits for completion using the default service.
func Run(ctx context.Context, command string, args ...string) (string, error) {
	svc := Default()
	if svc == nil {
		return "", ErrServiceNotInitialized
	}
	return svc.Run(ctx, command, args...)
}

// Get returns a process by ID from the default service.
func Get(id string) (*Process, error) {
	svc := Default()
	if svc == nil {
		return nil, ErrServiceNotInitialized
	}
	return svc.Get(id)
}

// List returns all processes from the default service.
func List() []*Process {
	svc := Default()
	if svc == nil {
		return nil
	}
	return svc.List()
}

// Kill terminates a process by ID using the default service.
func Kill(id string) error {
	svc := Default()
	if svc == nil {
		return ErrServiceNotInitialized
	}
	return svc.Kill(id)
}

// StartWithOptions spawns a process with full configuration using the default service.
func StartWithOptions(ctx context.Context, opts RunOptions) (*Process, error) {
	svc := Default()
	if svc == nil {
		return nil, ErrServiceNotInitialized
	}
	return svc.StartWithOptions(ctx, opts)
}

// RunWithOptions executes a command with options and waits using the default service.
func RunWithOptions(ctx context.Context, opts RunOptions) (string, error) {
	svc := Default()
	if svc == nil {
		return "", ErrServiceNotInitialized
	}
	return svc.RunWithOptions(ctx, opts)
}

// Running returns all currently running processes from the default service.
func Running() []*Process {
	svc := Default()
	if svc == nil {
		return nil
	}
	return svc.Running()
}

// ErrServiceNotInitialized is returned when the service is not initialized.
var ErrServiceNotInitialized = &ServiceError{msg: "process: service not initialized"}

// ServiceError represents a service-level error.
type ServiceError struct {
	msg string
}

// Error returns the service error message.
func (e *ServiceError) Error() string {
	return e.msg
}
