// Settings catalog: the static core groups (settingsNav.js) merged with the
// plugin-contributed cards from the ADR-010 get_settings_cards hook, served by
// GET /api/pluginui/settings-cards. Both SettingsLayout (rail) and SettingsIndex
// (landing) read the merged catalog so plugins add settings cards with no core
// edit. Fetched once into a module-level ref and shared across callers.
import { ref, computed } from 'vue'
import { Ruler, Wrench, Cog, Package, Settings, Puzzle, SlidersHorizontal, Palette, Bell, Network, Printer, Droplets } from 'lucide-vue-next'
import api from '../api'
import router from '../router'
import { settingsGroups } from '../views/settings/settingsNav'

// Icon string keys (as returned by the hook) mapped to Lucide components,
// same idea as the sidebar iconMap. Unknown keys fall back to a puzzle piece.
const iconMap = {
  ruler: Ruler,
  wrench: Wrench,
  cog: Cog,
  package: Package,
  settings: Settings,
  puzzle: Puzzle,
  sliders: SlidersHorizontal,
  palette: Palette,
  bell: Bell,
  network: Network,
  printer: Printer,
  droplets: Droplets,
}

function resolveIcon(key) {
  return iconMap[key] || Puzzle
}

// Merge plugin cards into a fresh copy of the core groups. A card joins the
// group whose title matches its `group`; a new group is appended at the end.
function mergeCards(baseGroups, cards) {
  const merged = baseGroups.map(group => ({
    title: group.title,
    cards: [...group.cards],
  }))
  const byTitle = new Map(merged.map(group => [group.title, group]))

  for (const card of cards) {
    const entry = {
      to: card.to,
      icon: resolveIcon(card.icon),
      title: card.title,
      description: card.description || '',
      position: card.position ?? 99,
    }
    let group = byTitle.get(card.group)
    if (!group) {
      group = { title: card.group, cards: [] }
      byTitle.set(card.group, group)
      merged.push(group)
    }
    group.cards.push(entry)
  }

  // Order plugin cards within a group by position; core cards keep their order.
  for (const group of merged) {
    group.cards.sort((a, b) => (a.position ?? 0) - (b.position ?? 0))
  }
  return merged
}

// Drop cards whose target route is not registered in THIS build. settingsNav
// hardcodes plugin settings (PC Access Protocols, Machine Types, VLANs, ...),
// but a lean per-site build only stages the chosen plugins' settings routes;
// showing a card whose route was never staged lands the admin on a blank page.
// Filtering by the router's own route table gates every menu the same way with
// no per-plugin logic. Called inside a computed so the (circular) router import
// is resolved by the time it runs, and so full builds keep every card.
function keepRegistered(baseGroups) {
  const registered = new Set(router.getRoutes().map(r => r.path))
  return baseGroups
    .map(group => ({
      title: group.title,
      cards: group.cards.filter(card => registered.has(card.to)),
    }))
    .filter(group => group.cards.length)
}

// Shared across component instances: seeded with the core groups, replaced with
// the merged catalog once the hook endpoint answers.
const rawGroups = ref(settingsGroups)
const groups = computed(() => keepRegistered(rawGroups.value))
let loaded = false

async function loadCatalog() {
  try {
    const response = await api.get('/pluginui/settings-cards')
    rawGroups.value = mergeCards(settingsGroups, response.data.data || [])
  } catch (error) {
    // Degrade to the core-only catalog; the rail still works without plugins.
    rawGroups.value = settingsGroups
  }
}

export function useSettingsCatalog() {
  if (!loaded) {
    loaded = true
    loadCatalog()
  }
  return { groups }
}
