/**
 * WEB-0b: Seiten-Editor der öffentlichen Webseite.
 * - Kopf: Titel, SEO-Beschreibung, Status (Entwurf/Veröffentlicht).
 * - Geordneter Block-Editor: Blöcke hinzufügen, bearbeiten, verschieben, löschen.
 *
 * Reihenfolge/Anlegen/Löschen rufen das Backend auf und laden danach neu; der
 * Editor wird über `key` neu montiert, sodass der lokale Zustand frisch aus den
 * geladenen Daten initialisiert wird (keine Prop→State-Synchronisation per Effekt).
 */
import { useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import { de } from '../strings/de'
import {
  ADDABLE_BLOCK_TYPES,
  addBlock,
  defaultBlockData,
  deleteBlock,
  getPage,
  reorderBlocks,
  updateBlock,
  updatePage,
  type Block,
  type BlockData,
  type BlockType,
  type GalleryImage,
  type Page,
  type PageStatus,
} from '../api/pages'
import { useApi, useMutation } from '../hooks/useApi'
import './webseite.css'

const asStr = (v: unknown): string => (typeof v === 'string' ? v : '')

export default function WebseiteEditorPage() {
  const { slug = '' } = useParams<{ slug: string }>()
  const page = useApi(() => getPage(slug), [slug])

  if (page.loading) return <p className="muted">{de.common.loading}</p>
  if (page.error || !page.data) {
    return (
      <section className="page">
        <h2>{de.pages.webseite.title}</h2>
        <div className="alert alert--error">
          <span>{page.error}</span>
          <button type="button" className="btn" onClick={page.reload}>
            {de.common.retry}
          </button>
        </div>
      </section>
    )
  }

  // Signatur der Blöcke -> erzwingt Neu-Montage nach Reload (frische Init).
  const signature = page.data.blocks.map((b) => `${b.id}:${b.order}`).join('|')
  return <PageEditor key={signature} page={page.data} reload={page.reload} />
}

function PageEditor({ page, reload }: { page: Page; reload: () => void }) {
  const t = de.pages.webseite
  const [title, setTitle] = useState(page.title)
  const [seo, setSeo] = useState(page.seoDescription ?? '')
  const [status, setStatus] = useState<PageStatus>(page.status)
  const [savedHead, setSavedHead] = useState(false)

  const saveHead = useMutation(() =>
    updatePage(page.id, {
      slug: page.slug,
      title,
      seoDescription: seo.trim() === '' ? null : seo,
      status,
    }),
  )
  async function onSaveHead() {
    const r = await saveHead.run()
    if (r.ok) {
      setSavedHead(true)
      reload()
    }
  }

  const blocks = [...page.blocks].sort((a, b) => a.order - b.order)

  const adder = useMutation((type: BlockType) =>
    addBlock(page.id, { type, data: defaultBlockData(type) }),
  )
  async function onAdd(type: BlockType) {
    const r = await adder.run(type)
    if (r.ok) reload()
  }

  const remover = useMutation((id: string) => deleteBlock(id))
  async function onDelete(id: string) {
    if (!window.confirm(t.blocks.confirmDelete)) return
    const r = await remover.run(id)
    if (r.ok) reload()
  }

  const reorder = useMutation((ids: string[]) => reorderBlocks(page.id, ids))
  async function onMove(index: number, dir: -1 | 1) {
    const target = index + dir
    if (target < 0 || target >= blocks.length) return
    const ids = blocks.map((b) => b.id)
    ;[ids[index], ids[target]] = [ids[target], ids[index]]
    const r = await reorder.run(ids)
    if (r.ok) reload()
  }

  const busy = adder.pending || remover.pending || reorder.pending

  return (
    <section className="page">
      <header className="page-head">
        <div>
          <h2>{page.title}</h2>
          <p className="muted">/{page.slug}</p>
        </div>
        <div className="head-actions">
          <Link to="/webseite" className="btn">
            {t.back}
          </Link>
        </div>
      </header>

      {/* Seiten-Kopf bearbeiten */}
      <div className="webseite-section">
        <label className="field">
          <span className="field-label">{t.editor.pageTitleLabel}</span>
          <input
            className="input"
            value={title}
            onChange={(e) => {
              setTitle(e.target.value)
              setSavedHead(false)
            }}
          />
        </label>
        <label className="field">
          <span className="field-label">{t.editor.seoLabel}</span>
          <textarea
            className="input"
            rows={2}
            value={seo}
            onChange={(e) => {
              setSeo(e.target.value)
              setSavedHead(false)
            }}
          />
          <span className="field-hint">{t.editor.seoHint}</span>
        </label>
        <label className="field">
          <span className="field-label">{t.statusLabel}</span>
          <select
            className="input"
            value={status}
            onChange={(e) => {
              setStatus(e.target.value as PageStatus)
              setSavedHead(false)
            }}
          >
            <option value="Draft">{t.statusDraft}</option>
            <option value="Published">{t.statusPublished}</option>
          </select>
        </label>
        {saveHead.error && <div className="alert alert--error">{saveHead.error}</div>}
        <div className="head-actions">
          <button type="button" className="btn btn--primary" onClick={onSaveHead} disabled={saveHead.pending}>
            {t.editor.save}
          </button>
          {savedHead && <span className="saved-hint">{t.editor.saved}</span>}
        </div>
      </div>

      {/* Block-Editor */}
      <h3 className="webseite-blocks-title">{t.blocks.sectionTitle}</h3>
      {(reorder.error || remover.error || adder.error) && (
        <div className="alert alert--error">{reorder.error ?? remover.error ?? adder.error}</div>
      )}

      {blocks.length === 0 ? (
        <p className="muted">{t.blocks.empty}</p>
      ) : (
        <ol className="block-list">
          {blocks.map((b, i) => (
            <li key={b.id}>
              <BlockCard
                block={b}
                index={i}
                count={blocks.length}
                busy={busy}
                onMove={onMove}
                onDelete={onDelete}
              />
            </li>
          ))}
        </ol>
      )}

      <div className="block-add" role="group" aria-label={t.blocks.addLabel}>
        <span className="field-label">{t.blocks.addLabel}</span>
        {ADDABLE_BLOCK_TYPES.map((type) => (
          <button
            key={type}
            type="button"
            className="btn"
            disabled={adder.pending}
            onClick={() => onAdd(type)}
          >
            + {t.blocks.types[type]}
          </button>
        ))}
      </div>
    </section>
  )
}

function BlockCard({
  block,
  index,
  count,
  busy,
  onMove,
  onDelete,
}: {
  block: Block
  index: number
  count: number
  busy: boolean
  onMove: (index: number, dir: -1 | 1) => void
  onDelete: (id: string) => void
}) {
  const t = de.pages.webseite.blocks
  const [data, setData] = useState<BlockData>(block.data)
  const [saved, setSaved] = useState(false)

  const save = useMutation(() => updateBlock(block.id, { type: block.type, data }))
  async function onSave() {
    const r = await save.run()
    if (r.ok) setSaved(true)
  }
  const set = (patch: BlockData) => {
    setData((d) => ({ ...d, ...patch }))
    setSaved(false)
  }

  return (
    <div className="block-card">
      <div className="block-card__head">
        <span className="block-card__type">{t.types[block.type]}</span>
        <span className="block-card__tools">
          <button
            type="button"
            className="btn btn--icon"
            aria-label={t.moveUp}
            disabled={busy || index === 0}
            onClick={() => onMove(index, -1)}
          >
            ↑
          </button>
          <button
            type="button"
            className="btn btn--icon"
            aria-label={t.moveDown}
            disabled={busy || index === count - 1}
            onClick={() => onMove(index, 1)}
          >
            ↓
          </button>
          <button
            type="button"
            className="btn btn--danger"
            disabled={busy}
            onClick={() => onDelete(block.id)}
          >
            {t.delete}
          </button>
        </span>
      </div>

      <BlockFields type={block.type} data={data} set={set} />

      {save.error && <div className="alert alert--error">{save.error}</div>}
      <div className="head-actions">
        <button type="button" className="btn btn--primary" onClick={onSave} disabled={save.pending}>
          {t.save}
        </button>
        {saved && <span className="saved-hint">{t.saved}</span>}
      </div>
    </div>
  )
}

function BlockFields({
  type,
  data,
  set,
}: {
  type: BlockType
  data: BlockData
  set: (patch: BlockData) => void
}) {
  const f = de.pages.webseite.blocks.fields

  switch (type) {
    case 'Heading':
      return (
        <>
          <label className="field">
            <span className="field-label">{f.headingText}</span>
            <input className="input" value={asStr(data.text)} onChange={(e) => set({ text: e.target.value })} />
          </label>
          <label className="field">
            <span className="field-label">{f.headingLevel}</span>
            <select
              className="input"
              value={data.level === 3 ? '3' : '2'}
              onChange={(e) => set({ level: Number(e.target.value) })}
            >
              <option value="2">{f.levelMain}</option>
              <option value="3">{f.levelSub}</option>
            </select>
          </label>
        </>
      )

    case 'RichText':
      return (
        <label className="field">
          <span className="field-label">{f.markdown}</span>
          <textarea
            className="input block-markdown"
            rows={6}
            value={asStr(data.markdown)}
            onChange={(e) => set({ markdown: e.target.value })}
          />
          <span className="field-hint">{f.markdownHint}</span>
        </label>
      )

    case 'Image':
      return (
        <>
          <label className="field">
            <span className="field-label">{f.imageUrl}</span>
            <input className="input" value={asStr(data.url)} onChange={(e) => set({ url: e.target.value })} />
          </label>
          <label className="field">
            <span className="field-label">{f.imageAlt}</span>
            <input className="input" value={asStr(data.alt)} onChange={(e) => set({ alt: e.target.value })} />
          </label>
        </>
      )

    case 'Gallery':
      return <GalleryFields data={data} set={set} />

    case 'ContactInfo':
      return (
        <>
          <label className="field">
            <span className="field-label">{f.contactName}</span>
            <input className="input" value={asStr(data.name)} onChange={(e) => set({ name: e.target.value })} />
          </label>
          <label className="field">
            <span className="field-label">{f.contactEmail}</span>
            <input className="input" value={asStr(data.email)} onChange={(e) => set({ email: e.target.value })} />
          </label>
          <label className="field">
            <span className="field-label">{f.contactPhone}</span>
            <input className="input" value={asStr(data.phone)} onChange={(e) => set({ phone: e.target.value })} />
          </label>
          <label className="field">
            <span className="field-label">{f.contactAddress}</span>
            <textarea
              className="input"
              rows={2}
              value={asStr(data.address)}
              onChange={(e) => set({ address: e.target.value })}
            />
          </label>
        </>
      )

    case 'AbgabetiereList':
      return (
        <>
          <p className="field-hint">{f.abgabeAutoNote}</p>
          <label className="field">
            <span className="field-label">{f.abgabeIntro}</span>
            <textarea
              className="input"
              rows={3}
              value={asStr(data.intro)}
              onChange={(e) => set({ intro: e.target.value })}
            />
          </label>
        </>
      )
  }
}

function GalleryFields({ data, set }: { data: BlockData; set: (patch: BlockData) => void }) {
  const f = de.pages.webseite.blocks.fields
  const images: GalleryImage[] = Array.isArray(data.images) ? (data.images as GalleryImage[]) : []

  const update = (i: number, patch: Partial<GalleryImage>) =>
    set({ images: images.map((img, j) => (j === i ? { ...img, ...patch } : img)) })

  return (
    <div className="field">
      <span className="field-label">{f.galleryImages}</span>
      {images.map((img, i) => (
        <div key={i} className="gallery-row">
          <input
            className="input"
            placeholder={f.imageUrl}
            value={asStr(img.url)}
            onChange={(e) => update(i, { url: e.target.value })}
          />
          <input
            className="input"
            placeholder={f.imageAlt}
            value={asStr(img.alt)}
            onChange={(e) => update(i, { alt: e.target.value })}
          />
          <button
            type="button"
            className="btn btn--danger"
            onClick={() => set({ images: images.filter((_, j) => j !== i) })}
          >
            {f.galleryRemove}
          </button>
        </div>
      ))}
      <button type="button" className="btn" onClick={() => set({ images: [...images, { url: '', alt: '' }] })}>
        + {f.galleryAdd}
      </button>
    </div>
  )
}
