package ports

import (
	"context"
	"time"

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

// SignalUpsertInput is the observe-pass signal write: open/resolve
// transitions with their triggers, committed atomically.
type SignalUpsertInput struct {
	Signal   domain.Signal
	Triggers []SignalTrigger
	Audit    []AuditEntry
	Event    *Event
}

// SignalTrigger is an automatic follow-up fired on a signal transition
// (payload firm; shapes firm up with the Phase 5 observation slice).
type SignalTrigger struct {
	Kind       string
	EntityID   domain.UUID
	Parameters map[string]any
}

// SignalTransitionInput acks/resolves/mutes a signal (check-then-act on the
// signal's current state inside the transaction).
type SignalTransitionInput struct {
	SignalID domain.UUID
	Action   string // "ack", "resolve", "mute"
	Note     string
	MuteFor  time.Duration
	Actor    string
	Audit    []AuditEntry
	Event    *Event
}

// SignalRepository is the signal aggregate.
type SignalRepository interface {
	Open(ctx context.Context) ([]domain.Signal, error)
	History(ctx context.Context, entityID domain.UUID, limit int) ([]domain.Signal, error)

	UpsertWithTriggers(ctx context.Context, input SignalUpsertInput) error
	Transition(ctx context.Context, input SignalTransitionInput) (domain.Signal, error)
}

// ExecutionSubmitInput is the queued-execution write: execution row,
// approval (for gated risk classes), audit, and event — one transaction.
type ExecutionSubmitInput struct {
	Execution domain.Execution
	Approval  *domain.Approval
	Audit     []AuditEntry
	Event     *Event
}

// ExecutionCompleteInput closes out an execution: final status, output
// summary, audit, event.
type ExecutionCompleteInput struct {
	ExecutionID domain.UUID
	Status      string
	Output      string
	ExitCode    int
	Audit       []AuditEntry
	Event       *Event
}

// ExecutionRepository is the execution aggregate. Claim uses an advisory
// lock so exactly one worker claims a queued execution.
type ExecutionRepository interface {
	List(ctx context.Context, cursor string, limit int) ([]domain.Execution, error)
	ReadLog(ctx context.Context, executionID domain.UUID) ([]string, error)

	SubmitQueued(ctx context.Context, input ExecutionSubmitInput) (domain.Execution, error)
	Claim(ctx context.Context) (*domain.Execution, error)
	AppendLog(ctx context.Context, executionID domain.UUID, chunk string) error
	Complete(ctx context.Context, input ExecutionCompleteInput) error
}

// ApprovalDecideInput verifies the HMAC token (check-then-act), flips the
// approval, un-gates the execution, and appends audit — one transaction.
// Double-approve must not double-execute.
type ApprovalDecideInput struct {
	ApprovalID domain.UUID
	Token      string
	Approved   bool
	Actor      string
	Audit      []AuditEntry
	Event      *Event
}

// ApprovalRepository is the approval aggregate.
type ApprovalRepository interface {
	ListPending(ctx context.Context, entityID domain.UUID, limit int) ([]domain.Approval, error)

	Decide(ctx context.Context, input ApprovalDecideInput) (domain.Approval, error)
}
