package pages

import (
	"context"
	"log"

	"github.com/gin-gonic/gin"

	"switchboard-core/store"
)

// TeamOption for template dropdowns.
type TeamOption struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	MemberCount int    `json:"member_count,omitempty"`
	IsActive    bool   `json:"is_active"`
}

// ── Page data structs ────────────────────────

// AdminPageData is what the admin surface templates receive.
type AdminPageData struct {
	Section        string               `json:"section"`
	Category       string               `json:"category"`
	ConfigSections []ConfigSectionEntry `json:"config_sections,omitempty"`
}

// SettingsPageData is what the settings surface templates receive.
// Feature gates (BYOK, personas) moved to sw.auth.policies in v0.37.19.
type SettingsPageData struct {
	Section        string               `json:"section"`
	ConfigSections []ConfigSectionEntry `json:"config_sections,omitempty"` // v0.38.3
}

// ── Loader registration ──────────────────────

// TeamAdminPageData is what the team-admin surface receives.
type TeamAdminPageData struct {
	Section        string               `json:"section"`
	ConfigSections []ConfigSectionEntry `json:"config_sections,omitempty"` // v0.38.3
}

func (e *Engine) registerLoaders() {
	e.RegisterLoader("admin", e.adminLoader)
	e.RegisterLoader("settings", e.settingsLoader)
	e.RegisterLoader("team-admin", e.teamAdminLoader)
}

// Used for manifest validation — DataRequires entries must match a key here.
func (e *Engine) ListDataProviders() []string {
	keys := make([]string, 0, len(e.loaders))
	for k := range e.loaders {
		keys = append(keys, k)
	}
	return keys
}

// ── Admin loader ─────────────────────────────
// Pre-loads ALL dropdown data. Fixes bugs #1 (model roles) and #2 (team scope).

func (e *Engine) adminLoader(c *gin.Context, _ store.Stores) (any, error) {
	section := c.Param("section")
	if section == "" {
		section = "users"
	}

	return &AdminPageData{
		Section:  section,
		Category: sectionCategory(section),
	}, nil
}

// ── Admin helpers ────────────────────────────

// sectionCategory maps an admin section to its category tab.
func sectionCategory(section string) string {
	switch section {
	case "users", "teams", "groups":
		return "people"
	case "workflows":
		return "workflows"
	case "settings", "storage", "packages", "broadcast":
		return "system"
	case "usage", "audit", "stats":
		return "monitoring"
	default:
		return "system"
	}
}

// ── Settings loader ──────────────────────────
// v0.22.7: Reads feature gates from GlobalConfig to control
// which nav links/tabs are visible (BYOK, User Personas).

func (e *Engine) teamAdminLoader(c *gin.Context, s store.Stores) (any, error) {
	section := c.Param("section")
	if section == "" {
		section = "members"
	}
	return &TeamAdminPageData{
		Section:        section,
		ConfigSections: configSectionsForSurface(context.Background(), s, "team-admin"),
	}, nil
}

func (e *Engine) settingsLoader(c *gin.Context, s store.Stores) (any, error) {
	section := c.Param("section")
	if section == "" {
		section = "general"
	}

	return &SettingsPageData{
		Section:        section,
		ConfigSections: configSectionsForSurface(context.Background(), s, "settings"),
	}, nil
}

// ── Config section discovery (v0.38.3) ───────
//
// Packages declare a config_section in their manifest. This helper scans
// enabled packages and returns entries whose surfaces array includes the
// target surface. No new tables or endpoints — purely manifest-driven.

func configSectionsForSurface(ctx context.Context, s store.Stores, surfaceID string) []ConfigSectionEntry {
	if s.Packages == nil {
		return nil
	}
	pkgs, err := s.Packages.List(ctx)
	if err != nil {
		log.Printf("[pages] config sections: failed to list packages: %v", err)
		return nil
	}

	var sections []ConfigSectionEntry
	for _, pkg := range pkgs {
		if !pkg.Enabled || pkg.Manifest == nil {
			continue
		}
		csRaw, ok := pkg.Manifest["config_section"]
		if !ok {
			continue
		}
		cs, ok := csRaw.(map[string]any)
		if !ok {
			continue
		}

		// Check if this section targets the requested surface
		surfacesRaw, _ := cs["surfaces"].([]any)
		if len(surfacesRaw) == 0 {
			continue
		}
		found := false
		for _, v := range surfacesRaw {
			if s, ok := v.(string); ok && s == surfaceID {
				found = true
				break
			}
		}
		if !found {
			continue
		}

		label, _ := cs["label"].(string)
		if label == "" {
			label = pkg.Title
		}
		icon, _ := cs["icon"].(string)
		component, _ := cs["component"].(string)
		if component == "" {
			component = "js/config.js"
		}
		category, _ := cs["category"].(string)
		if category == "" {
			category = "system"
		}

		sections = append(sections, ConfigSectionEntry{
			PackageID: pkg.ID,
			Label:     label,
			Icon:      icon,
			Component: component,
			Category:  category,
		})
	}
	return sections
}
