"use client";

import { useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { usePathname, useSearchParams } from "next/navigation";

import { ChevronDown } from "lucide-react";

import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
  SidebarGroup,
  SidebarGroupContent,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarMenuSub,
  SidebarMenuSubButton,
  SidebarMenuSubItem,
  useSidebar,
} from "@/components/ui/sidebar";
import { cn } from "@/lib/utils";
import { DEFAULT_CUSTOMER_SETTINGS_SECTION } from "@/navigation/settings/customer-settings-nav";
import type { NavGroup, NavMainItem, NavSubItem } from "@/navigation/sidebar/sidebar-items";

interface NavMainProps {
  readonly items: readonly NavGroup[];
}

const IsComingSoon = () => (
  <span className="ml-auto rounded-md bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
    Soon
  </span>
);

const IsNewBadge = () => (
  <span className="ml-auto shrink-0 rounded-md bg-emerald-600/15 px-1.5 py-0.5 text-[10px] font-semibold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-300">
    New
  </span>
);

function splitNavUrl(url: string): { pathname: string; searchParams: URLSearchParams } {
  const queryIndex = url.indexOf("?");
  if (queryIndex < 0) {
    return { pathname: url, searchParams: new URLSearchParams() };
  }

  return {
    pathname: url.slice(0, queryIndex),
    searchParams: new URLSearchParams(url.slice(queryIndex + 1)),
  };
}

function pathMatches(pathname: string, url: string, searchParams?: URLSearchParams | null): boolean {
  const { pathname: navPathname, searchParams: navSearchParams } = splitNavUrl(url);
  const pathOk = pathname === navPathname || pathname.startsWith(`${navPathname}/`);
  if (!pathOk) {
    return false;
  }

  const expectedSection = navSearchParams.get("section");
  if (!expectedSection) {
    return true;
  }

  const currentSection = searchParams?.get("section") ?? DEFAULT_CUSTOMER_SETTINGS_SECTION;
  return currentSection === expectedSection;
}

function NavLabel({ children }: { children: string }) {
  return (
    <span className="min-w-0 flex-1 truncate" title={children}>
      {children}
    </span>
  );
}

function SubItemLink({ item, active }: { item: NavSubItem; active: boolean }) {
  return (
    <Link
      prefetch={false}
      href={item.url}
      target={item.newTab ? "_blank" : undefined}
      className={cn(
        "flex w-full min-w-0 flex-row items-center gap-2",
        active && "font-medium",
      )}
    >
      {item.icon ? <item.icon className="size-3.5 shrink-0 opacity-80" /> : null}
      <NavLabel>{item.title}</NavLabel>
      {item.isNew && !item.comingSoon ? <IsNewBadge /> : null}
      {item.comingSoon ? <IsComingSoon /> : null}
    </Link>
  );
}

function NavItemExpanded({
  item,
  pathname,
  searchParams,
  open,
  onOpenChange,
}: {
  item: NavMainItem;
  pathname: string;
  searchParams: URLSearchParams;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}) {
  if (!item.subItems?.length) {
    return (
      <SidebarMenuItem>
        <SidebarMenuButton
          asChild
          aria-disabled={item.comingSoon}
          isActive={pathMatches(pathname, item.url, searchParams)}
          tooltip={item.title}
        >
          <Link prefetch={false} href={item.url} target={item.newTab ? "_blank" : undefined}>
            {item.icon && <item.icon />}
            <NavLabel>{item.title}</NavLabel>
            {item.isNew && !item.comingSoon ? <IsNewBadge /> : null}
            {item.comingSoon && <IsComingSoon />}
          </Link>
        </SidebarMenuButton>
      </SidebarMenuItem>
    );
  }

  const groupActive = item.subItems.some((sub) => pathMatches(pathname, sub.url, searchParams));

  return (
    <Collapsible open={open} onOpenChange={onOpenChange} className="group/collapsible">
      <SidebarMenuItem>
        <CollapsibleTrigger asChild>
          <SidebarMenuButton
            disabled={item.comingSoon}
            isActive={groupActive}
            tooltip={item.title}
            className={cn(
              "font-medium",
              open && "bg-sidebar-accent/60 text-sidebar-accent-foreground",
            )}
          >
            {item.icon && <item.icon />}
            <NavLabel>{item.title}</NavLabel>
            {item.isNew && !item.comingSoon ? <IsNewBadge /> : null}
            {item.comingSoon && <IsComingSoon />}
            <ChevronDown
              className={cn(
                "ml-auto size-4 shrink-0 text-sidebar-foreground/50 transition-transform duration-200",
                open && "rotate-180 text-sidebar-foreground",
              )}
            />
          </SidebarMenuButton>
        </CollapsibleTrigger>
        <CollapsibleContent>
          <SidebarMenuSub className="mx-2 mb-1 mt-0.5 gap-0.5 border-sidebar-border/70 py-1">
            {item.subItems.map((subItem) => {
              const active = pathMatches(pathname, subItem.url, searchParams);
              return (
                <SidebarMenuSubItem key={subItem.url}>
                  <SidebarMenuSubButton
                    aria-disabled={subItem.comingSoon}
                    isActive={active}
                    asChild
                    size="sm"
                    className="h-8 min-h-8 w-full justify-start gap-2 px-2"
                  >
                    <SubItemLink item={subItem} active={active} />
                  </SidebarMenuSubButton>
                </SidebarMenuSubItem>
              );
            })}
          </SidebarMenuSub>
        </CollapsibleContent>
      </SidebarMenuItem>
    </Collapsible>
  );
}

function NavItemCollapsed({
  item,
  pathname,
  searchParams,
}: {
  item: NavMainItem;
  pathname: string;
  searchParams: URLSearchParams;
}) {
  if (!item.subItems?.length) {
    return (
      <SidebarMenuItem>
        <SidebarMenuButton
          asChild
          aria-disabled={item.comingSoon}
          tooltip={item.title}
          isActive={pathMatches(pathname, item.url, searchParams)}
        >
          <Link prefetch={false} href={item.url} target={item.newTab ? "_blank" : undefined}>
            {item.icon && <item.icon />}
            <span>{item.title}</span>
          </Link>
        </SidebarMenuButton>
      </SidebarMenuItem>
    );
  }

  const groupActive = item.subItems.some((sub) => pathMatches(pathname, sub.url, searchParams));

  return (
    <SidebarMenuItem>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <SidebarMenuButton disabled={item.comingSoon} tooltip={item.title} isActive={groupActive}>
            {item.icon && <item.icon />}
            <span>{item.title}</span>
            <ChevronDown className="ml-auto size-4 opacity-60" />
          </SidebarMenuButton>
        </DropdownMenuTrigger>
        <DropdownMenuContent className="w-56 space-y-0.5" side="right" align="start">
          <p className="px-2 py-1.5 text-xs font-medium text-muted-foreground">{item.title}</p>
          {item.subItems.map((subItem) => (
            <DropdownMenuItem key={subItem.url} asChild>
              <Link
                prefetch={false}
                href={subItem.url}
                target={subItem.newTab ? "_blank" : undefined}
                className="flex items-center gap-2"
              >
                {subItem.icon && <subItem.icon className="size-3.5" />}
                <span className="truncate">{subItem.title}</span>
                {subItem.isNew && !subItem.comingSoon ? <IsNewBadge /> : null}
                {subItem.comingSoon && <IsComingSoon />}
              </Link>
            </DropdownMenuItem>
          ))}
        </DropdownMenuContent>
      </DropdownMenu>
    </SidebarMenuItem>
  );
}

export function NavMain({ items }: NavMainProps) {
  const path = usePathname();
  const searchParams = useSearchParams();
  const { state, isMobile } = useSidebar();
  const flatItems = useMemo(() => items.flatMap((group) => group.items), [items]);

  const [openByKey, setOpenByKey] = useState<Record<string, boolean>>(() => {
    const initial: Record<string, boolean> = {};
    for (const item of flatItems) {
      if (!item.subItems?.length) continue;
      initial[item.url] = item.subItems.some((sub) => pathMatches(path, sub.url, searchParams));
    }
    return initial;
  });

  useEffect(() => {
    setOpenByKey((current) => {
      let changed = false;
      const next = { ...current };
      for (const item of flatItems) {
        if (!item.subItems?.length) continue;
        const shouldOpen = item.subItems.some((sub) => pathMatches(path, sub.url, searchParams));
        if (shouldOpen && !next[item.url]) {
          next[item.url] = true;
          changed = true;
        }
      }
      return changed ? next : current;
    });
  }, [path, searchParams, flatItems]);

  return (
    <>
      {items.map((group) => (
        <SidebarGroup key={group.id} className="py-0">
          <SidebarGroupContent className="flex flex-col gap-1">
            <SidebarMenu className="gap-0.5">
              {group.items.map((item) => {
                if (state === "collapsed" && !isMobile) {
                  return (
                    <NavItemCollapsed
                      key={item.url}
                      item={item}
                      pathname={path}
                      searchParams={searchParams}
                    />
                  );
                }

                return (
                  <NavItemExpanded
                    key={item.url}
                    item={item}
                    pathname={path}
                    searchParams={searchParams}
                    open={Boolean(openByKey[item.url])}
                    onOpenChange={(open) =>
                      setOpenByKey((current) => ({ ...current, [item.url]: open }))
                    }
                  />
                );
              })}
            </SidebarMenu>
          </SidebarGroupContent>
        </SidebarGroup>
      ))}
    </>
  );
}
