'use client'

import { useCallback, useEffect, useRef, useState } from 'react'
import { toast } from 'sonner'
import {
  buildPublicPreviewUrl,
  createPreviewToken,
  resolveSiteUrl,
} from '../../lib/preview-link.js'
import type { SaveState } from './EditorTopBar.js'

interface UseSitePreviewOptions {
  collection: string
  documentId?: string | null
  slug?: string | null
  /** Collection URL prefix (e.g. `blog`). Empty/null for top-level pages. */
  urlPrefix?: string | null
  /** Raw `config.seo.siteUrl`; falls back to the current origin. */
  siteUrl?: string | null
  dirty: boolean
  saveState: SaveState
  /** Persist the draft; resolves `false` when the save failed. */
  saveDraft: () => Promise<boolean>
}

export interface SitePreviewState {
  /** Whether the inline iframe preview replaces the editor canvas. */
  active: boolean
  /** Public draft URL (`/<slug>?preview=<jwt>`); null while the token mints. */
  url: string | null
  /** Bumped after each completed save so the iframe reloads the fresh draft. */
  reloadKey: number
  toggle: () => void
}

/**
 * Inline branded preview — drives an in-editor iframe that renders the draft
 * through the consumer's REAL public route (same `?preview=<token>` contract
 * as "View on site"), so editors see actual site CSS without leaving the
 * admin. Saves first when dirty, and reloads the frame after each save so
 * what you see always matches the persisted draft.
 */
export function useSitePreview({
  collection,
  documentId,
  slug,
  urlPrefix,
  siteUrl,
  dirty,
  saveState,
  saveDraft,
}: UseSitePreviewOptions): SitePreviewState {
  const [active, setActive] = useState(false)
  const [url, setUrl] = useState<string | null>(null)
  const [reloadKey, setReloadKey] = useState(0)
  const tokenRef = useRef<string | null>(null)
  const prevSaveState = useRef(saveState)

  // After a save completes while the preview is open, rebuild the URL (the
  // slug may have changed in settings — the token is bound to the document
  // id, not the path) and reload the frame.
  useEffect(() => {
    if (active && prevSaveState.current === 'saving' && saveState === 'saved') {
      if (tokenRef.current && slug) {
        setUrl(
          buildPublicPreviewUrl({
            siteUrl: resolveSiteUrl(siteUrl),
            urlPrefix: urlPrefix ?? '',
            slug,
            token: tokenRef.current,
          }),
        )
      }
      setReloadKey((k) => k + 1)
    }
    prevSaveState.current = saveState
  }, [active, saveState, slug, siteUrl, urlPrefix])

  const toggle = useCallback(() => {
    if (active) {
      setActive(false)
      return
    }
    if (!documentId || !slug) {
      toast.error('Save the page before opening the site preview')
      return
    }
    setActive(true)
    setUrl(null)
    void (async () => {
      try {
        if (dirty) {
          const ok = await saveDraft()
          if (!ok) {
            setActive(false)
            return
          }
        }
        const { token } = await createPreviewToken(collection, documentId)
        tokenRef.current = token
        setUrl(
          buildPublicPreviewUrl({
            siteUrl: resolveSiteUrl(siteUrl),
            urlPrefix: urlPrefix ?? '',
            slug,
            token,
          }),
        )
      } catch (err) {
        toast.error(err instanceof Error ? err.message : 'Failed to open site preview')
        setActive(false)
      }
    })()
  }, [active, collection, documentId, slug, urlPrefix, siteUrl, dirty, saveDraft])

  return { active, url, reloadKey, toggle }
}
