'use client'

import { useMemo, useState } from 'react'
import { AlertTriangle, Copy, FilePlus, Layers, Pencil, RefreshCw, Trash2 } from 'lucide-react'
import { toast } from 'sonner'
import { cmsApi } from '../../lib/api.js'
import { useApiData } from '../../lib/useApiData.js'
import { ConfirmDialog } from '../../components/ui/ConfirmDialog.js'
import { EmptyState } from '../../components/ui/EmptyState.js'
import { FilterPill } from '../../components/ui/FilterPill.js'
import { Input } from '../../components/ui/Input.js'
import { Modal } from '../../components/ui/Modal.js'
import { Button } from '../../components/ui/Button.js'
import { RowActions, RowActionButton } from '../../components/ui/RowActions.js'
import { SearchInput } from '../../components/ui/SearchInput.js'
import { Select } from '../../components/ui/Select.js'
import { Skeleton } from '../../components/ui/Skeleton.js'

interface PageTemplate {
  id: string
  name?: string
  description?: string | null
  category?: string
  builtIn?: boolean
  updatedAt?: string
  thumbnail?: string | null
  tree?: { children?: unknown[] } | null
}

type CategoryId = 'content' | 'landing' | 'utility'

const CATEGORIES: Record<CategoryId, { label: string; dot: string; text: string }> = {
  content: { label: 'Content', dot: 'bg-[var(--acc)]', text: 'text-[var(--acc)]' },
  landing: { label: 'Landing', dot: 'bg-[var(--suc)]', text: 'text-[var(--suc)]' },
  utility: { label: 'Utility', dot: 'bg-[var(--warn)]', text: 'text-[var(--warn)]' },
}

function categoryOf(template: PageTemplate): CategoryId {
  const cat = template.category
  return cat === 'landing' || cat === 'utility' ? cat : 'content'
}

function sectionCountOf(template: PageTemplate): number {
  return Array.isArray(template.tree?.children) ? template.tree.children.length : 0
}

export interface PageTemplatesProps {
  onNavigate?: (path: string) => void
}

export function PageTemplates({ onNavigate }: PageTemplatesProps) {
  const { data, loading, error, refetch } = useApiData<PageTemplate[]>('/page-templates')
  const templates = useMemo(() => data ?? [], [data])

  const [search, setSearch] = useState('')
  const [category, setCategory] = useState<CategoryId | 'all'>('all')
  const [editTarget, setEditTarget] = useState<PageTemplate | null>(null)
  const [deleteTarget, setDeleteTarget] = useState<PageTemplate | null>(null)

  const filtered = useMemo(() => {
    const q = search.trim().toLowerCase()
    return templates.filter((t) => {
      const matchesQuery =
        !q ||
        (t.name ?? '').toLowerCase().includes(q) ||
        (t.description ?? '').toLowerCase().includes(q)
      const matchesCategory = category === 'all' || categoryOf(t) === category
      return matchesQuery && matchesCategory
    })
  }, [templates, search, category])

  async function confirmDelete() {
    if (!deleteTarget) return
    const res = await cmsApi(`/page-templates/${deleteTarget.id}`, { method: 'DELETE' })
    if (res.error) {
      toast.error(res.error)
    } else {
      toast.success('Template deleted')
      refetch()
    }
  }

  async function duplicateTemplate(template: PageTemplate) {
    // The list payload carries the full tree, so no extra fetch is needed.
    // Duplicating a built-in is the supported way to customize one (built-ins
    // themselves are locked against edits).
    if (!template.tree) {
      toast.error('Template has no layout to duplicate')
      return
    }
    const res = await cmsApi('/page-templates', {
      method: 'POST',
      body: JSON.stringify({
        name: `${template.name ?? 'Untitled template'} (copy)`,
        description: template.description ?? null,
        category: categoryOf(template),
        tree: template.tree,
        thumbnail: template.thumbnail ?? null,
      }),
    })
    if (res.error) {
      toast.error(res.error)
    } else {
      toast.success('Template duplicated')
      refetch()
    }
  }

  return (
    <div className="p-4 pr-8">
      {error && (
        <div className="mb-4 flex items-center gap-3 rounded-[var(--r)] border border-[var(--bdr)] bg-[var(--card)] p-3">
          <AlertTriangle className="h-5 w-5 shrink-0 text-[var(--muted)]" aria-hidden />
          <span className="flex-1 text-sm text-[var(--txt)]">{error}</span>
          <button
            type="button"
            onClick={refetch}
            className="rounded-md border border-[var(--bdr)] px-3 py-1 text-sm text-[var(--txt)] hover:bg-[var(--acc-l)]"
          >
            Retry
          </button>
        </div>
      )}

      <div className="mb-4 flex items-center justify-between gap-4">
        <div>
          <h1 className="text-foreground mb-1">Page Templates</h1>
          <p className="text-sm text-[var(--sub)]">
            {templates.length} saved template{templates.length === 1 ? '' : 's'}
          </p>
        </div>
        <Button
          type="button"
          variant="outline"
          size="md"
          onClick={refetch}
          leftIcon={<RefreshCw size={16} aria-hidden />}
        >
          Refresh
        </Button>
      </div>

      {!loading && templates.length > 0 && (
        <div className="mb-4 flex flex-wrap items-center gap-2">
          <div className="max-w-xs min-w-52 flex-1">
            <SearchInput value={search} onChange={setSearch} placeholder="Search templates…" />
          </div>
          <div className="flex gap-1.5" role="group" aria-label="Filter templates by category">
            <FilterPill active={category === 'all'} onClick={() => setCategory('all')}>
              All
            </FilterPill>
            {(Object.keys(CATEGORIES) as CategoryId[]).map((cat) => (
              <FilterPill key={cat} active={category === cat} onClick={() => setCategory(cat)}>
                {CATEGORIES[cat].label}
              </FilterPill>
            ))}
          </div>
          <span className="ml-auto text-[12.5px] whitespace-nowrap text-[var(--muted)]">
            {filtered.length} of {templates.length}
          </span>
        </div>
      )}

      {loading ? (
        <div
          className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3"
          role="status"
          aria-live="polite"
          aria-label="Loading page templates"
        >
          {Array.from({ length: 6 }, (_, i) => (
            <Skeleton key={i} variant="card" />
          ))}
        </div>
      ) : templates.length === 0 ? (
        <EmptyState
          icon={<Layers size={24} aria-hidden />}
          title="No page templates yet"
          description="Built-in templates are seeded by the CMS when the templates API is available."
          actionLabel="View Saved Sections"
          onAction={() => onNavigate?.('/saved-sections')}
        />
      ) : filtered.length === 0 ? (
        <p className="py-12 text-center text-sm text-[var(--muted)]">
          No templates match your search.
        </p>
      ) : (
        <ul
          className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3"
          aria-label="Page templates"
        >
          {filtered.map((template) => (
            <TemplateCard
              key={template.id}
              template={template}
              onUse={() => onNavigate?.(`/page-builder/new?template=${template.id}`)}
              onDuplicate={() => void duplicateTemplate(template)}
              onEdit={() => setEditTarget(template)}
              onDelete={() => setDeleteTarget(template)}
            />
          ))}
        </ul>
      )}

      <TemplateEditModal
        template={editTarget}
        onClose={() => setEditTarget(null)}
        onSaved={() => {
          setEditTarget(null)
          refetch()
        }}
      />

      <ConfirmDialog
        open={deleteTarget !== null}
        onClose={() => setDeleteTarget(null)}
        onConfirm={() => void confirmDelete()}
        title="Delete template?"
        description={`"${deleteTarget?.name ?? 'This template'}" will be permanently removed. Pages already created from it are not affected.`}
        confirmLabel="Delete"
        destructive
      />
    </div>
  )
}

function TemplateCard({
  template,
  onUse,
  onDuplicate,
  onEdit,
  onDelete,
}: {
  template: PageTemplate
  onUse: () => void
  onDuplicate: () => void
  onEdit: () => void
  onDelete: () => void
}) {
  const cat = CATEGORIES[categoryOf(template)]
  const sections = sectionCountOf(template)
  const name = template.name ?? 'Untitled template'
  const updated = template.updatedAt ? new Date(template.updatedAt).toLocaleDateString() : null

  return (
    <li className="group relative flex flex-col overflow-hidden rounded-[var(--r)] border border-[var(--bdr)] bg-[var(--card)] shadow-[var(--shd)] transition-[border-color,box-shadow,transform] duration-[var(--motion-fast)] focus-within:border-[var(--acc-m)] focus-within:shadow-[var(--shd2)] hover:-translate-y-0.5 hover:border-[var(--acc-m)] hover:shadow-[var(--shd2)] motion-reduce:hover:translate-y-0">
      <TemplatePreview template={template} sections={sections} />

      <div className="flex flex-1 flex-col p-4 pb-0">
        <div className="flex items-start justify-between gap-3">
          <h2 className="text-[15px] leading-snug font-medium text-[var(--txt)]">{name}</h2>
          {template.builtIn && (
            <span className="shrink-0 rounded-full border border-[var(--bdr)] bg-[var(--bg)] px-2 py-0.5 text-[10.5px] font-medium whitespace-nowrap text-[var(--sub)]">
              Built-in
            </span>
          )}
        </div>
        <p className="mt-2 min-h-10 text-[12.5px] leading-relaxed text-[var(--sub)]">
          {template.description ?? 'No description provided.'}
        </p>

        <div className="relative mt-3 flex h-[46px] items-center justify-between border-t border-[var(--bdr)] py-2.5">
          <span
            className={`inline-flex items-center gap-1.5 text-[11.5px] font-medium ${cat.text}`}
          >
            <span aria-hidden className={`h-[7px] w-[7px] shrink-0 rounded-full ${cat.dot}`} />
            {cat.label}
          </span>
          <span className="text-[11.5px] text-[var(--muted)] transition-opacity duration-[var(--motion-fast)] group-focus-within:opacity-0 group-hover:opacity-0">
            {sections} section{sections === 1 ? '' : 's'}
            {updated ? ` · ${updated}` : ''}
          </span>
          <RowActions className="absolute top-1/2 right-0 -translate-y-1/2">
            <RowActionButton aria-label={`Create page from ${name}`} onClick={onUse}>
              <FilePlus size={14} aria-hidden />
            </RowActionButton>
            <RowActionButton aria-label={`Duplicate ${name}`} onClick={onDuplicate}>
              <Copy size={14} aria-hidden />
            </RowActionButton>
            {!template.builtIn && (
              <>
                <RowActionButton aria-label={`Edit ${name}`} onClick={onEdit}>
                  <Pencil size={14} aria-hidden />
                </RowActionButton>
                <RowActionButton aria-label={`Delete ${name}`} danger onClick={onDelete}>
                  <Trash2 size={14} aria-hidden />
                </RowActionButton>
              </>
            )}
          </RowActions>
        </div>
      </div>
    </li>
  )
}

/**
 * Card preview area. Uses the stored thumbnail when one exists; otherwise
 * renders an honest wireframe placeholder built from the template's section
 * count (a hero band plus one bar per section) — no fake screenshots.
 */
function TemplatePreview({ template, sections }: { template: PageTemplate; sections: number }) {
  if (template.thumbnail) {
    return (
      <div className="h-28 shrink-0 overflow-hidden border-b border-[var(--bdr)] bg-[var(--bg)]">
        <img
          src={template.thumbnail}
          alt={`Preview of ${template.name ?? 'template'}`}
          className="h-full w-full object-cover"
        />
      </div>
    )
  }

  const bars = Math.max(0, Math.min(sections - 1, 3))
  return (
    <div
      aria-hidden
      className="flex h-28 shrink-0 flex-col gap-1.5 border-b border-[var(--bdr)] bg-[var(--bg)] p-3"
    >
      <div className="h-9 rounded-[5px] bg-[var(--acc-l)]" />
      {Array.from({ length: bars }, (_, i) => (
        <div
          key={i}
          className="h-3.5 rounded-[4px] bg-[var(--bdr)]"
          style={{ width: `${88 - i * 14}%` }}
        />
      ))}
    </div>
  )
}

function TemplateEditModal({
  template,
  onClose,
  onSaved,
}: {
  template: PageTemplate | null
  onClose: () => void
  onSaved: () => void
}) {
  // Keyed remount seeds the form state from the selected template each time
  // the modal opens, without effect-based state syncing.
  if (!template) return null
  return (
    <TemplateEditForm key={template.id} template={template} onClose={onClose} onSaved={onSaved} />
  )
}

function TemplateEditForm({
  template,
  onClose,
  onSaved,
}: {
  template: PageTemplate
  onClose: () => void
  onSaved: () => void
}) {
  const [name, setName] = useState(template.name ?? '')
  const [description, setDescription] = useState(template.description ?? '')
  const [category, setCategory] = useState<CategoryId>(categoryOf(template))
  const [saving, setSaving] = useState(false)

  async function handleSave() {
    if (!name.trim()) {
      toast.error('Template name is required')
      return
    }
    setSaving(true)
    const res = await cmsApi(`/page-templates/${template.id}`, {
      method: 'PUT',
      body: JSON.stringify({
        name: name.trim(),
        description: description.trim() || null,
        category,
      }),
    })
    setSaving(false)
    if (res.error) {
      toast.error(res.error)
    } else {
      toast.success('Template updated')
      onSaved()
    }
  }

  return (
    <Modal
      open
      onClose={onClose}
      title="Edit template"
      actions={
        <>
          <Button variant="ghost" onClick={onClose} disabled={saving}>
            Cancel
          </Button>
          <Button variant="primary" onClick={() => void handleSave()} loading={saving}>
            Save changes
          </Button>
        </>
      }
    >
      <div className="flex flex-col gap-4">
        <label className="flex flex-col gap-1.5">
          <span className="text-sm font-medium text-[var(--txt)]">Name</span>
          <Input
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="Template name"
          />
        </label>
        <label className="flex flex-col gap-1.5">
          <span className="text-sm font-medium text-[var(--txt)]">Description</span>
          <textarea
            value={description}
            onChange={(e) => setDescription(e.target.value)}
            rows={3}
            placeholder="What this template is for…"
            className="w-full resize-y rounded-[var(--r-control)] border border-[var(--bdr)] bg-[var(--input-background)] px-3 py-2 text-sm text-[var(--txt)] placeholder:text-[var(--muted)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
          />
        </label>
        <label className="flex flex-col gap-1.5">
          <span className="text-sm font-medium text-[var(--txt)]">Category</span>
          <Select value={category} onChange={(e) => setCategory(e.target.value as CategoryId)}>
            {(Object.keys(CATEGORIES) as CategoryId[]).map((cat) => (
              <option key={cat} value={cat}>
                {CATEGORIES[cat].label}
              </option>
            ))}
          </Select>
        </label>
      </div>
    </Modal>
  )
}
