// Schema-driven form fields. The editor renders a collection's `fields` (from
// /api/schema) generically, so the SAME admin works for any site's content model
// (openbureau, kgva, …). Field types → controls; markdown ('body') is handled by
// the rich editor in App.jsx, not here.
//
// A field: { name, type, required?, options?, default?, hint?, palette? }
// Types: string | text | slug | number | date | bool | select | list | image |
//        color | markdown (markdown rendered separately).

// openbureau's named colour palette — used for type:'color' when no per-field
// palette is given. Harmless elsewhere (sites without colour fields never see it).
export const DEFAULT_PALETTE = [
  ['', 'keine', 'transparent'],
  ['ajisai', 'Ajisai · Hortensie', '#A39EC4'], ['sakura', 'Sakura · Kirschblüte', '#C49EC4'],
  ['suna', 'Suna · Sand', '#C4C19E'], ['ichigo', 'Ichigo · Erdbeere', '#C49EA0'],
  ['yuyake', 'Yuyake · Sonnenuntergang', '#CEB188'], ['sora', 'Sora · Himmel', '#9EC3C4'],
  ['kusa', 'Kusa · Gras', '#9EC49F'], ['kori', 'Kori · Eis', '#A5B4CB'],
  ['amagumo', 'Amagumo · Regenwolke', '#4C4C4C'], ['yuki', 'Yuki · Schnee', '#F0F0F0'],
];
export const hexOf = (palette, name) => (palette.find((c) => c[0] === name) || [])[2] || 'transparent';

const SHORT = new Set(['string', 'slug', 'number', 'date', 'bool', 'select', 'color']);
export const isShort = (f) => SHORT.has(f.type);
export const isBody = (f) => f.type === 'markdown';

// Empty form for a new entry of `collection`.
export function blankForm(collection) {
  const f = { __raw: {} };
  for (const fld of collection.fields || []) {
    if (isBody(fld)) { f[fld.name] = fld.default ?? ''; continue; }
    if (fld.type === 'bool') f[fld.name] = fld.default ?? false;
    else if (fld.type === 'list') f[fld.name] = '';
    else f[fld.name] = fld.default ?? '';
  }
  return f;
}

// Frontmatter (from disk) → form values, per field type. The full original
// frontmatter is stashed under __raw so unknown keys survive a save (no data loss).
export function formFromFrontmatter(fm, collection) {
  const f = { __raw: fm || {} };
  for (const fld of collection.fields || []) {
    const v = fm[fld.name];
    if (fld.type === 'bool') f[fld.name] = !!v;
    else if (fld.type === 'list') f[fld.name] = Array.isArray(v) ? v.join(', ') : (v || '');
    else if (fld.type === 'date') f[fld.name] = v ? String(v).slice(0, 10) : '';
    else if (fld.type === 'number') f[fld.name] = v ?? '';
    else f[fld.name] = v ?? '';
  }
  return f;
}

// Form values → frontmatter. Starts from any preserved __raw (so fields not in the
// schema, e.g. image galleries, are kept), then sets/clears the schema fields.
export function frontmatterFromForm(form, collection) {
  const fm = { ...(form.__raw || {}) };
  const setOrDrop = (k, v) => { if (v === '' || v == null || (Array.isArray(v) && !v.length)) delete fm[k]; else fm[k] = v; };
  for (const fld of collection.fields || []) {
    const v = form[fld.name];
    if (fld.type === 'bool') { if (v) fm[fld.name] = true; else delete fm[fld.name]; continue; }
    if (fld.type === 'number') { setOrDrop(fld.name, v === '' || v == null ? '' : Number(v)); continue; }
    if (fld.type === 'list') { setOrDrop(fld.name, (v || '').split(',').map((x) => x.trim()).filter(Boolean)); continue; }
    setOrDrop(fld.name, v);
  }
  return fm;
}

// Build the target path from collection.path ( e.g. 'archiv/:section/:slug' ),
// falling back to '<slug>.md' (or '<id>.md' when there is no slug field).
export function targetPath(form, collection) {
  const tmpl = collection.path;
  const slug = (form.slug || '').trim();
  if (tmpl) {
    const rel = tmpl.replace(/:([a-z_]+)/gi, (_, k) => (form[k] || '').toString().trim());
    if (rel.includes('//') || rel.endsWith('/') || /:/.test(rel)) return ''; // missing segment
    return rel + '.md';
  }
  if (slug) return `${slug}.md`;
  return '';
}

// One field control (everything except markdown/body).
export function Field({ field, value, onChange, onUpload, busy }) {
  const set = (val) => onChange(field.name, val);
  const label = field.label || field.name;
  const palette = field.palette || DEFAULT_PALETTE;

  if (field.type === 'bool') {
    return <label className="check"><input type="checkbox" checked={!!value} onChange={(e) => set(e.target.checked)} /> {label}</label>;
  }
  if (field.type === 'select') {
    return (
      <label className="sm">{label}
        <select value={value || ''} onChange={(e) => set(e.target.value)}>
          {!field.required && <option value="">(—)</option>}
          {(field.options || []).map((o) => <option key={o} value={o}>{o}</option>)}
        </select>
      </label>
    );
  }
  if (field.type === 'color') {
    return (
      <label className="sm">{label}
        <div className="colorpick">
          <span className="swatch" style={{ background: hexOf(palette, value) }} />
          <select value={value || ''} onChange={(e) => set(e.target.value)}>
            {palette.map(([v, lbl]) => <option key={v} value={v}>{lbl}</option>)}
          </select>
        </div>
      </label>
    );
  }
  if (field.type === 'image') {
    return (
      <label>{label}
        <div className="cover-row">
          <input value={value || ''} onChange={(e) => set(e.target.value)} placeholder="/img/…" />
          <ImageUpload onUpload={onUpload} onDone={set} busy={busy} />
          {value && <span className="cover-thumb" style={{ backgroundImage: `url(${value})` }} />}
        </div>
      </label>
    );
  }
  if (field.type === 'text') {
    return <label>{label}<textarea value={value || ''} rows={2} onChange={(e) => set(e.target.value)} placeholder={field.hint || ''} /></label>;
  }
  if (field.type === 'number') {
    return <label className="xs">{label}<input type="number" value={value ?? ''} onChange={(e) => set(e.target.value)} placeholder={field.hint || ''} /></label>;
  }
  if (field.type === 'date') {
    return <label className="sm">{label}<input type="date" value={value || ''} onChange={(e) => set(e.target.value)} /></label>;
  }
  if (field.type === 'list') {
    return <label>{label}<input value={value || ''} onChange={(e) => set(e.target.value)} placeholder={field.hint || 'komma, getrennt'} /></label>;
  }
  // string, slug, and any unknown type → text input
  const cls = field.type === 'slug' ? 'sm' : '';
  return <label className={cls}>{label}<input value={value || ''} onChange={(e) => set(e.target.value)} placeholder={field.hint || ''} /></label>;
}

import { useRef } from 'react';
function ImageUpload({ onUpload, onDone, busy }) {
  const ref = useRef(null);
  return (
    <>
      <button type="button" onClick={() => ref.current?.click()} disabled={busy}>Hochladen</button>
      <input ref={ref} type="file" accept="image/*" hidden onChange={async (ev) => {
        const file = ev.target.files?.[0]; ev.target.value = '';
        if (!file) return;
        try { onDone(await onUpload(file)); } catch { /* ignore */ }
      }} />
    </>
  );
}
