'use client'

import { useMemo, useState, useEffect, type ReactNode } from 'react'
import { ExternalLink, Plus } from 'lucide-react'
import { Sidebar } from './Sidebar.js'
import { Header } from './Header.js'
import { Breadcrumbs } from '../components/Breadcrumbs.js'
import { AdminShell } from './primitives/AdminShell.js'
import { Toaster } from 'sonner'

export interface LayoutProps {
  config: any
  session: any
  currentPath: string
  onNavigate: (path: string) => void
  onLogout?: () => void
  children: ReactNode
}

/**
 * Layout — thin shell that wires Sidebar/Header/Breadcrumbs into the
 * `<AdminShell>` primitive.
 *
 * `AdminShell` (in `./primitives/AdminShell.tsx`) owns the actual layout
 * algorithm (CSS Grid on desktop, fixed slide-in overlay on mobile,
 * JS-driven `matchMedia` breakpoint) so that every layout decision lives
 * in one place. Per-product chrome (Sidebar, Header, Breadcrumbs)
 * composes on top of it.
 *
 * DO NOT re-implement layout logic in this file — extend `AdminShell`
 * instead. The previous flex + `fixed`↔`static` toggle caused recurring
 * sidebar-overlap bugs; the grid-based primitive is the contract.
 */
export function Layout({
  config,
  session,
  currentPath,
  onNavigate,
  onLogout,
  children,
}: LayoutProps) {
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false)
  const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false)

  useEffect(() => {
    setMobileSidebarOpen(false)
  }, [currentPath])

  const pageActions = useMemo(
    () => computePageActions({ currentPath, config, onNavigate }),
    [currentPath, config, onNavigate],
  )

  return (
    <>
      <Toaster position="bottom-right" />
      <AdminShell
        mobileSidebarOpen={mobileSidebarOpen}
        onMobileSidebarClose={() => setMobileSidebarOpen(false)}
        sidebar={
          <Sidebar
            collapsed={sidebarCollapsed}
            onToggleCollapse={() => setSidebarCollapsed(!sidebarCollapsed)}
            currentPath={currentPath}
            onNavigate={onNavigate}
            config={config}
          />
        }
        header={
          <Header
            onToggleSidebar={() => setMobileSidebarOpen(!mobileSidebarOpen)}
            session={session}
            onNavigate={onNavigate}
            onLogout={onLogout}
            pageActions={pageActions}
          />
        }
        breadcrumbs={<Breadcrumbs currentPath={currentPath} onNavigate={onNavigate} />}
      >
        <div className="h-full">{children}</div>
      </AdminShell>
    </>
  )
}

// ─── Page actions ────────────────────────────────────────────────────────────

interface PageActionsContext {
  currentPath: string
  config: any
  onNavigate: (path: string) => void
}

/**
 * Per-route primary actions that render on the right of the top bar.
 *
 * Centralised here so the top bar's actions row stays consistent
 * across view changes — no flicker on navigation, no per-view header
 * reimplementation. Views that need view-local actions (e.g. a
 * "Save draft" button on the post editor) continue to render them
 * inside their own hero; this slot is for the highest-level
 * primary/secondary pair that mirrors the reference dashboard.
 *
 * Resolution rules:
 *   - Dashboard / home → "+ New Post" + "View Site"
 *   - List views → just "+ New <Type>"
 *   - Editor views → no top-bar action (editor renders its own toolbar)
 */
function computePageActions({
  currentPath,
  config,
  onNavigate,
}: PageActionsContext): ReactNode | null {
  const collections = collectionList(config)
  const postCollections = collections.filter((c) => c.type === 'post')
  const newPostPath = resolveNewPostPath(postCollections)
  const siteUrl: string | null = config?.site?.url ?? config?.seo?.siteUrl ?? null

  const isDashboard = currentPath === '/' || currentPath === '/dashboard'

  // Dashboard: keep the existing "+ New Post" / "View Site" pair. With
  // a single Post Type we route straight to its editor; with several we
  // route to the picker so the user can choose the type first.
  if (isDashboard) {
    return (
      <>
        <button
          type="button"
          onClick={() => onNavigate(newPostPath)}
          className="bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-ring inline-flex items-center gap-1.5 rounded-lg px-3.5 py-1.5 text-sm font-medium shadow-sm transition-colors focus:outline-none focus-visible:ring-2"
        >
          <Plus className="h-3.5 w-3.5" aria-hidden />
          New Post
        </button>
        {siteUrl ? (
          <a
            href={siteUrl}
            target="_blank"
            rel="noopener noreferrer"
            className="border-border bg-background text-foreground hover:bg-accent inline-flex items-center gap-1.5 rounded-lg border px-3 py-1.5 text-sm font-medium transition-colors"
          >
            <ExternalLink className="h-3.5 w-3.5" aria-hidden />
            View Site
          </a>
        ) : null}
      </>
    )
  }

  // Posts area — "+ New Post" + "Manage types" on the list page;
  // "+ New Post Type" on the types page. The buttons live in the top
  // bar so the page header stays clean. See the dashboard rule for
  // why these come from a single config-aware helper.
  if (currentPath === '/posts') {
    return (
      <button
        type="button"
        onClick={() => onNavigate(newPostPath)}
        className="bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-ring inline-flex items-center gap-1.5 rounded-lg px-3.5 py-1.5 text-sm font-medium shadow-sm transition-colors focus:outline-none focus-visible:ring-2"
      >
        <Plus className="h-3.5 w-3.5" aria-hidden />
        New Post
      </button>
    )
  }

  if (currentPath === '/posts/types') {
    return (
      <button
        type="button"
        onClick={() => onNavigate('/posts/types/new')}
        className="bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-ring inline-flex items-center gap-1.5 rounded-lg px-3.5 py-1.5 text-sm font-medium shadow-sm transition-colors focus:outline-none focus-visible:ring-2"
      >
        <Plus className="h-3.5 w-3.5" aria-hidden />
        New Post Type
      </button>
    )
  }

  // Pages list — "+ New page" routes to the page creation flow. Handled
  // explicitly (not via the collection loop) so the label/route stay
  // exact even though `pages` is a reserved route.
  if (currentPath === '/pages') {
    return (
      <button
        type="button"
        onClick={() => onNavigate('/pages/new')}
        className="bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-ring inline-flex items-center gap-1.5 rounded-lg px-3.5 py-1.5 text-sm font-medium shadow-sm transition-colors focus:outline-none focus-visible:ring-2"
      >
        <Plus className="h-3.5 w-3.5" aria-hidden />
        New page
      </button>
    )
  }

  // List views — surface "+ New X" so authors can keep creating without
  // hunting for a per-list button. Skip on editor views; those have their
  // own toolbar.
  for (const c of collections) {
    if (currentPath === `/${c.slug}`) {
      return (
        <button
          type="button"
          onClick={() => onNavigate(`/${c.slug}/new`)}
          className="bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-ring inline-flex items-center gap-1.5 rounded-lg px-3.5 py-1.5 text-sm font-medium shadow-sm transition-colors focus:outline-none focus-visible:ring-2"
        >
          <Plus className="h-3.5 w-3.5" aria-hidden />
          New {c.labels?.singular ?? c.slug}
        </button>
      )
    }
  }

  return null
}

interface CollectionMeta {
  slug: string
  type?: string
  labels?: { singular?: string; plural?: string }
  admin?: { hidden?: boolean }
}

/**
 * Where "+ New Post" should land, given the configured post-type
 * collections:
 *   - exactly one  → straight to that type's editor (`/<slug>/new`)
 *   - more than one → the type picker (`/posts/new`)
 *   - none          → the Post Type setup instructions
 */
function resolveNewPostPath(postCollections: CollectionMeta[]): string {
  if (postCollections.length === 1) return `/${postCollections[0]!.slug}/new`
  if (postCollections.length > 1) return '/posts/new'
  return '/posts/types/new'
}

function collectionList(config: any): CollectionMeta[] {
  if (!config?.collections) return []
  const raw = config.collections
  const list: any[] = Array.isArray(raw) ? raw : Object.values(raw)
  return list.filter((c) => !c?.admin?.hidden)
}
