package ports

import (
	"context"
	"time"

	"github.com/dtoro/oikos/internal/core/domain"
)

// Target is a resolved execution endpoint (mirrors remote.ExecTarget; the
// remote adapter maps between them). Wrap rewrites a plain command for
// transport: identity for a host, pct/qm wrapping for guests.
type Target struct {
	Host string
	User string
	Wrap func(cmd string) string
}

// ExecOpts carries execution options; Sink, when non-nil, receives output
// chunks as they arrive (streaming path).
type ExecOpts struct {
	Timeout time.Duration
	Sink    func(stream string, chunk []byte)
}

// ExecResult is the outcome of one command execution.
type ExecResult struct {
	Output   string
	Duration time.Duration
	Err      error
}

// CommandExecutor runs a command on a resolved target over SSH. Implemented
// by the ssh adapter wrapping internal/actuator (dial pool + breaker).
type CommandExecutor interface {
	Run(ctx context.Context, target Target, command string, opts ExecOpts) ExecResult
}

// TargetResolver resolves entity slugs/IDs to execution endpoints.
// Implemented by the remote adapter on top of EntityRepository.
type TargetResolver interface {
	ResolveExecTarget(ctx context.Context, targetSlug string) (Target, error)
	ResolveForCheck(ctx context.Context, targetID domain.UUID, targetType string) (Target, error)
	ResolveHost(ctx context.Context, hostSlug, fallbackUser string) (addr, user string, err error)
	// IsGuest reports whether an entity type is reached via pct/qm exec
	// through a Proxmox host rather than by direct SSH.
	IsGuest(entityType string) bool
}

// Provisioner creates guests via pct/qm on a Proxmox host. The ssh
// adapter implements it over CommandExecutor: template-cache resolution,
// cluster-wide VMID collision guard, gateway preflight, and the pct/qm
// create itself. DB registration of the created guest is NOT part of the
// port — ProvisioningService owns that over the entity/relationship
// repositories.
type Provisioner interface {
	CreateLXC(ctx context.Context, input LXCInput) (ProvisionResult, error)
	CreateVM(ctx context.Context, input VMInput) (ProvisionResult, error)
}

// LXCInput is a fully-defaulted LXC create spec (ProvisioningService
// applies defaults before calling). HostAddr/HostUser are the resolved
// SSH endpoint of the Proxmox host; Sink, when non-nil, receives the
// create command's output chunks as they arrive.
type LXCInput struct {
	HostAddr string
	HostUser string
	HostSlug string

	Hostname     string
	VMID         int
	Cores        int
	MemoryMB     int
	DiskGB       int
	IP           string
	GW           string
	Bridge       string
	Storage      string
	Template     string
	Privileged   bool
	Nesting      bool
	Mounts       []string
	Nameserver   string
	Searchdomain string

	Sink func(stream string, chunk []byte)
}

// VMInput mirrors LXCInput for VM creation via qm.
type VMInput struct {
	HostAddr string
	HostUser string
	HostSlug string

	Name       string
	VMID       int
	TemplateID int
	Cores      int
	MemoryMB   int
	DiskGB     int

	Sink func(stream string, chunk []byte)
}

// ProvisionResult reports what the provisioner actually did — the VMID
// may differ from the request (cluster collision guard reassigns), and
// the template is the concrete cache entry picked.
type ProvisionResult struct {
	VMID     int
	Template string
	Output   string
}
