package router

import (
	"context"
	"fmt"

	"go.uber.org/zap"

	"iop/apps/node/internal/adapters"
	"iop/apps/node/internal/runtime"
)

type defaultRouter struct {
	registry *adapters.Registry
	logger   *zap.Logger
}

// New returns a Router that resolves requests to registered adapters.
func New(reg *adapters.Registry, logger *zap.Logger) runtime.Router {
	return &defaultRouter{registry: reg, logger: logger}
}

func (r *defaultRouter) Resolve(_ context.Context, req runtime.RunRequest) (runtime.ExecutionSpec, error) {
	adapterName := req.Adapter
	if adapterName == "" {
		return runtime.ExecutionSpec{}, fmt.Errorf("router: adapter is required")
	}

	if _, err := r.registry.Lookup(adapterName); err != nil {
		return runtime.ExecutionSpec{}, fmt.Errorf("router: %w", err)
	}

	spec := runtime.ExecutionSpec{
		RunID:       req.RunID,
		Adapter:     adapterName,
		Target:      req.Target,
		SessionID:   req.SessionID,
		SessionMode: req.SessionMode,
		Background:  req.Background,
		Workspace:   req.Workspace,
		Policy:      req.Policy,
		Input:       req.Input,
		TimeoutSec:  req.TimeoutSec,
		Metadata:    req.Metadata,
	}

	r.logger.Debug("resolved execution spec",
		zap.String("run_id", req.RunID),
		zap.String("adapter", spec.Adapter),
		zap.String("target", spec.Target),
	)
	return spec, nil
}

func (r *defaultRouter) ResolveAdapter(ctx context.Context, req runtime.RunRequest) (runtime.ExecutionSpec, runtime.Adapter, error) {
	spec, err := r.Resolve(ctx, req)
	if err != nil {
		return runtime.ExecutionSpec{}, nil, err
	}
	adapter, err := r.registry.Lookup(spec.Adapter)
	if err != nil {
		return runtime.ExecutionSpec{}, nil, fmt.Errorf("router: %w", err)
	}
	return spec, adapter, nil
}

func (r *defaultRouter) LookupAdapter(adapterName string) (runtime.Adapter, error) {
	return r.registry.Lookup(adapterName)
}

func (r *defaultRouter) GetAdapter(adapterName string) (runtime.Adapter, bool) {
	a, err := r.registry.Lookup(adapterName)
	if err != nil {
		return nil, false
	}
	return a, true
}
