package api

import (
	"context"

	"github.com/tidbcloud/AgentTeam/desktop/internal/profile"
	"github.com/tidbcloud/AgentTeam/desktop/internal/types"
	"github.com/tidbcloud/AgentTeam/desktop/internal/uisession"
)

type serverRuntimeParticipant struct {
	connections types.ServerConnectionAccessor
	sessions    *uisession.Store
}

// NewServerRuntimeParticipant composes the profile-owned mutation transaction
// with daemon runtime connections and the shared UI session fence.
func NewServerRuntimeParticipant(
	connections types.ServerConnectionAccessor,
	sessions *uisession.Store,
) profile.ServerRuntimeParticipant {
	return &serverRuntimeParticipant{
		connections: connections,
		sessions:    sessions,
	}
}

func (p *serverRuntimeParticipant) BeginServerTransition(serverID string) profile.ServerTransition {
	return p.sessions.BeginServerTransitionHandle(serverID)
}

func (p *serverRuntimeParticipant) ReconcileServer(
	ctx context.Context,
	previous, current *profile.AgentTeamServer,
) error {
	return reconcileServerConnection(ctx, p.connections, previous, current)
}

func (p *serverRuntimeParticipant) RepairServer(
	ctx context.Context,
	current profile.AgentTeamServer,
) error {
	if p.connections == nil {
		return nil
	}
	repairer, ok := p.connections.(interface {
		RepairServer(context.Context, profile.AgentTeamServer) error
	})
	if !ok {
		return profile.ErrServerRuntimeRepairUnsupported
	}
	return repairer.RepairServer(ctx, current)
}

func (p *serverRuntimeParticipant) InvalidateServer(serverID string) {
	p.sessions.InvalidateServer(serverID)
}

type serverConnectionReconciler interface {
	Reconcile(previous, current *profile.AgentTeamServer) error
}

type legacyContextualServerConnectionReconciler interface {
	Reconcile(context.Context, *profile.AgentTeamServer, *profile.AgentTeamServer) error
}

type contextualServerConnectionReconciler interface {
	ReconcileContext(context.Context, *profile.AgentTeamServer, *profile.AgentTeamServer) error
}

func reconcileServerConnection(
	ctx context.Context,
	connections types.ServerConnectionAccessor,
	previous, current *profile.AgentTeamServer,
) error {
	if connections == nil {
		return nil
	}
	if reconciler, ok := connections.(contextualServerConnectionReconciler); ok {
		return reconciler.ReconcileContext(ctx, previous, current)
	}
	if reconciler, ok := connections.(legacyContextualServerConnectionReconciler); ok {
		return reconciler.Reconcile(ctx, previous, current)
	}
	if reconciler, ok := connections.(serverConnectionReconciler); ok {
		return reconciler.Reconcile(previous, current)
	}

	switch {
	case current == nil:
		if previous == nil {
			return nil
		}
		return connections.Disable(previous.ID)
	case previous == nil:
		if current.Enabled {
			return connections.Enable(current.ID)
		}
		return nil
	case previous.Enabled != current.Enabled:
		if current.Enabled {
			return connections.Enable(current.ID)
		}
		return connections.Disable(previous.ID)
	default:
		return nil
	}
}
