import { useEffect, useMemo, useRef, useState } from 'react'
import { Link, getRouteApi } from '@tanstack/react-router'
import { Brand } from '@/components/layout/Nav'
import { ThemeButton } from '@/components/layout/ThemeButton'
import { Alert } from '@/components/ui/Alert'
import { IconButton } from '@/components/ui/Button'
import { Tag } from '@/components/ui/Tag'
import { Canvas, type CanvasHandle } from '@/editor/Canvas'
import { PHONE_BREAKPOINT } from '@/editor/shared'
import { useEditorStore } from '@/editor/store'
import type { EditorGarden } from '@/editor/types'
import { cn } from '@/lib/cn'
import { monogramMap } from '@/lib/monogram'
import { toEditorObject } from '@/lib/objects'
import { toEditorPlanting } from '@/lib/plantings'
import { usePublicGarden } from '@/lib/publicGarden'
import { usePageTitle } from '@/lib/usePageTitle'

const routeApi = getRouteApi('/g/$token')

/**
 * The public, read-only garden behind a share token — the unauthenticated
 * `/g/$token` route (no auth guard), so a logged-out visitor never hits /login
 * or OIDC. The same canvas, with every mutation entry point off.
 */
export function PublicGardenPage() {
  const { token } = routeApi.useParams()
  const full = usePublicGarden(token)
  usePageTitle(full.data?.garden.name ?? 'Shared garden')
  const canvasRef = useRef<CanvasHandle>(null)
  const rootRef = useRef<HTMLDivElement>(null)
  const [vw, setVw] = useState(() => (typeof window !== 'undefined' ? window.innerWidth : 1024))

  useEffect(() => {
    useEditorStore.getState().reset()
  }, [token])

  useEffect(() => {
    const el = rootRef.current
    if (!el) return
    const ro = new ResizeObserver(([entry]) => setVw(entry.contentRect.width))
    ro.observe(el)
    return () => ro.disconnect()
  }, [])
  const isMobile = vw < PHONE_BREAKPOINT

  const objects = useMemo(() => full.data?.objects.map(toEditorObject) ?? [], [full.data?.objects])
  const plantings = useMemo(() => full.data?.plantings.map(toEditorPlanting) ?? [], [full.data?.plantings])
  const plants = useMemo(() => full.data?.plants ?? [], [full.data?.plants])
  const plantsById = useMemo(() => new Map(plants.map((p) => [p.id, p])), [plants])
  const letters = useMemo(() => monogramMap(plants), [plants])

  if (full.isPending) return <p className="p-7 text-[13px] font-semibold text-ink-mute">Loading the garden…</p>
  if (full.isError) {
    return (
      <div className="flex min-h-dvh flex-col bg-bg">
        <div className="flex items-center gap-3 px-3.5 py-2.5">
          <Link to="/" className="no-underline">
            <Brand />
          </Link>
        </div>
        <div className="p-7">
          <Alert>This shared link isn't available. The owner may have turned it off or changed it.</Alert>
        </div>
      </div>
    )
  }

  const g = full.data.garden
  const garden: EditorGarden = { id: g.id, name: g.name, widthCm: g.widthCm, heightCm: g.heightCm, unitPref: g.unitPref, gridSizeCm: g.gridSizeCm, snapToGrid: g.snapToGrid }

  return (
    <div ref={rootRef} className="flex h-dvh flex-col bg-bg">
      <div className="flex flex-none items-center gap-3 px-3.5 py-2.5">
        <Link to="/" className="no-underline">
          <Brand />
        </Link>
        <span className="min-w-0 truncate font-heading text-[17px]" title={g.name}>
          {g.name}
        </span>
        <Tag tone="accent-2" className="flex-none">
          shared · read-only
        </Tag>
        <ThemeButton className="ml-auto" />
      </div>
      <div className={cn('relative min-h-0 flex-1', !isMobile && 'panel m-3.5 mt-0 overflow-hidden')}>
        <Canvas ref={canvasRef} garden={garden} objects={objects} plantings={plantings} plantsById={plantsById} letters={letters} canEdit={false} isMobile={isMobile} />
        <IconButton label="Fit the garden" icon="maximize" iconSize={16} variant="plain" size={40} className="elev-sm absolute bottom-3 right-3 border border-divider bg-surface" onClick={() => canvasRef.current?.zoomFit()} />
      </div>
    </div>
  )
}
