/**
 * Shared navigation defaults — single source of truth.
 *
 * Consumed by PublicNavBar, AppLayout, NavigationSettingsPage, and PublicLayout footer.
 * Eliminates the three duplicate DEFAULT_NAV_ITEMS arrays that previously caused sync bugs.
 */
import React from 'react';
import {
  HomeOutlined,
  SendOutlined,
  EnvironmentOutlined,
  BarChartOutlined,
  CalendarOutlined,
  ScheduleOutlined,
  PlayCircleOutlined,
  HeartOutlined,
  DollarOutlined,
  ShoppingOutlined,
  LinkOutlined,
  GlobalOutlined,
  BookOutlined,
  TagOutlined,
  VideoCameraOutlined,
  FileTextOutlined,
  TrophyOutlined,
  AppstoreOutlined,
  WalletOutlined,
} from '@ant-design/icons';
import type { NavItem } from '@/types/api';

// ---------------------------------------------------------------------------
// Icon map — shared across all consumers
// ---------------------------------------------------------------------------

export const ICON_MAP: Record<string, React.ReactNode> = {
  HomeOutlined: React.createElement(HomeOutlined),
  SendOutlined: React.createElement(SendOutlined),
  EnvironmentOutlined: React.createElement(EnvironmentOutlined),
  BarChartOutlined: React.createElement(BarChartOutlined),
  CalendarOutlined: React.createElement(CalendarOutlined),
  ScheduleOutlined: React.createElement(ScheduleOutlined),
  PlayCircleOutlined: React.createElement(PlayCircleOutlined),
  HeartOutlined: React.createElement(HeartOutlined),
  DollarOutlined: React.createElement(DollarOutlined),
  ShoppingOutlined: React.createElement(ShoppingOutlined),
  LinkOutlined: React.createElement(LinkOutlined),
  GlobalOutlined: React.createElement(GlobalOutlined),
  BookOutlined: React.createElement(BookOutlined),
  TagOutlined: React.createElement(TagOutlined),
  VideoCameraOutlined: React.createElement(VideoCameraOutlined),
  FileTextOutlined: React.createElement(FileTextOutlined),
  TrophyOutlined: React.createElement(TrophyOutlined),
  AppstoreOutlined: React.createElement(AppstoreOutlined),
  WalletOutlined: React.createElement(WalletOutlined),
};

// ---------------------------------------------------------------------------
// Default nav items — the canonical list with group nesting
// ---------------------------------------------------------------------------

export const DEFAULT_NAV_ITEMS: NavItem[] = [
  { id: 'home', label: 'Home', path: '/home', icon: 'HomeOutlined', enabled: true, order: 0, type: 'builtin' },
  { id: 'campaigns', label: 'Campaigns', path: '/campaigns', icon: 'SendOutlined', enabled: true, order: 1, type: 'builtin', featureFlag: 'enableInfluence' },
  { id: 'map', label: 'Map', path: '/map', icon: 'EnvironmentOutlined', enabled: true, order: 2, type: 'builtin', featureFlag: 'enableMap' },
  {
    id: 'scheduling', label: 'Scheduling', path: '', icon: 'AppstoreOutlined', enabled: true, order: 3, type: 'group',
    children: [
      { id: 'shifts', label: 'Shifts', path: '/shifts', icon: 'ScheduleOutlined', enabled: true, order: 0, type: 'builtin', featureFlag: 'enableMap' },
      { id: 'events', label: 'Calendar', path: '/events', icon: 'CalendarOutlined', enabled: true, order: 1, type: 'builtin', featureFlag: 'enableEvents' },
      { id: 'polls', label: 'Polls', path: '/polls', icon: 'BarChartOutlined', enabled: true, order: 2, type: 'builtin', featureFlag: 'enableMeetingPlanner' },
    ],
  },
  { id: 'gallery', label: 'Gallery', path: '/gallery', icon: 'PlayCircleOutlined', enabled: true, order: 4, type: 'builtin', featureFlag: 'enableMediaFeatures' },
  {
    id: 'commerce', label: 'Commerce', path: '', icon: 'WalletOutlined', enabled: true, order: 5, type: 'group', featureFlag: 'enablePayments',
    children: [
      { id: 'pricing', label: 'Pricing', path: '/pricing', icon: 'DollarOutlined', enabled: true, order: 0, type: 'builtin' },
      { id: 'shop', label: 'Shop', path: '/shop', icon: 'ShoppingOutlined', enabled: true, order: 1, type: 'builtin' },
      { id: 'donate', label: 'Donate', path: '/donate', icon: 'HeartOutlined', enabled: true, order: 2, type: 'builtin' },
    ],
  },
  { id: 'wall-of-fame', label: 'Wall of Fame', path: '/wall-of-fame', icon: 'TrophyOutlined', enabled: true, order: 6, type: 'builtin', featureFlag: 'enableSocial' },
  { id: 'pages', label: 'Pages', path: '/pages', icon: 'FileTextOutlined', enabled: true, order: 7, type: 'builtin', featureFlag: 'enableLandingPages' },
  { id: 'landing', label: 'Website', path: '$landing', icon: 'GlobalOutlined', enabled: false, order: 8, type: 'builtin', external: true },
  { id: 'docs', label: 'Docs', path: '$docs', icon: 'BookOutlined', enabled: false, order: 9, type: 'builtin', external: true },
];

// ---------------------------------------------------------------------------
// Admin-specific overrides applied on top of shared defaults
// ---------------------------------------------------------------------------

export const ADMIN_NAV_OVERRIDES: Record<string, Partial<NavItem>> = {
  home: { path: '/', external: true },
  events: { label: 'Events', external: true },
};

// ---------------------------------------------------------------------------
// Feature flags
// ---------------------------------------------------------------------------

/** Flags that default to true (opt-out) — visible unless explicitly disabled */
const OPT_OUT_FLAGS = new Set([
  'enableInfluence',
  'enableMap',
  'enableMediaFeatures',
  'enableEvents',
]);

/** Build the feature flags record from settings */
export function buildFeatureFlags(settings: Record<string, any> | null | undefined): Record<string, boolean | undefined> {
  if (!settings) return {};
  return {
    enableInfluence: settings.enableInfluence,
    enableMap: settings.enableMap,
    enableMediaFeatures: settings.enableMediaFeatures,
    enablePayments: settings.enablePayments,
    enableEvents: settings.enableEvents,
    enableMeetingPlanner: settings.enableMeetingPlanner,
    enableTicketedEvents: settings.enableTicketedEvents,
    enableSocial: settings.enableSocial,
    enableMeet: settings.enableMeet,
    enableLandingPages: settings.enableLandingPages,
  };
}

/** Check whether a single feature flag passes */
export function flagPasses(flagName: string, flags: Record<string, boolean | undefined>): boolean {
  if (OPT_OUT_FLAGS.has(flagName)) {
    return flags[flagName] !== false;
  }
  return flags[flagName] === true;
}

// ---------------------------------------------------------------------------
// Merge: sync stored nav config with code-level defaults
// ---------------------------------------------------------------------------

/** Collect all IDs from items (top-level + children) */
function collectIds(items: NavItem[]): Set<string> {
  const ids = new Set<string>();
  for (const item of items) {
    ids.add(item.id);
    if (item.children) {
      for (const child of item.children) ids.add(child.id);
    }
  }
  return ids;
}

/**
 * Merge stored nav config with code-level defaults.
 * - Syncs icon/path for existing builtins (recursively for children).
 * - Appends missing builtins/groups at end.
 * - Adds missing children inside existing groups.
 */
export function mergeNavDefaults(stored: NavItem[]): NavItem[] {
  const defaultMap = new Map<string, NavItem>();
  for (const d of DEFAULT_NAV_ITEMS) {
    if (d.type === 'builtin' || d.type === 'group') defaultMap.set(d.id, d);
    if (d.children) {
      for (const child of d.children) {
        if (child.type === 'builtin') defaultMap.set(child.id, child);
      }
    }
  }

  const existingIds = collectIds(stored);

  // Sync existing items
  const synced = stored.map(item => {
    const def = defaultMap.get(item.id);
    if (!def) return item;

    if (item.type === 'builtin' && def.type === 'builtin') {
      return { ...item, icon: def.icon, path: def.path };
    }

    if (item.type === 'group' && def.type === 'group' && def.children) {
      // Sync existing children and append missing ones
      const childMap = new Map(def.children.map(c => [c.id, c]));
      const syncedChildren = (item.children || []).map(child => {
        const childDef = childMap.get(child.id);
        return (childDef && child.type === 'builtin') ? { ...child, icon: childDef.icon, path: childDef.path } : child;
      });
      const childIds = new Set(syncedChildren.map(c => c.id));
      const missingChildren = def.children.filter(c => !childIds.has(c.id) && !existingIds.has(c.id));
      const children = missingChildren.length > 0 ? [...syncedChildren, ...missingChildren] : syncedChildren;
      return { ...item, icon: def.icon, children };
    }

    return item;
  });

  // Append missing top-level items (groups + builtins not already present anywhere)
  const syncedIds = collectIds(synced);
  const missing = DEFAULT_NAV_ITEMS.filter(d =>
    (d.type === 'builtin' || d.type === 'group') && !syncedIds.has(d.id)
  );

  return missing.length > 0 ? [...synced, ...missing] : synced;
}

// ---------------------------------------------------------------------------
// Filter: apply feature flags and visibility rules
// ---------------------------------------------------------------------------

/**
 * Filter nav items by feature flags and enabled state.
 * Groups are visible when: (a) group's own featureFlag passes, AND (b) at least one child passes.
 */
export function filterNavItems(items: NavItem[], featureFlags: Record<string, boolean | undefined>): NavItem[] {
  return items
    .filter(item => item.enabled)
    .filter(item => {
      if (item.type === 'group') {
        // Group's own feature flag must pass (if set)
        if (item.featureFlag && !flagPasses(item.featureFlag, featureFlags)) return false;
        // At least one child must be visible
        const visibleChildren = (item.children || [])
          .filter(c => c.enabled)
          .filter(c => !c.featureFlag || flagPasses(c.featureFlag, featureFlags));
        return visibleChildren.length > 0;
      }
      if (!item.featureFlag) return true;
      return flagPasses(item.featureFlag, featureFlags);
    })
    .map(item => {
      if (item.type !== 'group' || !item.children) return item;
      // Filter children within visible groups
      const filteredChildren = item.children
        .filter(c => c.enabled)
        .filter(c => !c.featureFlag || flagPasses(c.featureFlag, featureFlags))
        .sort((a, b) => a.order - b.order);
      return { ...item, children: filteredChildren };
    })
    .sort((a, b) => a.order - b.order);
}

// ---------------------------------------------------------------------------
// Flatten: convert groups to flat list (for footer, Gancio, MkDocs)
// ---------------------------------------------------------------------------

/** Flatten groups into their children. Groups themselves are removed; children promoted to top level. */
export function flattenNavItems(items: NavItem[]): NavItem[] {
  const result: NavItem[] = [];
  for (const item of items) {
    if (item.type === 'group' && item.children) {
      for (const child of item.children) {
        result.push(child);
      }
    } else {
      result.push(item);
    }
  }
  return result;
}

// ---------------------------------------------------------------------------
// Apply admin overrides to shared defaults
// ---------------------------------------------------------------------------

export function applyAdminOverrides(items: NavItem[]): NavItem[] {
  return items.map(item => {
    const override = ADMIN_NAV_OVERRIDES[item.id];
    if (override) return { ...item, ...override };
    if (item.type === 'group' && item.children) {
      const children = item.children.map(child => {
        const childOverride = ADMIN_NAV_OVERRIDES[child.id];
        return childOverride ? { ...child, ...childOverride } : child;
      });
      return { ...item, children };
    }
    return item;
  });
}

// ---------------------------------------------------------------------------
// Active route detection with group support
// ---------------------------------------------------------------------------

/** Check if a path matches any item or its children. Returns true if active. */
export function isItemActive(item: NavItem, currentPath: string): boolean {
  if (item.type === 'group' && item.children) {
    return item.children.some(child => child.path === currentPath || (child.path && currentPath.startsWith(child.path + '/')));
  }
  return item.path === currentPath || (item.path !== '' && currentPath.startsWith(item.path + '/'));
}
