'use client';

import { usePathname } from 'next/navigation';

import { formatSegment, isIdSegment, SEGMENT_LABELS } from '@/lib/route-labels';
import { useBreadcrumbStore } from '@/stores/breadcrumb-store';

export interface SmartBackTarget {
  /** Concrete href the back button should navigate to. Always a real
   *  URL (never router.back()) so deep-link refresh + middle-click open-
   *  in-new-tab both work. */
  href: string;
  /** Short label rendered next to the chevron. Example: "Clients",
   *  "Sarah Doe", "Administration". The button surfaces this as
   *  "Back to {label}" so the user knows where they're headed. */
  label: string;
}

/**
 * Derives the contextual back-target for the current route. Replaces the
 * topbar breadcrumb trail with a single, prominent "Back to X" button.
 *
 * Resolution order:
 *
 *  1. In-app history - if the rep navigated here from another page in
 *     this same SPA session (and that page belongs to the same port),
 *     send them back to that exact page. Lets cross-record drills
 *     (Sarah Doe -> her Yacht -> Back) return to the entity the rep
 *     was actually on, not the logical Yacht-list parent. The
 *     `NavigationHistoryTracker` mounted at the app shell feeds this.
 *  2. Detail-page hints registered via `useBreadcrumbHint` - when a
 *     detail page registers a parent (e.g. "Mary Smith" with href
 *     `/port/clients/abc`), the back button reads "Back to Mary Smith".
 *     This is the fallback when history is unavailable (refresh, direct
 *     link, bookmark, first navigation).
 *  3. URL-derived parent segment - strip the last path segment (and any
 *     trailing UUID), look up the human label, route there. So
 *     /port/admin/branding -> "Back to Administration".
 *  4. null - top-level pages like /port/dashboard, /port/clients don't
 *     get a back button (the sidebar is the way out).
 *
 * Labels for history-derived back are pulled from `labelCache` (snapshot
 * by `useBreadcrumbHint` at the moment each detail page mounted) and
 * fall through to URL-derivation when no label was ever cached.
 */
export function useSmartBack(): SmartBackTarget | null {
  const pathname = usePathname();
  const hint = useBreadcrumbStore((s) => s.hints[pathname]);
  const historyStack = useBreadcrumbStore((s) => s.historyStack);
  const labelCache = useBreadcrumbStore((s) => s.labelCache);

  const segments = pathname.split('/').filter(Boolean);
  // The first segment is always the port slug in this app's routing
  // scheme. A "top-level" page has 2 segments (port + section) -
  // anything shallower has no logical parent within the app.
  if (segments.length <= 2) return null;
  const portSlug = segments[0];
  if (!portSlug) return null;

  // 1. In-app history - prefer the actual previous page in this SPA
  // session when it's within the same port (cross-port jumps should
  // fall back to logical parent so we don't ferry someone across
  // tenant boundaries via a stale stack entry).
  const previousPath = historyStack[historyStack.length - 1];
  if (previousPath && previousPath !== pathname && previousPath.startsWith(`/${portSlug}/`)) {
    const cachedLabel = labelCache[previousPath];
    if (cachedLabel) {
      return { href: previousPath, label: cachedLabel };
    }
    // No cached label means we never saw a useBreadcrumbHint for that
    // path (e.g. list pages, settings pages). Derive from URL so the
    // back button still has something readable to show.
    const derivedLabel = labelFromPath(previousPath);
    if (derivedLabel) return { href: previousPath, label: derivedLabel };
  }

  // 2. Closest registered hint parent. Detail pages register a chain
  // like [{label: "Clients", href: "/port/clients"}, {label: "Mary
  // Smith", href: "/port/clients/abc"}] - the last entry is the one
  // that semantically WAS the previous page.
  if (hint && hint.parents.length > 0) {
    const closest = hint.parents[hint.parents.length - 1];
    if (closest?.href) {
      return { href: closest.href, label: closest.label };
    }
  }

  // URL derivation: walk backwards from the leaf, skipping UUID
  // segments, until we find a non-id segment. The parent path is
  // everything up to and including that segment.
  const significantSegments: Array<{ value: string; index: number }> = [];
  for (let i = 1; i < segments.length; i++) {
    const seg = segments[i];
    if (!seg || isIdSegment(seg)) continue;
    significantSegments.push({ value: seg, index: i });
  }

  // Need at least 2 non-id segments to have a "parent" (one is the
  // current page, one is its parent). With only one significant
  // segment, we're effectively on a list page - no back affordance.
  if (significantSegments.length < 2) return null;

  const parent = significantSegments[significantSegments.length - 2];
  if (!parent) return null;
  const parentPath = '/' + segments.slice(0, parent.index + 1).join('/');
  const parentLabel = SEGMENT_LABELS[parent.value] ?? formatSegment(parent.value);

  // Defensive: never produce an href that strips the port slug. If the
  // walk above produced something that doesn't start with /<portSlug>/
  // we're outside the dashboard layout and shouldn't render a back link
  // at all.
  if (!parentPath.startsWith(`/${portSlug}`)) return null;

  return { href: parentPath, label: parentLabel };
}

/**
 * Best-effort label for a pathname when no cached label exists. Walks
 * the URL backwards, ignoring UUIDs, returning the human-formatted
 * deepest non-id segment. Used as the label for history-derived back
 * targets when the previous page never registered a useBreadcrumbHint
 * (e.g. list pages, settings sub-pages).
 */
function labelFromPath(path: string): string | null {
  const segments = path.split('/').filter(Boolean);
  for (let i = segments.length - 1; i >= 1; i--) {
    const seg = segments[i];
    if (!seg || isIdSegment(seg)) continue;
    return SEGMENT_LABELS[seg] ?? formatSegment(seg);
  }
  return null;
}
