'use client';

import { useState } from 'react';
import Image from 'next/image';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import {
  LayoutDashboard,
  Users,
  UsersRound,
  Bookmark,
  Anchor,
  KeyRound,
  Ship,
  Building2,
  Receipt,
  FileText,
  FileBarChart,
  Inbox,
  MailQuestion,
  Camera,
  Globe,
  Settings,
  Shield,
  ScrollText,
  RefreshCw,
  Home,
  ChevronLeft,
  ChevronRight,
  ChevronDown,
  ChevronUp,
} from 'lucide-react';

import { cn } from '@/lib/utils';
import { formatRole } from '@/lib/constants';
import { useUIStore } from '@/stores/ui-store';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Badge } from '@/components/ui/badge';
import { Separator } from '@/components/ui/separator';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { UserMenu } from '@/components/layout/user-menu';
import { useUmamiActive } from '@/components/website-analytics/use-website-analytics';
import type { UserPortRole } from '@/lib/db/schema/users';
import type { Role } from '@/lib/db/schema/users';
import type { Port } from '@/lib/db/schema/ports';

interface SidebarProps {
  portRoles: (UserPortRole & { port: { id: string; slug: string; name: string }; role: Role })[];
  isSuperAdmin?: boolean;
  user?: { name: string; email: string };
  /** Ports the user has access to. Drives the footer port switcher. */
  ports?: Port[];
  /** Per-port logo URLs resolved server-side in the dashboard layout.
   *  The sidebar header swaps to the current port's logo via the UI
   *  store's `currentPortId`. Null entries render the wordmark fallback. */
  portLogoUrls?: Record<string, string | null>;
  /** Per-port `tenancies_module_enabled` resolution. Gates the Tenancies
   *  sidebar entry. Resolved server-side in the dashboard layout. */
  tenanciesModuleByPort?: Record<string, boolean>;
  /** Per-port `expenses_module_enabled` resolution. Gates the Expenses
   *  + How-to-upload-receipts sidebar entries. Resolved server-side in
   *  the dashboard layout. Defaults to true (feature on) per port when
   *  the map is missing for the active port. */
  expensesModuleByPort?: Record<string, boolean>;
  /** Per-port `residential_module_enabled` resolution. Gates the entire
   *  "Residential" sidebar section. Resolved server-side in the dashboard
   *  layout. Defaults to true (feature on) per port when the map is
   *  missing for the active port. */
  residentialModuleByPort?: Record<string, boolean>;
}

interface NavItem {
  href: string;
  label: string;
  icon: React.ElementType;
  exact?: boolean;
}

interface NavSection {
  title: string;
  items: NavItem[];
  adminRequired?: boolean;
  /** When true, only render if the user has marina-side access. */
  marinaRequired?: boolean;
  /** When true, only render if the user has residential-side access. */
  residentialRequired?: boolean;
  /** When true, only render if the residential module is enabled for the
   *  current port. Resolved against `residentialModuleByPort`. */
  requiresResidentialModule?: boolean;
  /** When true, only render if Umami analytics is wired up for the port. */
  umamiRequired?: boolean;
}

interface NavItemGated extends NavItem {
  /** When true, only render this item if the tenancies module is enabled
   *  for the current port. Resolved against `tenanciesModuleByPort`. */
  requiresTenanciesModule?: boolean;
  /** When true, only render this item if the expenses module is enabled
   *  for the current port. Resolved against `expensesModuleByPort`. */
  requiresExpensesModule?: boolean;
  /** When true, only render this item if Umami analytics is wired up
   *  for the port. */
  umamiRequired?: boolean;
}

function buildNavSections(portSlug: string | undefined): NavSection[] {
  const base = portSlug ? `/${portSlug}` : '';

  return [
    {
      title: 'Main',
      marinaRequired: true,
      items: [
        { href: `${base}/dashboard`, label: 'Dashboard', icon: LayoutDashboard },
        { href: `${base}/clients`, label: 'Clients', icon: Users },
        { href: `${base}/client-groups`, label: 'Client Groups', icon: UsersRound },
        { href: `${base}/yachts`, label: 'Yachts', icon: Ship },
        { href: `${base}/companies`, label: 'Companies', icon: Building2 },
        { href: `${base}/interests`, label: 'Interests', icon: Bookmark },
        { href: `${base}/inquiries`, label: 'Inquiries', icon: MailQuestion },
        { href: `${base}/berths`, label: 'Berths', icon: Anchor },
        {
          href: `${base}/tenancies`,
          label: 'Tenancies',
          icon: KeyRound,
          requiresTenanciesModule: true,
        } as NavItemGated,
      ],
    },
    {
      title: 'Residential',
      residentialRequired: true,
      requiresResidentialModule: true,
      items: [
        {
          href: `${base}/residential/clients`,
          label: 'Residential Clients',
          icon: Home,
        },
        {
          href: `${base}/residential/interests`,
          label: 'Residential Interests',
          icon: Bookmark,
        },
      ],
    },
    {
      title: 'Insights',
      marinaRequired: true,
      items: [
        // Reports surface (dashboard / clients / berths / interests
        // builders, plus templates / schedules / runs). Routes existed
        // since the report-builder ship but the sidebar entry was never
        // wired - reps had to land here via direct link.
        {
          href: `${base}/reports`,
          label: 'Reports',
          icon: FileBarChart,
        },
        // Marketing / Umami integration. Distinct from the main dashboard
        // (which is sales-focused) so the audience and the metrics don't
        // compete for visual real estate. Hidden when Umami isn't wired
        // up via the per-item umamiRequired flag below.
        {
          href: `${base}/website-analytics`,
          label: 'Website analytics',
          icon: Globe,
          umamiRequired: true,
        } as NavItemGated,
      ],
    },
    {
      title: 'Documents',
      marinaRequired: true,
      items: [{ href: `${base}/documents`, label: 'Documents', icon: FileText }],
    },
    {
      title: 'Financial',
      marinaRequired: true,
      items: [
        {
          href: `${base}/expenses`,
          label: 'Expenses',
          icon: Receipt,
          requiresExpensesModule: true,
        } as NavItemGated,
        // Invoices nav entry removed - the expense-to-PDF flow is the
        // only invoicing surface now (employee expense reports). The
        // standalone /invoices route still exists for any back-compat
        // links but is no longer surfaced in nav.
        // Dedicated explainer page covers "Add to Home Screen" install
        // + walkthrough; the mobile-only scanner UI itself lives at /scan
        // and is reached via the install or the explainer page button.
        {
          href: `${base}/invoices/upload-receipts`,
          label: 'How to upload receipts',
          icon: Camera,
          requiresExpensesModule: true,
        } as NavItemGated,
      ],
    },
    {
      title: 'Communication',
      marinaRequired: true,
      items: [
        // Email tab removed: deferred building a full inbox/threading
        // feature (would require Google OAuth + scope review + IMAP
        // syncing infra). This entry routes to the merged
        // Alerts + Reminders surface (2026-05-11) - explicit name so
        // reps don't mistake it for an email inbox.
        { href: `${base}/inbox`, label: 'Alerts & Reminders', icon: Inbox },
      ],
    },
    {
      title: 'Admin',
      adminRequired: true,
      items: [
        { href: `${base}/settings`, label: 'Settings', icon: Settings },
        { href: `${base}/admin`, label: 'Administration', icon: Shield },
        // F14: audit log page existed but had no nav link.
        { href: `${base}/admin/audit`, label: 'Audit Log', icon: ScrollText },
        // #67 Phase 5: surfaces berths flipped manually without a backing
        // interest so reps can run the catch-up wizard.
        {
          href: `${base}/admin/berths/reconcile`,
          label: 'Reconcile berths',
          icon: RefreshCw,
        },
      ],
    },
  ];
}

function NavItemLink({
  item,
  collapsed,
  active,
}: {
  item: NavItem;
  collapsed: boolean;
  active: boolean;
}) {
  const content = (
    <Link
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      href={item.href as any}
      className={cn(
        'relative flex items-center gap-3 px-3 py-2 rounded-md text-sm font-medium transition-all duration-150',
        'text-slate-700 hover:bg-accent hover:text-foreground',
        active && 'bg-accent text-foreground pl-[14px]',
        collapsed && 'justify-center px-2',
      )}
    >
      {active && !collapsed && (
        <span
          aria-hidden
          className="absolute left-0 top-1 bottom-1 w-1 rounded-r-full bg-[#3a7bc8]"
        />
      )}
      <item.icon
        className={cn(
          'shrink-0',
          active ? 'text-[#3a7bc8]' : 'text-slate-500',
          collapsed ? 'w-5 h-5' : 'w-4 h-4',
        )}
      />
      {!collapsed && <span>{item.label}</span>}
    </Link>
  );

  if (collapsed) {
    return (
      <Tooltip>
        <TooltipTrigger asChild>{content}</TooltipTrigger>
        <TooltipContent side="right" className="font-medium">
          {item.label}
        </TooltipContent>
      </Tooltip>
    );
  }

  return content;
}

function SidebarContent({
  collapsed,
  portSlug,
  portRoles,
  isSuperAdmin,
  hasAdminAccess,
  hasMarinaAccess,
  hasResidentialAccess,
  tenanciesModuleEnabled,
  expensesModuleEnabled,
  residentialModuleEnabled,
  user,
  ports,
  currentPort,
  currentLogoUrl,
  onToggleCollapse,
}: {
  collapsed: boolean;
  portSlug: string | undefined;
  portRoles: SidebarProps['portRoles'];
  isSuperAdmin: boolean;
  hasAdminAccess: boolean;
  hasMarinaAccess: boolean;
  hasResidentialAccess: boolean;
  tenanciesModuleEnabled: boolean;
  expensesModuleEnabled: boolean;
  residentialModuleEnabled: boolean;
  user?: SidebarProps['user'];
  ports?: Port[];
  currentPort: Port | null;
  currentLogoUrl: string | null;
  /** When provided, renders the collapse toggle row above the user footer (desktop). */
  onToggleCollapse?: () => void;
}) {
  const pathname = usePathname();
  const [adminExpanded, setAdminExpanded] = useState(true);
  const sections = buildNavSections(portSlug);
  const umami = useUmamiActive('today');
  const umamiConfigured = !umami.isLoading && umami.data?.notConfigured !== true;

  // Small label under the user identity when the user has access to more
  // than one port - disambiguates which port is currently active without
  // pulling the port name back into the breadcrumbs.
  const showPortLabel = !!ports && ports.length > 1;
  const currentPortName = showPortLabel
    ? (ports.find((p) => p.slug === portSlug)?.name ?? null)
    : null;

  // Pre-compute every nav href the sidebar offers across all sections so
  // the active-state check can do longest-prefix-match. Without this,
  // /invoices/upload-receipts would highlight both "Invoices" and "How to
  // upload receipts" - every ancestor prefix matches.
  const allHrefs = sections.flatMap((s) => s.items.map((i) => i.href));

  function isActive(href: string, exact?: boolean): boolean {
    if (exact) return pathname === href;
    if (!pathname.startsWith(href)) return false;
    // Active only if no other sidebar item has a strictly more-specific
    // prefix match. That makes the highlight follow the URL into the
    // deepest registered route (e.g. /invoices/upload-receipts wins over
    // /invoices when both are sidebar items).
    return !allHrefs.some((other) => other.length > href.length && pathname.startsWith(other));
  }

  // Sidebar header showcases the Port Nimara logo as the visual anchor of
  // the brand. Collapse toggle is a small overlay button so it doesn't
  // compete with the logo for attention.
  return (
    <TooltipProvider delayDuration={0}>
      <div className="flex flex-col h-full bg-white">
        {/* Brand header - logo centered. Soft hairline below echoes the
            inter-section separators in the nav so the eye reads the logo
            as a distinct top-row, not a floating element. */}
        <div
          className={cn(
            'relative flex items-center justify-center border-b border-slate-200',
            collapsed ? 'h-16 px-2' : 'h-24 px-4',
          )}
        >
          {currentLogoUrl ? (
            <Image
              src={currentLogoUrl}
              alt={currentPort?.name ?? 'Logo'}
              width={collapsed ? 40 : 72}
              height={collapsed ? 40 : 72}
              className="rounded-full shadow-sm"
              unoptimized
              priority
            />
          ) : (
            <div className="flex h-12 items-center px-3 text-sm font-semibold text-slate-700">
              {currentPort?.name ?? 'CRM'}
            </div>
          )}
          {onToggleCollapse && (
            <button
              type="button"
              onClick={onToggleCollapse}
              aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
              className={cn(
                'absolute right-2 flex h-6 w-6 items-center justify-center rounded-md text-slate-400 hover:bg-slate-100 hover:text-slate-700 transition-colors',
                collapsed ? 'top-1' : 'top-2',
              )}
            >
              {collapsed ? (
                <ChevronRight className="w-4 h-4" aria-hidden />
              ) : (
                <ChevronLeft className="w-4 h-4" aria-hidden />
              )}
            </button>
          )}
        </div>

        {/* Nav */}
        <ScrollArea className="flex-1 py-2">
          <nav className="px-2 space-y-4">
            {sections.map((section) => {
              if (section.adminRequired && !hasAdminAccess) return null;
              if (section.marinaRequired && !hasMarinaAccess) return null;
              if (section.residentialRequired && !hasResidentialAccess) return null;
              if (section.requiresResidentialModule && !residentialModuleEnabled) return null;
              if (section.umamiRequired && !umamiConfigured) return null;

              // Resolve the items this section will actually render after
              // per-item module/permission gating. If they all gate off
              // (e.g. the Financial section once the Expenses module is
              // disabled), skip the whole section so its header + separator
              // don't linger as an orphaned label.
              const visibleItems = section.items.filter((item) => {
                const gated = item as NavItemGated;
                if (gated.requiresTenanciesModule && !tenanciesModuleEnabled) return false;
                if (gated.requiresExpensesModule && !expensesModuleEnabled) return false;
                if (gated.umamiRequired && !umamiConfigured) return false;
                return true;
              });
              if (visibleItems.length === 0) return null;

              return (
                <div key={section.title}>
                  {!collapsed && (
                    <div className="flex items-center justify-between px-1 mb-1">
                      <span className="text-slate-500 text-xs font-semibold uppercase tracking-[0.12em]">
                        {section.title}
                      </span>
                      {section.adminRequired && (
                        <button
                          onClick={() => setAdminExpanded((v) => !v)}
                          className="text-slate-400 hover:text-slate-700 transition-colors"
                        >
                          {adminExpanded ? (
                            <ChevronUp className="w-3 h-3" aria-hidden />
                          ) : (
                            <ChevronDown className="w-3 h-3" aria-hidden />
                          )}
                        </button>
                      )}
                    </div>
                  )}
                  {(!section.adminRequired || adminExpanded || collapsed) && (
                    <ul className="space-y-0.5">
                      {visibleItems.map((item) => (
                        <li key={item.href}>
                          <NavItemLink
                            item={item}
                            collapsed={collapsed}
                            active={isActive(item.href, item.exact)}
                          />
                        </li>
                      ))}
                    </ul>
                  )}
                  <Separator className="mt-3 bg-slate-200" aria-hidden />
                </div>
              );
            })}
          </nav>
        </ScrollArea>

        {/* User footer - entire row is the trigger for the UserMenu so the
            user can click their name/avatar to access Settings /
            port-switcher / sign-out. The same UserMenu component drives the
            top-right avatar dropdown, so the menu items stay consistent. */}
        <div className={cn('border-t border-slate-200 p-2', collapsed && 'flex justify-center')}>
          {collapsed ? (
            <UserMenu
              align="start"
              user={user}
              ports={ports}
              trigger={
                <button
                  type="button"
                  aria-label="Open user menu"
                  className="rounded-full focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[#3a7bc8] focus-visible:ring-offset-2 focus-visible:ring-offset-white"
                >
                  <Avatar className="w-8 h-8 cursor-pointer">
                    <AvatarImage src={undefined} />
                    <AvatarFallback className="bg-[#3a7bc8] text-white text-xs font-semibold">
                      {(user?.name ?? 'U').slice(0, 1).toUpperCase()}
                    </AvatarFallback>
                  </Avatar>
                </button>
              }
            />
          ) : (
            <UserMenu
              align="start"
              user={user}
              ports={ports}
              trigger={
                <button
                  type="button"
                  aria-label="Open user menu"
                  className="flex w-full items-center gap-3 rounded-md p-1.5 text-left transition-colors hover:bg-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[#3a7bc8] focus-visible:ring-offset-2 focus-visible:ring-offset-white"
                >
                  <Avatar className="w-8 h-8 shrink-0 shadow-sm ring-2 ring-slate-200">
                    <AvatarImage src={undefined} />
                    <AvatarFallback className="bg-[#3a7bc8] text-white text-xs font-semibold">
                      {(user?.name ?? 'U').slice(0, 1).toUpperCase()}
                    </AvatarFallback>
                  </Avatar>
                  <div className="flex-1 min-w-0">
                    <p className="text-foreground text-sm font-medium truncate">
                      {user?.name ?? 'User'}
                    </p>
                    <Badge
                      variant="outline"
                      className="text-xs px-1.5 py-0 text-slate-500 border-slate-300 mt-0.5"
                    >
                      {isSuperAdmin ? 'Super Admin' : formatRole(portRoles[0]?.role?.name)}
                    </Badge>
                    {currentPortName && (
                      <p className="mt-1 text-xs text-slate-400 truncate">{currentPortName}</p>
                    )}
                  </div>
                </button>
              }
            />
          )}
        </div>
      </div>
    </TooltipProvider>
  );
}

export function Sidebar({
  portRoles,
  isSuperAdmin = false,
  user,
  ports,
  portLogoUrls,
  tenanciesModuleByPort,
  expensesModuleByPort,
  residentialModuleByPort,
}: SidebarProps) {
  // Sidebar collapse removed - design preference is the always-expanded
  // form. Forcibly false; the store flag stays for backwards-compat with
  // any code still reading it.
  const sidebarCollapsed = false;
  const currentPortSlug = useUIStore((s) => s.currentPortSlug);
  const currentPortId = useUIStore((s) => s.currentPortId);
  const currentPort = ports?.find((p) => p.id === currentPortId) ?? ports?.[0] ?? null;
  const currentLogoUrl = currentPortId ? (portLogoUrls?.[currentPortId] ?? null) : null;
  const tenanciesModuleEnabled = currentPortId
    ? (tenanciesModuleByPort?.[currentPortId] ?? false)
    : false;
  // Expenses defaults to enabled when the port's entry is missing - the
  // registry default is `true`, so a port that's never explicitly
  // toggled the feature should keep it visible.
  const expensesModuleEnabled = currentPortId
    ? (expensesModuleByPort?.[currentPortId] ?? true)
    : true;
  // Residential defaults to enabled when the port's entry is missing -
  // the registry default is `true`, so a port that's never explicitly
  // toggled the feature keeps the section visible.
  const residentialModuleEnabled = currentPortId
    ? (residentialModuleByPort?.[currentPortId] ?? true)
    : true;

  // Super admins see every section regardless of role rows.
  const hasAdminAccess =
    isSuperAdmin ||
    portRoles.some(
      (pr) =>
        pr.role?.permissions?.admin?.manage_users || pr.role?.permissions?.admin?.manage_settings,
    );

  const hasMarinaAccess =
    isSuperAdmin || portRoles.some((pr) => pr.role?.permissions?.clients?.view);

  const hasResidentialAccess =
    isSuperAdmin ||
    portRoles.some((pr) => pr.residentialAccess || pr.role?.permissions?.residential_clients?.view);

  return (
    <aside
      className={cn(
        'relative hidden md:flex flex-col h-screen border-r border-slate-200 transition-all duration-200 ease-in-out shrink-0 bg-white',
        sidebarCollapsed ? 'w-sidebar-collapsed' : 'w-sidebar',
      )}
    >
      <SidebarContent
        collapsed={sidebarCollapsed}
        portSlug={currentPortSlug ?? undefined}
        portRoles={portRoles}
        isSuperAdmin={isSuperAdmin}
        hasAdminAccess={hasAdminAccess}
        hasMarinaAccess={hasMarinaAccess}
        hasResidentialAccess={hasResidentialAccess}
        tenanciesModuleEnabled={tenanciesModuleEnabled}
        expensesModuleEnabled={expensesModuleEnabled}
        residentialModuleEnabled={residentialModuleEnabled}
        user={user}
        ports={ports}
        currentPort={currentPort}
        currentLogoUrl={currentLogoUrl}
      />
    </aside>
  );
}
