package handlers

// v0.38.4: Connection type discovery endpoint.
// Returns merged connection types from all active packages.
// Library declarations take precedence over non-library declarations.

import (
	"encoding/json"
	"net/http"

	"github.com/gin-gonic/gin"

	"switchboard-core/store"
)

// ConnectionTypeEntry is a single connection type in the API response.
type ConnectionTypeEntry struct {
	Type         string                       `json:"type"`
	Label        string                       `json:"label"`
	PackageID    string                       `json:"package_id"`
	PackageTitle string                       `json:"package_title"`
	Fields       map[string]map[string]string `json:"fields"`
	Scopes       []string                     `json:"scopes,omitempty"`
}

// ConnectionTypeHandler serves GET /api/v1/connection-types.
type ConnectionTypeHandler struct {
	stores store.Stores
}

func NewConnectionTypeHandler(s store.Stores) *ConnectionTypeHandler {
	return &ConnectionTypeHandler{stores: s}
}

// ListConnectionTypes returns all connection types declared by active packages.
// Library packages take precedence when multiple packages declare the same type.
func (h *ConnectionTypeHandler) ListConnectionTypes(c *gin.Context) {
	ctx := c.Request.Context()
	pkgs, err := h.stores.Packages.List(ctx)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list packages"})
		return
	}

	type entry struct {
		ct        ConnectionTypeEntry
		isLibrary bool
	}
	seen := map[string]*entry{}

	for _, pkg := range pkgs {
		if pkg.Status != "active" || !pkg.Enabled {
			continue
		}
		connsRaw, ok := pkg.Manifest["connections"]
		if !ok {
			continue
		}
		connsJSON, _ := json.Marshal(connsRaw)
		var conns []struct {
			Type   string                       `json:"type"`
			Label  string                       `json:"label"`
			Fields map[string]map[string]string `json:"fields"`
			Scopes []string                     `json:"scopes"`
		}
		if err := json.Unmarshal(connsJSON, &conns); err != nil {
			continue
		}

		isLib := pkg.Type == "library"
		for _, cd := range conns {
			if cd.Type == "" {
				continue
			}
			existing, exists := seen[cd.Type]
			// Library declarations take precedence
			if exists && !isLib && existing.isLibrary {
				continue
			}
			label := cd.Label
			if label == "" {
				label = cd.Type
			}
			seen[cd.Type] = &entry{
				ct: ConnectionTypeEntry{
					Type:         cd.Type,
					Label:        label,
					PackageID:    pkg.ID,
					PackageTitle: pkg.Title,
					Fields:       cd.Fields,
					Scopes:       cd.Scopes,
				},
				isLibrary: isLib,
			}
		}
	}

	result := make([]ConnectionTypeEntry, 0, len(seen))
	for _, e := range seen {
		result = append(result, e.ct)
	}
	c.JSON(http.StatusOK, gin.H{"data": result})
}
