package connector_inbound_routing

import (
	"context"
	"database/sql"
)

// DBRouteResolver is the production implementation of RouteResolver backed by
// _System_ConnectorInboundRoute rows.
//
// Wire this in application startup:
//
//	resolver := connector_inbound_routing.NewDBRouteResolver(db)
//
// The resolver is stateless; it issues one SQL query per call and is safe for
// concurrent use.
type DBRouteResolver struct{ db *sql.DB }

// NewDBRouteResolver constructs a DBRouteResolver that reads from db.
func NewDBRouteResolver(db *sql.DB) *DBRouteResolver {
	return &DBRouteResolver{db: db}
}

// ResolveFlow returns the latest version and flow name for
// (packInstallID, eventKind).  The packInstallID scopes the lookup to the
// event's own pack incarnation so the Dispatcher can share the same
// packInstallID for both route resolution and enqueue — eliminating the
// install-transition race where route-A could be paired with pack-B.
// Returns ErrRouteNotDeclared when no active route row exists for this pair.
// Returns a DB error on query failure.
func (r *DBRouteResolver) ResolveFlow(ctx context.Context, namespace, packInstallID, eventKind string) (int64, string, error) {
	flow, version, found, err := loadConnectorInboundRouteFlowName(ctx, r.db, packInstallID, eventKind)
	if err != nil {
		return 0, "", err
	}
	if !found {
		return 0, "", ErrRouteNotDeclared
	}
	return version, flow, nil
}

// ResolveFlowByVersion returns the flow name for the exact
// (installedPackID, eventKind, version) triple.
// Returns ErrRouteNotDeclared when no row with that version exists.
// Returns ErrRouteVersionSwept when the row exists but is soft-deleted (IsDeleted=1).
// Returns a DB error on query failure.
func (r *DBRouteResolver) ResolveFlowByVersion(ctx context.Context, installedPackID, eventKind string, version int64) (string, error) {
	spec, isDeleted, found, err := loadConnectorInboundRouteByVersion(ctx, r.db, installedPackID, eventKind, version)
	if err != nil {
		return "", err
	}
	if !found {
		return "", ErrRouteNotDeclared
	}
	if isDeleted {
		return "", ErrRouteVersionSwept
	}
	return spec.FlowDeveloperName, nil
}

func (r *DBRouteResolver) ResolveExecutionSpecByVersion(ctx context.Context, installedPackID, eventKind string, version int64) (RouteExecutionSpec, error) {
	spec, isDeleted, found, err := loadConnectorInboundRouteByVersion(ctx, r.db, installedPackID, eventKind, version)
	if err != nil {
		return RouteExecutionSpec{}, err
	}
	if !found {
		return RouteExecutionSpec{}, ErrRouteNotDeclared
	}
	if isDeleted {
		return RouteExecutionSpec{}, ErrRouteVersionSwept
	}
	return NormalizeRouteExecutionSpec(spec)
}
