package runtimeworker

import (
	"context"
	"database/sql"
	"errors"
	"strings"
	"time"

	"github.com/nexuscrm/backend/internal/runtimeconfig"
	"github.com/nexuscrm/backend/internal/runtimepermissionstate"
)

type workerPermissionStateGate interface {
	Capabilities() []string
	Ready() bool
}

type observedWorkerPermissionStateGate struct {
	gate        workerPermissionStateGate
	observation authorityCheckObservation
}

func (gate *observedWorkerPermissionStateGate) Capabilities() []string {
	if gate == nil || gate.gate == nil {
		return nil
	}
	return gate.gate.Capabilities()
}

func (gate *observedWorkerPermissionStateGate) Ready() bool {
	if gate == nil || gate.gate == nil {
		return false
	}
	started := time.Now()
	ready := gate.gate.Ready()
	gate.observation.observe(started, ready)
	return ready
}

func (gate *observedWorkerPermissionStateGate) snapshot() authorityCheckSnapshot {
	if gate == nil {
		return authorityCheckSnapshot{}
	}
	return gate.observation.snapshot()
}

func newWorkerPermissionStateGate(
	ctx context.Context,
	db *sql.DB,
	version string,
	role runtimeconfig.WorkerRole,
	factory permissionStateGateFactory,
) (*observedWorkerPermissionStateGate, error) {
	gate, err := factory(ctx, db, runtimepermissionstate.Config{
		SourceRevision:          version,
		ConfigurationSchema:     role.Schema,
		PermissionStateProtocol: role.PermissionStateProtocol,
		Role:                    runtimepermissionstate.RoleReaderWriter,
	})
	if err != nil {
		return nil, err
	}
	return &observedWorkerPermissionStateGate{gate: gate}, nil
}

func workerPermissionStateProcessInputs(
	workFamily string,
	gate workerPermissionStateGate,
	ownershipReady func() bool,
) ([]string, func() bool, error) {
	if strings.TrimSpace(workFamily) == "" || gate == nil || ownershipReady == nil {
		return nil, nil, errors.New("runtime worker: Permission State process composition is incomplete")
	}
	capabilities := append([]string{workFamily}, gate.Capabilities()...)
	ready := func() bool {
		return ownershipReady() && gate.Ready()
	}
	return capabilities, ready, nil
}
