import { Suspense, lazy } from "react"
import { Navigate, type RouteObject } from "react-router-dom"

import { LoadingFallback } from "./pages/_loading"
import { RouteError } from "./pages/_error"
import { LibraryLayout } from "./pages/library/_layout"
import ProductDashboard from "./pages/_product-dashboard"
import { ProductRootGate } from "@/contexts/product-root-gate"
import { DefaultProductRedirect } from "@/contexts/default-product-redirect"

/**
 * Vite route table — implements the multi-product routing pattern
 * (`docs/multi-product-routing-pattern.md` in the source workspace,
 * vendored to consumer apps via `exxat-ui sync-extras`):
 *
 *  - **Per-product dashboards** live under `/<product-root>/dashboard`
 *    (Rule 1). Switching products navigates to that root's dashboard
 *    (Rule 2 — driven by `useProductSwitch` in
 *    `contexts/product-route-sync.tsx`).
 *  - **Back-compat redirects** at the workspace root (`/dashboard` →
 *    `/prism/dashboard`) keep deep links from before this refactor working
 *    without a server-side 308.
 *  - **Library** stays mounted at `/library/*` for now — it's effectively
 *    shell-global today (only Prism uses it) and the library subsystem
 *    has internal `pathname === LIBRARY_LIST_PATH` checks across four
 *    files that we'd have to refactor before moving it. Once a second
 *    product needs its own Library, peel `/library` into per-product
 *    mounts and rewrite those checks behind a `stripProductPrefix(pathname)`
 *    helper.
 *  - **Shell-global routes** (`/settings`, `/help`) stay at the root —
 *    they exist per *user*, not per *product* (see
 *    `.cursor/rules/exxat-product-routing.mdc` "When this rule does not
 *    apply").
 *  - **DS demo routes** (`/columns`, `/tokens-themes`) stay at the
 *    root while they're still development surfaces — same exception.
 */

function lazyPage(loader: () => Promise<{ default: React.ComponentType }>) {
  const Lazy = lazy(loader)
  return (
    <Suspense fallback={<LoadingFallback />}>
      <Lazy />
    </Suspense>
  )
}

/** Back-compat redirect for `/dashboard` → default product dashboard. */
function LegacyRedirectToDefaultDashboard({ rootSegment }: { rootSegment: string }) {
  return <DefaultProductRedirect />
}

// ─────────────────────────────────────────────────────────────────────────────
// Per-product children
// ─────────────────────────────────────────────────────────────────────────────
//
// Today only the dashboard is under a product root. Once Library / Placements
// / Settings sub-screens move under products, append their children here (or
// extract per-product factories like `prismChildren()`, `oneSitesChildren()`).

function productChildren(): RouteObject[] {
  return [
    { index: true, element: <Navigate to="dashboard" replace /> },
    {
      path: "dashboard",
      element: <ProductDashboard />,
      errorElement: <RouteError />,
    },
  ]
}

export const routes: RouteObject[] = [
  // ───────────────────────────────────────────────────────────────────────
  // Root + back-compat redirects
  // ───────────────────────────────────────────────────────────────────────
  // Cold-start landing → tenant default product (Prism when unset).
  { index: true, element: <DefaultProductRedirect /> },

  // Pre-product back-compat for the only previously-rooted hub.
  { path: "dashboard", element: <LegacyRedirectToDefaultDashboard rootSegment="dashboard" /> },
  // ───────────────────────────────────────────────────────────────────────
  // Product-owned roots (Rule 1) — built-in slugs + custom suffix slugs.
  // MUST stay after shell-global routes so `/settings` etc. are not captured.
  // ───────────────────────────────────────────────────────────────────────
  {
    path: ":productRootSegment",
    element: <ProductRootGate />,
    children: productChildren(),
    errorElement: <RouteError />,
  },


  // ───────────────────────────────────────────────────────────────────────
  // Shell-global routes (per-user, not per-product)
  // ───────────────────────────────────────────────────────────────────────
  {
    path: "library",
    element: <LibraryLayout />,
    errorElement: <RouteError />,
    children: [
      { index: true, element: lazyPage(() => import("./pages/library/index")) },
      { path: "all", element: lazyPage(() => import("./pages/library/all")) },
      { path: "find", element: lazyPage(() => import("./pages/library/find")) },
      { path: "list", element: lazyPage(() => import("./pages/library/list")) },
      { path: "new", element: lazyPage(() => import("./pages/library/new")) },
    ],
  },
  {
    path: "settings",
    element: lazyPage(() => import("./pages/settings")),
    errorElement: <RouteError />,
  },
  {
    path: "help",
    element: lazyPage(() => import("./pages/help")),
    errorElement: <RouteError />,
  },

  // ───────────────────────────────────────────────────────────────────────
  // DS demo routes (development surfaces — still at root per the rule's
  // exception; once promoted into a product hub they adopt that subpath).
  // ───────────────────────────────────────────────────────────────────────
  {
    path: "columns",
    element: lazyPage(() => import("./pages/columns")),
    errorElement: <RouteError />,
  },
  {
    path: "tokens-themes",
    element: lazyPage(() => import("./pages/tokens-themes")),
    errorElement: <RouteError />,
  },

  {
    path: "*",
    element: lazyPage(() => import("./pages/_not-found")),
  },
]
