import {
  Users, Building2, Calendar, BookOpen, LayoutDashboard, LogOut, GraduationCap, MapPin,
  GitBranch, Monitor, ShoppingCart, CalendarDays, Shield, Tag, FileText, Landmark, UserCircle,
  ScrollText, Clock, BarChart3, Award, CalendarClock, CalendarX, CreditCard, SendHorizonal, Hammer, Mail,
  ShieldCheck, AlertTriangle, ClipboardCheck, Sparkles, Target, Gift, Store, Scale,
} from 'lucide-react';
import { useMemo } from 'react';
import { NavLink } from '@/components/NavLink';
import { useAuth } from '@/hooks/useAuth';
import { useQuery } from '@tanstack/react-query';
import {
  Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel,
  SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarFooter, useSidebar,
} from '@/components/ui/sidebar';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import type { PageMetadata } from '@/types';
import { HIDDEN_GROUPS, HIDDEN_PAGE_KEYS } from '@/lib/page-visibility';

// page-key → URL. Hard-coded here because the URL is determined by the
// Laravel route registration (not by the data-driven page record).
const PAGE_URLS: Record<string, string> = {
  dashboard: '/admin',
  orders: '/admin/orders',
  calendar: '/admin/calendar',
  availability: '/admin/availability',
  'bank-holidays': '/admin/bank-holidays',
  certificates: '/admin/certificates',
  waitlist: '/admin/waitlist',
  'course-requests': '/admin/course-requests',
  'date-changes': '/admin/date-changes',
  'location-overrides': '/admin/location-overrides',
  'my-schedule': '/admin/my-schedule',
  courses: '/admin/courses',
  categories: '/admin/categories',
  'course-assignments': '/admin/course-assignments',
  prerequisites: '/admin/prerequisites',
  'e-learning': '/admin/e-learning',
  venues: '/admin/venues',
  trainers: '/admin/trainers',
  companies: '/admin/companies',
  accounts: '/admin/accounts',
  revenue: '/admin/revenue',
  finance: '/admin/finance',
  'discount-codes': '/admin/discount-codes',
  'credit-notes': '/admin/credit-notes',
  reconciliation: '/admin/reconciliation',
  referrals: '/admin/referrals',
  'provider-hub': '/admin/provider-hub',
  sops: '/admin/sops',
  'locktel-cms': '/admin/locktel-cms',
  'user-roles': '/admin/user-roles',
  'role-management': '/admin/role-management',
  services: '/admin/services',
  'audit-log': '/admin/audit-log',
  'email-logs': '/admin/email-logs',
  'ar-assist': '/admin/ar-assist',
  'compliance-docs': '/admin/compliance-docs',
  'risk-assessor': '/admin/risk-assessor',
  'skills-gap': '/admin/skills-gap',
  'compliance-hub': '/admin/compliance-hub',
  'company-portal': '/company-portal',
  'company-site': '/company-site',
  'provider-portal': '/provider-portal',
  'delegate-dashboard': '/delegate-dashboard',
  'delegate-profile': '/delegate-profile',
};

// page-key → icon. Defaults to FileText for unknown (newly created) pages.
const PAGE_ICONS: Record<string, React.ElementType> = {
  dashboard: LayoutDashboard,
  orders: ShoppingCart,
  calendar: CalendarDays,
  availability: Calendar,
  'bank-holidays': CalendarX,
  certificates: Award,
  waitlist: Clock,
  'course-requests': SendHorizonal,
  'date-changes': CalendarClock,
  'location-overrides': Shield,
  'my-schedule': CalendarDays,
  courses: GraduationCap,
  categories: Tag,
  'course-assignments': BookOpen,
  prerequisites: GitBranch,
  'e-learning': Monitor,
  venues: MapPin,
  trainers: Users,
  companies: Building2,
  accounts: UserCircle,
  revenue: BarChart3,
  finance: CreditCard,
  'discount-codes': Tag,
  'credit-notes': ScrollText,
  reconciliation: Scale,
  referrals: Gift,
  'provider-hub': GraduationCap,
  sops: FileText,
  'locktel-cms': Landmark,
  'user-roles': Shield,
  'role-management': ShieldCheck,
  services: Hammer,
  'audit-log': ScrollText,
  'email-logs': Mail,
  'ar-assist': Sparkles,
  'compliance-docs': ClipboardCheck,
  'risk-assessor': AlertTriangle,
  'skills-gap': Target,
  'compliance-hub': ShieldCheck,
  'company-portal': Building2,
  'company-site': Store,
  'provider-portal': Users,
  'delegate-dashboard': GraduationCap,
  'delegate-profile': UserCircle,
};

// page-key → display label override. The DB label is the source of truth, but
// a few historical sidebar names differ from the canonical page label.
const LABEL_OVERRIDES: Record<string, string> = {
  orders: 'Bookings',
  certificates: 'Cert Manager',
  'course-assignments': 'Assignments',
  venues: 'Locations',
  'discount-codes': 'Discounts',
  'user-roles': 'User Roles',
  accounts: 'User Accounts',
};

// Group ordering. Pages whose group is missing from this list fall to the end
// in alphabetical order.
const GROUP_ORDER = [
  '_dashboard', 'Operations', 'Training', 'People', 'Commercial',
  'Tools', 'Compliance', 'System', 'Portals',
];

// HIDDEN_GROUPS / HIDDEN_PAGE_KEYS now live in @/lib/page-visibility so the SOP
// manual hides exactly what the sidebar hides. Remove an entry there to bring a
// group/page back in both places.

const roleLabelMap: Record<string, string> = {
  sys_admin: 'System Admin',
  sys_manager: 'System Manager',
  admin: 'Admin',
  manager: 'Manager',
  company_manager: 'Company Mgr',
  company_trainer: 'Trainer',
  delegate: 'Delegate',
};

const purchasingRoleLabelMap: Record<string, string> = {
  company_trainer: 'Staff',
};

const AdminSidebar = () => {
  const { user, roles, signOut, companyId, permittedPages, pagesCatalog, hasRole } = useAuth();
  const { state } = useSidebar();
  const collapsed = state === 'collapsed';

  const { data: companyData } = useQuery({
    queryKey: ['sidebar-company-type', companyId],
    enabled: !!companyId,
    queryFn: async () => {
      const res = await fetch(`/api/companies/${companyId}/type`);
      if (!res.ok) return null;
      return res.json() as Promise<{ company_type: string } | null>;
    },
  });

  const isPurchasing = companyData?.company_type === 'customer_company';
  const primaryRole = roles[0] ?? '';

  const permittedSet = useMemo(() => new Set(permittedPages), [permittedPages]);

  // Filter the catalog: only pages with a group (sidebar-visible) AND that
  // the current user has access to AND that have a known URL mapping AND that
  // aren't explicitly hidden.
  const sidebarPages = useMemo(
    () => pagesCatalog
      .filter((p): p is PageMetadata & { group: string } => Boolean(p.group))
      .filter((p) => permittedSet.has(p.key))
      .filter((p) => Boolean(PAGE_URLS[p.key]))
      .filter((p) => !HIDDEN_PAGE_KEYS.has(p.key))
      // The Storefront, Provider hub, and the whole course-delivery operational
      // stack only apply to training/hybrid companies — hide them for customer
      // (purchasing) companies, which only book training.
      .filter((p) => !(isPurchasing && [
        'provider-hub', 'company-site',
        'trainers', 'venues', 'calendar', 'availability', 'course-assignments', 'courses', 'prerequisites',
      ].includes(p.key))),
    [pagesCatalog, permittedSet, isPurchasing],
  );

  // Group pages by `group`, sorted within group by `sort_order`.
  const grouped = useMemo(() => {
    const map = new Map<string, PageMetadata[]>();
    for (const p of sidebarPages) {
      const g = p.group ?? '';
      if (!map.has(g)) map.set(g, []);
      map.get(g)!.push(p);
    }
    map.forEach((pages) => pages.sort((a, b) => a.sort_order - b.sort_order));
    return map;
  }, [sidebarPages]);

  // Dashboard sits at the very top; treat it as its own (un-labeled) group.
  const dashboardPage = pagesCatalog.find((p) => p.key === 'dashboard' && permittedSet.has('dashboard'));

  const orderedGroups = useMemo(() => {
    const known = GROUP_ORDER.filter((g) => g === '_dashboard' || grouped.has(g));
    const unknown = Array.from(grouped.keys())
      .filter((g) => !GROUP_ORDER.includes(g))
      .sort();
    return [...known, ...unknown].filter((g) => !HIDDEN_GROUPS.has(g));
  }, [grouped]);

  const labelFor = (p: PageMetadata) => {
    if (isPurchasing && p.key === 'my-schedule') return 'My Bookings';
    return LABEL_OVERRIDES[p.key] ?? p.label;
  };

  const displayRole = isPurchasing
    ? purchasingRoleLabelMap[primaryRole] || roleLabelMap[primaryRole] || primaryRole
    : roleLabelMap[primaryRole] || primaryRole;

  const renderItem = (p: PageMetadata) => {
    const Icon = PAGE_ICONS[p.key] ?? FileText;
    const url = PAGE_URLS[p.key];
    const label = labelFor(p);
    return (
      <SidebarMenuItem key={p.key}>
        <SidebarMenuButton asChild tooltip={collapsed ? label : undefined}>
          <NavLink
            to={url}
            end={url === '/admin'}
            className="hover:bg-sidebar-accent"
            activeClassName="bg-sidebar-accent text-sidebar-primary font-medium"
          >
            <Icon className="mr-2 h-4 w-4 shrink-0" />
            {!collapsed && <span className="flex-1 truncate">{label}</span>}
          </NavLink>
        </SidebarMenuButton>
      </SidebarMenuItem>
    );
  };

  return (
    <Sidebar collapsible="icon">
      <SidebarContent>
        {orderedGroups.map((groupName) => {
          if (groupName === '_dashboard') {
            if (!dashboardPage) return null;
            return (
              <SidebarGroup key="_dashboard">
                <SidebarGroupContent>
                  <SidebarMenu>{renderItem(dashboardPage)}</SidebarMenu>
                </SidebarGroupContent>
              </SidebarGroup>
            );
          }

          const items = grouped.get(groupName) ?? [];
          if (items.length === 0) return null;

          return (
            <SidebarGroup key={groupName}>
              {!collapsed && (
                <SidebarGroupLabel className="text-[10px] uppercase tracking-widest text-muted-foreground/60 px-3 mt-1">
                  {groupName}
                </SidebarGroupLabel>
              )}
              <SidebarGroupContent>
                <SidebarMenu>
                  {items.map(renderItem)}

                  {/* Custom item: company_manager gets a "My Delegates" shortcut
                      to their own company page, inserted under Operations. */}
                  {groupName === 'Operations' && hasRole('company_manager') && companyId && (
                    <SidebarMenuItem key="my-delegates-custom">
                      <SidebarMenuButton asChild tooltip={collapsed ? 'My Delegates' : undefined}>
                        <NavLink
                          to={`/admin/companies/${companyId}`}
                          className="hover:bg-sidebar-accent"
                          activeClassName="bg-sidebar-accent text-sidebar-primary font-medium"
                        >
                          <Users className="mr-2 h-4 w-4 shrink-0" />
                          {!collapsed && <span className="flex-1 truncate">My Delegates</span>}
                        </NavLink>
                      </SidebarMenuButton>
                    </SidebarMenuItem>
                  )}
                </SidebarMenu>
              </SidebarGroupContent>
            </SidebarGroup>
          );
        })}
      </SidebarContent>
      <SidebarFooter className="p-3 border-t border-sidebar-border">
        {!collapsed && (
          <>
            <div className="flex items-center gap-2 mb-1">
              <Badge variant="outline" className="text-[10px] px-1.5 py-0">
                {displayRole}
              </Badge>
            </div>
            <p className="text-[11px] text-muted-foreground truncate mb-2">{user?.email}</p>
          </>
        )}
        <Button variant="outline" size="sm" className="w-full h-8 text-xs" onClick={signOut}>
          <LogOut className="h-3 w-3 shrink-0" />
          {!collapsed && <span className="ml-2">Sign Out</span>}
        </Button>
      </SidebarFooter>
    </Sidebar>
  );
};

export default AdminSidebar;
