'use client'

import { useMemo, useState } from 'react'
import { ArrowLeft, Check, Copy, Sparkles } from 'lucide-react'
import { toast } from 'sonner'
import { resolvePostTypeIcon, type PostTypeIconName } from '../../components/posts/icons.js'
import { paletteFor } from '../../components/posts/badges.js'
import { POST_TYPE_PRESETS, type PresetColor, type QuickPreset } from './post-type-presets.js'

/**
 * /posts/types/new — Quick Post Type gallery + snippet generator.
 *
 * Two ways to start:
 *   1. Pick a Quick Post Type preset (Blog) — pre-fills the form and
 *      tailored extra fields.
 *   2. Fill the form from scratch.
 *
 * Either way the page emits a paste-ready `actuate.config.ts` snippet.
 *
 * Why this isn't a runtime form-driven CRUD:
 *   Collections in ActuateCMS are file-defined in `actuate.config.ts`.
 *   Writing to that file at runtime would require either a parallel
 *   DB-only post-type model that duplicates the Collection concept, or
 *   mutating a source file on disk — which breaks Vercel's read-only
 *   serverless filesystem and any immutable deploy model. So we
 *   generate the snippet and the developer commits + redeploys. Same
 *   model Sanity, Keystone, and Payload use for code-defined schemas.
 */

const SLUG_RE = /^[a-z][a-z0-9-]*$/

const ICON_OPTIONS: { value: PostTypeIconName; label: string }[] = [
  { value: 'file-text', label: 'Document' },
  { value: 'briefcase', label: 'Briefcase' },
  { value: 'newspaper', label: 'Newspaper' },
  { value: 'book', label: 'Book' },
  { value: 'folder', label: 'Folder' },
  { value: 'layers', label: 'Layers' },
  { value: 'image', label: 'Image' },
  { value: 'calendar', label: 'Calendar' },
  { value: 'users', label: 'People' },
  { value: 'help', label: 'Help' },
]

interface DraftType {
  slug: string
  singular: string
  plural: string
  color: PresetColor
  icon: PostTypeIconName
  description: string
  /** Extra field lines beyond the shared base, seeded by a preset. */
  extraFields: string[]
}

const BLANK_DRAFT: DraftType = {
  slug: '',
  singular: '',
  plural: '',
  color: 'purple',
  icon: 'file-text',
  description: '',
  extraFields: [],
}

export function NewPostTypeInstructions({ onNavigate }: { onNavigate: (p: string) => void }) {
  const [draft, setDraft] = useState<DraftType>(BLANK_DRAFT)
  const [activePreset, setActivePreset] = useState<string | null>(null)
  const [copied, setCopied] = useState(false)
  const snippet = useMemo(() => renderSnippet(draft), [draft])

  const slugValid = SLUG_RE.test(draft.slug)

  const applyPreset = (preset: QuickPreset) => {
    setActivePreset(preset.key)
    setDraft({
      slug: preset.slug,
      singular: preset.singular,
      plural: preset.plural,
      color: preset.color,
      icon: preset.icon,
      description: preset.description,
      extraFields: preset.extraFields,
    })
  }

  // Manual edits clear the active-preset highlight but keep any
  // preset-seeded extra fields (the user may still want them).
  const patchDraft = (patch: Partial<DraftType>) => {
    setActivePreset(null)
    setDraft((d) => ({ ...d, ...patch }))
  }

  const copy = async () => {
    try {
      await navigator.clipboard.writeText(snippet)
      setCopied(true)
      toast.success('Snippet copied to clipboard')
      setTimeout(() => setCopied(false), 1800)
    } catch {
      toast.error('Copy failed — select the snippet manually')
    }
  }

  return (
    <div className="mx-auto flex h-full max-w-3xl flex-col gap-6 p-4 sm:p-6">
      <button
        type="button"
        onClick={() => onNavigate('/posts/types')}
        className="text-muted-foreground hover:text-foreground inline-flex w-fit items-center gap-1.5 text-sm transition-colors"
      >
        <ArrowLeft className="h-3.5 w-3.5" aria-hidden />
        Back to Post Types
      </button>

      <div className="flex flex-col gap-1">
        <h1 className="text-foreground text-xl font-medium tracking-tight sm:text-2xl">
          Add a Post Type
        </h1>
        <p className="text-muted-foreground text-sm">
          Post Types are content models defined in{' '}
          <code className="font-mono">actuate.config.ts</code>. Start from a quick template or fill
          in the details below, then paste the generated snippet into your config and redeploy.
        </p>
      </div>

      {/* Quick Post Type gallery */}
      <section aria-labelledby="quick-types-heading" className="flex flex-col gap-3">
        <div className="flex items-center gap-1.5">
          <Sparkles className="text-muted-foreground h-3.5 w-3.5" aria-hidden />
          <h2 id="quick-types-heading" className="text-foreground text-sm font-medium">
            Quick start
          </h2>
        </div>
        <div className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-5">
          {POST_TYPE_PRESETS.map((preset) => {
            const palette = paletteFor(preset.color)
            const Icon = resolvePostTypeIcon(preset.icon)
            const selected = activePreset === preset.key
            return (
              <button
                key={preset.key}
                type="button"
                onClick={() => applyPreset(preset)}
                aria-pressed={selected}
                className={`focus-visible:ring-ring flex flex-col items-start gap-2 rounded-xl border p-3 text-left shadow-sm transition-colors focus:outline-none focus-visible:ring-2 ${
                  selected
                    ? 'border-primary bg-primary/5'
                    : 'border-border bg-card hover:border-primary/40 hover:bg-accent'
                }`}
              >
                <span
                  className={`inline-flex h-8 w-8 items-center justify-center rounded-lg ${palette.bg} ${palette.text}`}
                >
                  <Icon className="h-4 w-4" aria-hidden />
                </span>
                <span className="text-foreground text-sm leading-tight font-medium">
                  {preset.label}
                </span>
              </button>
            )
          })}
        </div>
      </section>

      {/* Detail form */}
      <div className="bg-card border-border grid grid-cols-1 gap-4 rounded-xl border p-5 shadow-sm sm:grid-cols-2">
        <Field
          label="Slug"
          htmlFor="pt-slug"
          error={draft.slug && !slugValid ? 'lowercase letters, numbers, and dashes only' : null}
        >
          <input
            id="pt-slug"
            value={draft.slug}
            onChange={(e) => patchDraft({ slug: e.target.value.trim() })}
            className="border-border bg-background text-foreground focus:border-primary focus:ring-primary/30 w-full rounded-lg border px-3 py-1.5 text-sm focus:ring-2 focus:outline-none"
            placeholder="reviews"
          />
        </Field>
        <Field label="Singular label" htmlFor="pt-singular">
          <input
            id="pt-singular"
            value={draft.singular}
            onChange={(e) => patchDraft({ singular: e.target.value })}
            className="border-border bg-background text-foreground focus:border-primary focus:ring-primary/30 w-full rounded-lg border px-3 py-1.5 text-sm focus:ring-2 focus:outline-none"
            placeholder="Review"
          />
        </Field>
        <Field label="Plural label" htmlFor="pt-plural">
          <input
            id="pt-plural"
            value={draft.plural}
            onChange={(e) => patchDraft({ plural: e.target.value })}
            className="border-border bg-background text-foreground focus:border-primary focus:ring-primary/30 w-full rounded-lg border px-3 py-1.5 text-sm focus:ring-2 focus:outline-none"
            placeholder="Reviews"
          />
        </Field>
        <Field label="Description" htmlFor="pt-desc">
          <input
            id="pt-desc"
            value={draft.description}
            onChange={(e) => patchDraft({ description: e.target.value })}
            className="border-border bg-background text-foreground focus:border-primary focus:ring-primary/30 w-full rounded-lg border px-3 py-1.5 text-sm focus:ring-2 focus:outline-none"
            placeholder="Product reviews and editorial pieces."
          />
        </Field>
        <Field label="Accent color" htmlFor="pt-color">
          <select
            id="pt-color"
            value={draft.color}
            onChange={(e) => patchDraft({ color: e.target.value as PresetColor })}
            className="border-border bg-background text-foreground focus:border-primary focus:ring-primary/30 w-full rounded-lg border px-3 py-1.5 text-sm focus:ring-2 focus:outline-none"
          >
            <option value="purple">Purple</option>
            <option value="green">Green</option>
            <option value="orange">Orange</option>
            <option value="blue">Blue</option>
            <option value="red">Red</option>
            <option value="pink">Pink</option>
          </select>
        </Field>
        <Field label="Icon" htmlFor="pt-icon">
          <select
            id="pt-icon"
            value={draft.icon}
            onChange={(e) => patchDraft({ icon: e.target.value as PostTypeIconName })}
            className="border-border bg-background text-foreground focus:border-primary focus:ring-primary/30 w-full rounded-lg border px-3 py-1.5 text-sm focus:ring-2 focus:outline-none"
          >
            {ICON_OPTIONS.map((o) => (
              <option key={o.value} value={o.value}>
                {o.label}
              </option>
            ))}
          </select>
        </Field>
      </div>

      <div>
        <div className="mb-2 flex items-center justify-between">
          <h2 className="text-foreground text-sm font-medium">
            Add to <code className="font-mono">actuate.config.ts</code>
          </h2>
          <button
            type="button"
            onClick={copy}
            disabled={!slugValid}
            className="border-border bg-background text-foreground hover:bg-accent inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-40"
          >
            {copied ? (
              <Check className="h-3.5 w-3.5" aria-hidden />
            ) : (
              <Copy className="h-3.5 w-3.5" aria-hidden />
            )}
            {copied ? 'Copied' : 'Copy snippet'}
          </button>
        </div>
        <pre className="border-border bg-muted text-foreground overflow-x-auto rounded-lg border p-4 text-xs leading-relaxed">
          <code>{snippet}</code>
        </pre>
        <p className="text-muted-foreground mt-3 text-xs">
          After adding the snippet and redeploying, the new type will appear in the Posts area tabs
          and on this Post Types page automatically.
        </p>
      </div>
    </div>
  )
}

function Field({
  label,
  htmlFor,
  error,
  children,
}: {
  label: string
  htmlFor: string
  error?: string | null
  children: React.ReactNode
}) {
  return (
    <div className="flex flex-col gap-1">
      <label htmlFor={htmlFor} className="text-foreground text-sm font-medium">
        {label}
      </label>
      {children}
      {error ? <span className="text-destructive text-xs">{error}</span> : null}
    </div>
  )
}

export function renderSnippet(draft: DraftType): string {
  const safeSlug = draft.slug || 'new-type'
  const extraFieldsBlock =
    draft.extraFields.length > 0
      ? '\n      // type-specific fields\n' +
        draft.extraFields.map((line) => `      ${line}`).join('\n') +
        '\n'
      : ''

  return `// Add this entry to the \`collections\` map in actuate.config.ts:
collections: {
  // …existing collections,
  '${safeSlug}': {
    slug: '${safeSlug}',
    labels: {
      singular: '${escapeString(draft.singular || 'Entry')}',
      plural: '${escapeString(draft.plural || 'Entries')}',
    },
    type: 'post',
    urlPrefix: '${safeSlug}',
    admin: {
      group: 'Posts',
      icon: '${draft.icon}',
      color: '${draft.color}',
      description: '${escapeString(draft.description)}',
    },
    fields: {
      title: { type: 'text', label: 'Title', required: true },
      slug: { type: 'slug', label: 'Slug', from: 'title' },
      excerpt: { type: 'text', label: 'Excerpt' },
      featuredImage: { type: 'media', label: 'Featured Image' },
      body: { type: 'richText', label: 'Body' },
      status: {
        type: 'select',
        label: 'Status',
        options: [
          { label: 'Draft', value: 'draft' },
          { label: 'Published', value: 'published' },
          { label: 'Scheduled', value: 'scheduled' },
        ],
      },
      publishDate: { type: 'date', label: 'Publish Date', includeTime: true },
      metaTitle: { type: 'text', label: 'SEO Title' },
      metaDescription: { type: 'text', label: 'SEO Description' },
${extraFieldsBlock}    },
  },
},
`
}

function escapeString(input: string): string {
  return input.replace(/\\/g, '\\\\').replace(/'/g, "\\'")
}
