'use client'

import { useId, useState } from 'react'
import * as Dialog from '@radix-ui/react-dialog'
import { Check, Copy, Link2, Loader2, Share2, X } from 'lucide-react'
import { toast } from 'sonner'
import { cmsApi } from '../lib/api.js'
import { adminPortalContainer } from '../lib/portal-container.js'

export interface SharePreviewLinkDialogProps {
  collectionSlug: string
  documentId: string
  /** Document slug, used to build a friendly preview URL. */
  documentSlug?: string | null
  /**
   * Optional site URL (https://...) to prepend. If omitted we just emit the
   * relative path and ask the admin to share it however they want.
   */
  siteUrl?: string
  /** Custom URL prefix for this collection (e.g. /blog). Defaults to slug. */
  urlPrefix?: string
  open: boolean
  onClose: () => void
}

interface TTLChoice {
  label: string
  seconds: number
  hint: string
}

const TTL_CHOICES: TTLChoice[] = [
  { label: '1 hour', seconds: 60 * 60, hint: 'Quick review' },
  { label: '1 day', seconds: 24 * 60 * 60, hint: 'Single workday' },
  { label: '7 days', seconds: 7 * 24 * 60 * 60, hint: 'Client review' },
  { label: '30 days', seconds: 30 * 24 * 60 * 60, hint: 'Long-running staging' },
]

function buildPreviewUrl({
  siteUrl,
  urlPrefix,
  collectionSlug,
  documentSlug,
  token,
}: {
  siteUrl?: string
  urlPrefix?: string
  collectionSlug: string
  documentSlug?: string | null
  token: string
}): string {
  const base = (siteUrl ?? '').replace(/\/+$/, '')
  // Build the same path /resolve would match: <urlPrefix>/<slug>, or
  // /<slug> for top-level page collections. If there's no slug yet we
  // fall back to /admin's preview endpoint as a safety net.
  const slug = documentSlug?.toString().trim() ?? ''
  if (!slug) {
    return `${base}/preview/${collectionSlug}/_?token=${encodeURIComponent(token)}`
  }
  const prefix = (urlPrefix ?? collectionSlug).replace(/^\/+|\/+$/g, '')
  const path = prefix ? `/${prefix}/${slug}` : `/${slug}`
  return `${base}${path}?preview=${encodeURIComponent(token)}`
}

export function SharePreviewLinkDialog({
  collectionSlug,
  documentId,
  documentSlug,
  siteUrl,
  urlPrefix,
  open,
  onClose,
}: SharePreviewLinkDialogProps) {
  const [ttl, setTtl] = useState<number>(TTL_CHOICES[2]!.seconds)
  const [token, setToken] = useState<string>('')
  const [previewUrl, setPreviewUrl] = useState<string>('')
  const [expiresAt, setExpiresAt] = useState<string>('')
  const [generating, setGenerating] = useState(false)
  const [copied, setCopied] = useState(false)
  const previewUrlId = useId()

  async function generate() {
    setGenerating(true)
    const res = await cmsApi<{
      token: string
      expiresAt: string
      slug?: string | null
    }>('/preview/token', {
      method: 'POST',
      body: JSON.stringify({
        collection: collectionSlug,
        documentId,
        ttlSeconds: ttl,
      }),
    })
    setGenerating(false)
    if (res.error || !res.data) {
      toast.error(res.error ?? 'Failed to create preview token')
      return
    }
    const data = res.data
    setToken(data.token)
    setExpiresAt(data.expiresAt ?? '')
    const url = buildPreviewUrl({
      siteUrl,
      urlPrefix,
      collectionSlug,
      documentSlug: data.slug ?? documentSlug,
      token: data.token,
    })
    setPreviewUrl(url)
    setCopied(false)
  }

  async function copyToClipboard() {
    if (!previewUrl) return
    try {
      await navigator.clipboard.writeText(previewUrl)
      setCopied(true)
      toast.success('Preview link copied')
      setTimeout(() => setCopied(false), 2000)
    } catch {
      toast.error("Couldn't copy to clipboard")
    }
  }

  return (
    <Dialog.Root open={open} onOpenChange={(next) => !next && onClose()}>
      <Dialog.Portal container={adminPortalContainer()}>
        <Dialog.Overlay className="fixed inset-0 z-50 bg-black/40" />
        <Dialog.Content className="bg-card text-card-foreground border-border fixed top-1/2 left-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 rounded-lg border shadow-xl focus:outline-none">
          <div className="border-border flex items-center justify-between border-b px-4 py-3">
            <div className="flex items-center gap-2">
              <Share2 className="text-muted-foreground h-5 w-5" aria-hidden />
              <Dialog.Title className="text-foreground text-lg font-medium">
                Share preview link
              </Dialog.Title>
            </div>
            <Dialog.Close asChild>
              <button
                type="button"
                aria-label="Close dialog"
                className="text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-ring rounded-lg p-1.5 transition-colors focus-visible:ring-2 focus-visible:outline-none"
              >
                <X className="h-5 w-5" aria-hidden />
              </button>
            </Dialog.Close>
          </div>

          <div className="space-y-4 px-4 py-4">
            <Dialog.Description className="text-muted-foreground text-sm">
              Generate a signed URL that lets anyone with the link view the current draft of this
              document — even if it's never been published.
            </Dialog.Description>

            <div className="space-y-2">
              <span className="text-foreground text-sm font-medium">Link lifetime</span>
              <div className="grid grid-cols-2 gap-2">
                {TTL_CHOICES.map((choice) => {
                  const selected = ttl === choice.seconds
                  return (
                    <button
                      key={choice.seconds}
                      type="button"
                      aria-pressed={selected}
                      onClick={() => setTtl(choice.seconds)}
                      className={`rounded-md border px-3 py-2 text-left text-sm transition-colors ${
                        selected
                          ? 'border-primary bg-primary/10 text-foreground'
                          : 'border-border hover:border-input hover:bg-accent'
                      }`}
                    >
                      <div className="font-medium">{choice.label}</div>
                      <div className="text-muted-foreground text-xs">{choice.hint}</div>
                    </button>
                  )
                })}
              </div>
              <p className="text-muted-foreground text-xs">
                Preview tokens can't be revoked individually — pick the shortest TTL that fits.
              </p>
            </div>

            {previewUrl ? (
              <div className="border-border bg-muted space-y-2 rounded-lg border p-3">
                <label
                  htmlFor={previewUrlId}
                  className="text-muted-foreground text-xs font-medium tracking-wide uppercase"
                >
                  Preview URL
                </label>
                <div className="flex items-stretch gap-2">
                  <input
                    id={previewUrlId}
                    readOnly
                    value={previewUrl}
                    onFocus={(e) => e.currentTarget.select()}
                    className="border-input bg-background text-foreground flex-1 rounded-md border px-2 py-1.5 font-mono text-xs"
                  />
                  <button
                    type="button"
                    onClick={copyToClipboard}
                    className="bg-primary text-primary-foreground inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium hover:opacity-90"
                  >
                    {copied ? (
                      <Check className="h-3.5 w-3.5" aria-hidden />
                    ) : (
                      <Copy className="h-3.5 w-3.5" aria-hidden />
                    )}
                    {copied ? 'Copied' : 'Copy'}
                  </button>
                </div>
                {expiresAt && (
                  <p className="text-muted-foreground text-xs">
                    Expires {new Date(expiresAt).toLocaleString()}
                  </p>
                )}
              </div>
            ) : null}
          </div>

          <div className="border-border flex items-center justify-end gap-2 border-t px-4 py-3">
            <Dialog.Close asChild>
              <button
                type="button"
                className="text-foreground hover:bg-accent rounded-md px-3 py-1.5 text-sm"
              >
                Close
              </button>
            </Dialog.Close>
            <button
              type="button"
              onClick={generate}
              disabled={generating}
              className="bg-primary text-primary-foreground inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium hover:opacity-90 disabled:opacity-50"
            >
              {generating ? (
                <Loader2 className="h-4 w-4 animate-spin" aria-hidden />
              ) : (
                <Link2 className="h-4 w-4" aria-hidden />
              )}
              {previewUrl ? 'Generate new link' : 'Generate link'}
            </button>
          </div>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  )
}
