'use client'

import { useEffect, useMemo, useRef, useState } from 'react'
import { Loader2, Sparkles } from 'lucide-react'
import { toast } from 'sonner'
import { normalizeSlug, validateSlug } from '@actuate-media/cms-core/client'
import { Modal } from '../../components/ui/Modal.js'
import { Button } from '../../components/ui/Button.js'
import { ConfirmDialog } from '../../components/ui/ConfirmDialog.js'
import { MediaPickerModal } from '../../components/MediaPickerModal.js'
import { TagInput } from '../../components/TagInput.js'
import { coauthorText } from '../../lib/coauthor-client.js'
import type { EditorPost } from '../../lib/post-editor-service.js'

/**
 * The slice of a collection's field config the modal reads to pick controls:
 * a `select` category renders a dropdown (structured vocabulary), an `array`
 * tags field renders the chip input with autocomplete.
 */
export interface PostFieldConfig {
  type?: string
  options?: Array<{ label: string; value: string }>
  maxRows?: number
}

interface PostFieldsModalProps {
  open: boolean
  post: EditorPost
  canEdit: boolean
  /** Field definitions from the post type's collection config. */
  fields?: Record<string, PostFieldConfig | undefined>
  onClose: () => void
  onSave: (patch: Partial<EditorPost>) => void
}

const LABEL = 'text-foreground mb-1 block text-xs font-medium'
/** Match TipTap body editor borders — `border-input` is transparent in theme.css. */
const INPUT =
  'border-border bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-2.5 py-1.5 text-sm focus-visible:ring-2 focus-visible:outline-none'

const slugify = normalizeSlug

type FormSnapshot = {
  title: string
  slug: string
  excerpt: string
  featuredImage: string
  category: string
  tags: string
}

function snapshotFromPost(post: EditorPost): FormSnapshot {
  return {
    title: post.title,
    slug: post.slug,
    excerpt: post.excerpt,
    featuredImage: post.featuredImage,
    category: post.category,
    tags: [...post.tags].sort().join('\0'),
  }
}

function snapshotFromFields(input: {
  title: string
  slug: string
  excerpt: string
  featuredImage: string
  category: string
  tags: string[]
}): FormSnapshot {
  return {
    ...input,
    tags: [...input.tags].sort().join('\0'),
  }
}

function stripHtml(html: string): string {
  return html
    .replace(/<[^>]*>/g, ' ')
    .replace(/\s+/g, ' ')
    .trim()
}

function buildContentContext(title: string, body: string, excerpt: string): string {
  const plain = stripHtml(body)
  const parts = [title.trim(), excerpt.trim(), plain].filter(Boolean)
  return parts.join('\n\n')
}

function AiFieldButton({
  label,
  busy,
  disabled,
  onClick,
}: {
  label: string
  busy: boolean
  disabled?: boolean
  onClick: () => void
}) {
  return (
    <button
      type="button"
      aria-label={label}
      title={label}
      disabled={disabled || busy}
      onClick={onClick}
      className="inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] font-medium text-[var(--acc)] transition-colors duration-[var(--motion-fast)] hover:bg-[var(--acc-l)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none disabled:opacity-60"
    >
      {busy ? (
        <Loader2 className="h-3 w-3 animate-spin" aria-hidden />
      ) : (
        <Sparkles className="h-3 w-3" aria-hidden />
      )}
      {busy ? 'Generating…' : 'AI'}
    </button>
  )
}

/** Edits post metadata: title, slug, excerpt, featured image, category, and tags. SEO lives in the SEO tab. */
export function PostFieldsModal({
  open,
  post,
  canEdit,
  fields,
  onClose,
  onSave,
}: PostFieldsModalProps) {
  const [title, setTitle] = useState(post.title)
  const [slug, setSlug] = useState(post.slug)
  const [excerpt, setExcerpt] = useState(post.excerpt)
  const [featuredImage, setFeaturedImage] = useState(post.featuredImage)
  const [category, setCategory] = useState(post.category)
  const [tags, setTags] = useState<string[]>(post.tags)
  const [slugTouched, setSlugTouched] = useState(Boolean(post.slug))
  const [mediaOpen, setMediaOpen] = useState(false)
  const [aiBusy, setAiBusy] = useState(false)
  const [confirmDiscard, setConfirmDiscard] = useState(false)
  const baselineRef = useRef<FormSnapshot | null>(null)
  // Land the user in the Title field (name-it-first flow for new posts).
  const titleRef = useRef<HTMLInputElement | null>(null)

  const categoryField = fields?.category
  const categoryOptions =
    categoryField?.type === 'select' && Array.isArray(categoryField.options)
      ? categoryField.options
      : null
  const tagsField = fields?.tags
  const hasTags = tagsField?.type === 'array'

  useEffect(() => {
    if (!open) {
      baselineRef.current = null
      setConfirmDiscard(false)
      return
    }
    setTitle(post.title)
    setSlug(post.slug)
    setExcerpt(post.excerpt)
    setFeaturedImage(post.featuredImage)
    setCategory(post.category)
    setTags(post.tags)
    setSlugTouched(Boolean(post.slug))
    setAiBusy(false)
    baselineRef.current = snapshotFromPost(post)
  }, [open, post])

  const isDirty = useMemo(() => {
    if (!open || !baselineRef.current) return false
    const current = snapshotFromFields({
      title,
      slug,
      excerpt,
      featuredImage,
      category,
      tags,
    })
    return JSON.stringify(current) !== JSON.stringify(baselineRef.current)
  }, [open, title, slug, excerpt, featuredImage, category, tags])

  function requestDismiss() {
    if (isDirty) {
      setConfirmDiscard(true)
      return
    }
    onClose()
  }

  function handleTitle(next: string) {
    setTitle(next)
    if (!slugTouched) setSlug(slugify(next))
  }

  const slugError = validateSlug(slug)

  async function handleAiGenerateExcerpt() {
    const context = buildContentContext(title, post.body, excerpt)
    if (!context.trim()) {
      toast.error(
        'Add a title or write body content in the Article Body section before generating with AI.',
      )
      return
    }

    setAiBusy(true)
    try {
      const outcome = await coauthorText('compress', context, {
        instructions:
          'Write a 1–2 sentence excerpt for blog listings and cards. Return only the excerpt text.',
        targetLength: 45,
      })
      if (!outcome.ok) {
        toast.error(outcome.error)
        return
      }
      setExcerpt(outcome.result.text.trim())
      toast.success('Excerpt generated — review before saving.')
    } catch {
      toast.error('AI request failed.')
    } finally {
      setAiBusy(false)
    }
  }

  function handleSave() {
    if (slugError) return
    onSave({ title, slug, excerpt, featuredImage, category, tags })
    onClose()
  }

  return (
    <>
      <Modal
        open={open}
        onClose={onClose}
        onDismiss={requestDismiss}
        title="Post details"
        size="lg"
        initialFocusRef={titleRef}
        actions={
          <>
            <Button variant="ghost" onClick={requestDismiss}>
              Cancel
            </Button>
            <Button
              variant="primary"
              onClick={handleSave}
              disabled={!canEdit || Boolean(slugError)}
            >
              Done
            </Button>
          </>
        }
      >
        <div className="space-y-3">
          <div>
            <label className={LABEL} htmlFor="pf-title">
              Title <span className="text-destructive">*</span>
            </label>
            <input
              id="pf-title"
              ref={titleRef}
              className={INPUT}
              value={title}
              disabled={!canEdit}
              placeholder="e.g. Announcing our new product"
              onChange={(e) => handleTitle(e.target.value)}
            />
          </div>

          <div className="grid grid-cols-2 gap-3">
            <div>
              <label className={LABEL} htmlFor="pf-slug">
                Slug <span className="text-destructive">*</span>
              </label>
              <input
                id="pf-slug"
                className={INPUT}
                value={slug}
                disabled={!canEdit}
                placeholder={slugTouched ? undefined : 'Generated from title…'}
                aria-invalid={Boolean(slugError)}
                aria-describedby={slugError ? 'pf-slug-error' : undefined}
                onChange={(e) => {
                  setSlugTouched(true)
                  setSlug(slugify(e.target.value))
                }}
              />
              {slugError && (
                <p id="pf-slug-error" className="text-destructive mt-1 text-xs">
                  {slugError}
                </p>
              )}
            </div>

            <div>
              <label className={LABEL} htmlFor="pf-category">
                Category
              </label>
              {categoryOptions ? (
                <select
                  id="pf-category"
                  className={INPUT}
                  value={category}
                  disabled={!canEdit}
                  onChange={(e) => setCategory(e.target.value)}
                >
                  <option value="">No category</option>
                  {categoryOptions.map((o) => (
                    <option key={o.value} value={o.value}>
                      {o.label}
                    </option>
                  ))}
                  {category && !categoryOptions.some((o) => o.value === category) && (
                    <option value={category}>{category}</option>
                  )}
                </select>
              ) : (
                <input
                  id="pf-category"
                  className={INPUT}
                  value={category}
                  disabled={!canEdit}
                  placeholder="e.g. Product"
                  onChange={(e) => setCategory(e.target.value)}
                />
              )}
            </div>
          </div>

          {hasTags && (
            <div>
              <label className={LABEL} htmlFor="pf-tags">
                Tags
              </label>
              <TagInput
                id="pf-tags"
                value={tags}
                onChange={setTags}
                collection={post.postType}
                field="tags"
                disabled={!canEdit}
                maxTags={tagsField?.maxRows}
              />
            </div>
          )}

          <div>
            <div className="mb-1 flex items-center justify-between gap-2">
              <label className={`${LABEL} mb-0`} htmlFor="pf-excerpt">
                Excerpt
              </label>
              <AiFieldButton
                label="Generate excerpt from content"
                busy={aiBusy}
                disabled={!canEdit}
                onClick={() => void handleAiGenerateExcerpt()}
              />
            </div>
            <textarea
              id="pf-excerpt"
              className={`${INPUT} min-h-[72px] resize-y`}
              value={excerpt}
              disabled={!canEdit}
              placeholder="A short summary shown in listings and the header."
              onChange={(e) => setExcerpt(e.target.value)}
            />
          </div>

          <div>
            <label className={LABEL} htmlFor="pf-image">
              Featured image
            </label>
            <div className="flex gap-2">
              <input
                id="pf-image"
                className={`${INPUT} min-w-0 flex-1`}
                value={featuredImage}
                disabled={!canEdit}
                placeholder="https://… or pick from the media library"
                onChange={(e) => setFeaturedImage(e.target.value)}
              />
              <button
                type="button"
                disabled={!canEdit}
                onClick={() => setMediaOpen(true)}
                className="bg-accent text-foreground border-border hover:bg-accent/80 shrink-0 rounded-md border px-3 py-1.5 text-xs font-medium disabled:opacity-50"
              >
                Browse
              </button>
            </div>
            {featuredImage && (
              <div className="border-border bg-muted mt-2 overflow-hidden rounded-md border">
                <img src={featuredImage} alt="" className="h-28 w-full object-cover" />
              </div>
            )}
          </div>
        </div>
      </Modal>

      <MediaPickerModal
        open={mediaOpen}
        onClose={() => setMediaOpen(false)}
        onSelect={(url) => {
          setFeaturedImage(url)
          setMediaOpen(false)
        }}
        accept="image/*"
      />

      <ConfirmDialog
        open={confirmDiscard}
        onClose={() => setConfirmDiscard(false)}
        onConfirm={onClose}
        title="Discard unsaved changes?"
        description="You have unsaved post details. Closing now will discard them."
        confirmLabel="Discard"
        cancelLabel="Keep editing"
        destructive
      />
    </>
  )
}
