/* global React, Icon, IconBtn, db */
/* Flashcard schema builder.
 * One screen for both create + edit. Steps are stacked vertically rather
 * than wizard-paged so the entire schema is visible while tweaking it.
 */
const { useState, useEffect, useMemo, useCallback } = React;

function FlashcardBuilder({ collection, cardsCount = 0, onCancel, onSaved }) {
  const isEdit = !!collection;
  const { FIELD_TYPES, FIELD_TYPE_BY_ID, STARTER_TEMPLATES, fieldUid } = window.flashcards;

  const [name, setName] = useState(collection?.name || '');
  const [description, setDescription] = useState(collection?.description || '');
  const [srcLang, setSrcLang] = useState(collection?.srcLang || '');
  const [tgtLang, setTgtLang] = useState(collection?.tgtLang || '');
  const [schema, setSchema] = useState(collection?.schema || []);
  const [promptField, setPromptField] = useState(collection?.promptField || null);
  const [answerFields, setAnswerFields] = useState(collection?.answerFields || []);
  const [pickedTemplate, setPickedTemplate] = useState(isEdit ? null : 'general');
  const [saving, setSaving] = useState(false);

  // Apply a template — only when nothing has been authored yet
  const applyTemplate = (tplId) => {
    const tpl = STARTER_TEMPLATES.find(t => t.id === tplId);
    if (!tpl) return;
    const newSchema = tpl.schema.map((f, i) => ({
      id: fieldUid(),
      name: f.name,
      type: f.type,
      required: f.required,
      hint: f.hint || '',
      options: f.options || [],
    }));
    setSchema(newSchema);
    setPromptField(newSchema[tpl.promptIdx]?.id || null);
    setAnswerFields(tpl.answerIdxs.map(i => newSchema[i]?.id).filter(Boolean));
    setPickedTemplate(tplId);
    if (!name && tpl.id === 'general') setName('New collection');
  };

  // First-mount: prepopulate from default template if creating
  useEffect(() => {
    if (isEdit) return;
    if (schema.length === 0 && pickedTemplate === 'general') applyTemplate('general');
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const addField = () => {
    const f = { id: fieldUid(), name: '', type: 'text', required: false, hint: '', options: [] };
    setSchema(prev => [...prev, f]);
    setPickedTemplate(null);
  };

  const updateField = (id, patch) => {
    setSchema(prev => prev.map(f => f.id === id ? { ...f, ...patch } : f));
    setPickedTemplate(null);
  };

  const removeField = async (id) => {
    if (isEdit && cardsCount > 0) {
      const ok = await window.lhDialog.confirm({
        title: 'Remove this field?',
        message: `This field exists on ${cardsCount} card${cardsCount === 1 ? '' : 's'}. Their values for this field will be discarded.`,
        confirmLabel: 'Remove field',
        danger: true,
        icon: 'delete',
      });
      if (!ok) return;
    }
    setSchema(prev => prev.filter(f => f.id !== id));
    if (promptField === id) setPromptField(null);
    setAnswerFields(prev => prev.filter(x => x !== id));
    setPickedTemplate(null);
  };

  const moveField = (id, dir) => {
    setSchema(prev => {
      const i = prev.findIndex(f => f.id === id);
      const j = i + dir;
      if (i < 0 || j < 0 || j >= prev.length) return prev;
      const next = [...prev];
      [next[i], next[j]] = [next[j], next[i]];
      return next;
    });
    setPickedTemplate(null);
  };

  const togglePromptAnswer = (id, role) => {
    if (role === 'prompt') {
      setPromptField(id);
      setAnswerFields(prev => prev.filter(x => x !== id));
    } else if (role === 'answer') {
      if (promptField === id) setPromptField(null);
      setAnswerFields(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]);
    } else {
      if (promptField === id) setPromptField(null);
      setAnswerFields(prev => prev.filter(x => x !== id));
    }
  };

  const roleOf = (id) =>
    promptField === id ? 'prompt' :
    answerFields.includes(id) ? 'answer' : 'none';

  const errors = useMemo(() => {
    const out = [];
    if (!name.trim()) out.push('Give the collection a name.');
    if (schema.length === 0) out.push('Add at least one field.');
    if (schema.some(f => !f.name.trim())) out.push('Every field needs a name.');
    if (!promptField) out.push('Pick one field as the prompt (the side shown first).');
    if (answerFields.length === 0) out.push('Pick at least one field as the answer.');
    return out;
  }, [name, schema, promptField, answerFields]);

  const save = async () => {
    if (errors.length > 0) return;
    setSaving(true);
    const cleaned = schema.map(f => ({
      id: f.id,
      name: f.name.trim(),
      type: f.type,
      required: !!f.required,
      hint: f.hint?.trim() || '',
      options: f.type === 'select' ? (f.options || []).filter(o => o.trim()) : undefined,
    }));
    const next = {
      ...(collection || {}),
      name: name.trim(),
      description: description.trim(),
      srcLang: srcLang.trim(),
      tgtLang: tgtLang.trim(),
      schema: cleaned,
      promptField,
      answerFields,
      archived: collection?.archived || false,
      lastStudiedAt: collection?.lastStudiedAt || null,
    };
    const saved = await db.flashcardCollections.put(next);
    setSaving(false);
    onSaved?.(saved);
  };

  const remove = async () => {
    if (!isEdit) return;
    const ok = await window.lhDialog.confirm({
      title: `Delete "${collection.name}"?`,
      message: cardsCount > 0
        ? `This collection and all ${cardsCount} of its cards will be permanently removed.`
        : 'This collection will be permanently removed.',
      confirmLabel: 'Delete forever',
      danger: true,
      icon: 'delete_forever',
    });
    if (!ok) return;
    // Cascade-delete cards belonging to this collection
    const cards = await db.flashcardCards.list({ where: c => c.collectionId === collection.id });
    for (const c of cards) await db.flashcardCards.delete(c.id);
    await db.flashcardCollections.delete(collection.id);
    onCancel(); // back to list
  };

  const archive = async () => {
    if (!isEdit) return;
    await db.flashcardCollections.put({ ...collection, archived: !collection.archived });
    onSaved?.({ ...collection, archived: !collection.archived });
  };

  return (
    <div className="fc-builder">
      <button className="fc-detail-back" onClick={onCancel}>
        <Icon name="arrow_back" />Back
      </button>
      <div className="fc-builder-header">
        <h2>{isEdit ? 'Edit collection' : 'New collection'}</h2>
        <p>{isEdit
          ? 'Schema changes apply to all cards in this collection.'
          : 'Pick a template to start with, then tailor the fields to fit how you study.'}</p>
      </div>

      {/* Step 1 — basics */}
      <div className="fc-step">
        <div className="fc-step-label">Step 1 · Basics</div>
        <div className="fc-form-row">
          <div style={{ flex: 2 }}>
            <label className="fc-label">Name</label>
            <input className="fc-input" placeholder="e.g. Japanese N5 vocab" value={name} onChange={e => setName(e.target.value)} maxLength={80} />
          </div>
        </div>
        <div className="fc-form-row">
          <div>
            <label className="fc-label">From (source language)</label>
            <input className="fc-input" placeholder="English" value={srcLang} onChange={e => setSrcLang(e.target.value)} maxLength={40} />
          </div>
          <div>
            <label className="fc-label">To (studying)</label>
            <input className="fc-input" placeholder="Japanese" value={tgtLang} onChange={e => setTgtLang(e.target.value)} maxLength={40} />
          </div>
        </div>
        <div>
          <label className="fc-label">Description (optional)</label>
          <textarea className="fc-textarea" placeholder="Notes about this collection — source, scope, etc." value={description} onChange={e => setDescription(e.target.value)} maxLength={400} />
        </div>
      </div>

      {/* Step 2 — template (only on create) */}
      {!isEdit && (
        <div className="fc-step">
          <div className="fc-step-label">Step 2 · Template</div>
          <h3>Start from a template (you can edit it next)</h3>
          <div className="fc-templates">
            {STARTER_TEMPLATES.map(t => (
              <button
                key={t.id}
                className={`fc-template ${pickedTemplate === t.id ? 'is-active' : ''}`}
                onClick={() => applyTemplate(t.id)}
              >
                <div className="fc-template-head">
                  <Icon name={t.icon} />
                  <span>{t.name}</span>
                </div>
                <div className="fc-template-desc">{t.description}</div>
              </button>
            ))}
          </div>
        </div>
      )}

      {/* Step 3 — fields */}
      <div className="fc-step">
        <div className="fc-step-label">Step {isEdit ? '2' : '3'} · Fields</div>
        <h3>Define what each card looks like</h3>
        <FieldsEditor
          schema={schema}
          roleOf={roleOf}
          onChange={updateField}
          onRemove={removeField}
          onMove={moveField}
          onToggleRole={togglePromptAnswer}
          fieldTypes={FIELD_TYPES}
          fieldTypeById={FIELD_TYPE_BY_ID}
        />
        {schema.length < 10 && (
          <button className="fc-field-add" onClick={addField} style={{ marginTop: 8 }}>
            <Icon name="add" />Add field
          </button>
        )}
        {schema.length >= 10 && (
          <p style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 8 }}>
            Soft limit reached — 10 fields keeps the card form readable.
          </p>
        )}
      </div>

      {/* Roles summary */}
      {schema.length > 0 && (
        <div className="fc-step">
          <div className="fc-step-label">Step {isEdit ? '3' : '4'} · Review</div>
          <div className="fc-roles-summary">
            <div>
              <Icon name="visibility" style={{ fontSize: 14, marginRight: 4, verticalAlign: 'middle' }} />
              <b>Prompt:</b>{' '}
              {promptField
                ? <span style={{ color: 'var(--color-primary)', fontWeight: 600 }}>{schema.find(f => f.id === promptField)?.name || '?'}</span>
                : <span style={{ color: 'var(--text-faint)' }}>not chosen</span>}
            </div>
            <div>
              <Icon name="flip" style={{ fontSize: 14, marginRight: 4, verticalAlign: 'middle' }} />
              <b>Answer:</b>{' '}
              {answerFields.length > 0
                ? <span style={{ color: '#6ee7b7', fontWeight: 600 }}>{schema.filter(f => answerFields.includes(f.id)).map(f => f.name).join(', ')}</span>
                : <span style={{ color: 'var(--text-faint)' }}>not chosen</span>}
            </div>
          </div>
          {errors.length > 0 && (
            <div className="fc-callout is-warn" style={{ marginTop: 12 }}>
              <Icon name="warning" />
              <ul>{errors.map((e, i) => <li key={i}>{e}</li>)}</ul>
            </div>
          )}
        </div>
      )}

      <div className="fc-builder-foot">
        <div style={{ display: 'flex', gap: 8 }}>
          {isEdit && (
            <>
              <button className="lh-btn ghost" onClick={archive}>
                <Icon name={collection.archived ? 'unarchive' : 'archive'} />
                {collection.archived ? 'Unarchive' : 'Archive'}
              </button>
              <button className="lh-btn danger" onClick={remove}>
                <Icon name="delete" />Delete
              </button>
            </>
          )}
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <button className="lh-btn ghost" onClick={onCancel}>Cancel</button>
          <button className="lh-btn primary" disabled={errors.length > 0 || saving} onClick={save}>
            <Icon name="check" />{isEdit ? 'Save changes' : 'Create collection'}
          </button>
        </div>
      </div>
    </div>
  );
}

window.FlashcardBuilder = FlashcardBuilder;

// ----------------------------------------------------------------
// FieldsEditor — list of editable field rows
// ----------------------------------------------------------------
function FieldsEditor({ schema, roleOf, onChange, onRemove, onMove, onToggleRole, fieldTypes, fieldTypeById }) {
  if (schema.length === 0) {
    return (
      <div style={{
        padding: 24, textAlign: 'center', fontSize: 12, color: 'var(--text-muted)',
        border: '1px dashed var(--color-border)', borderRadius: 12,
      }}>
        No fields yet. Pick a template above or add one below.
      </div>
    );
  }
  return (
    <div className="fc-fields-list">
      {schema.map((f, i) => {
        const role = roleOf(f.id);
        const meta = fieldTypeById[f.type] || fieldTypes[0];
        return (
          <div key={f.id} className="fc-field-row">
            <div className="fc-field-handle">
              <button onClick={() => onMove(f.id, -1)} disabled={i === 0} title="Move up">
                <Icon name="keyboard_arrow_up" />
              </button>
              <button onClick={() => onMove(f.id, +1)} disabled={i === schema.length - 1} title="Move down">
                <Icon name="keyboard_arrow_down" />
              </button>
            </div>

            <input
              className="fc-input"
              placeholder="Field name"
              value={f.name}
              onChange={e => onChange(f.id, { name: e.target.value })}
              maxLength={40}
            />

            <select
              className="fc-select"
              value={f.type}
              onChange={e => onChange(f.id, { type: e.target.value })}
            >
              {fieldTypes.map(t => <option key={t.id} value={t.id}>{t.label}</option>)}
            </select>

            <div className="fc-field-role">
              <button
                className={role === 'prompt' ? 'is-prompt' : ''}
                onClick={() => onToggleRole(f.id, role === 'prompt' ? 'none' : 'prompt')}
                title="Show this on the front of the card"
              >Prompt</button>
              <button
                className={role === 'answer' ? 'is-answer' : ''}
                onClick={() => onToggleRole(f.id, role === 'answer' ? 'none' : 'answer')}
                title="Reveal this on the back of the card"
              >Answer</button>
            </div>

            <IconBtn name="delete" tone="danger" title="Remove field" onClick={() => onRemove(f.id)} />

            <div className="fc-field-options" style={{ gridColumn: '2 / -1' }}>
              <input
                className="fc-input"
                placeholder={`Hint shown when filling this field (e.g. ${meta.desc})`}
                value={f.hint || ''}
                onChange={e => onChange(f.id, { hint: e.target.value })}
                maxLength={120}
                style={{ flex: 1, minWidth: 200, fontSize: 11 }}
              />
              {f.type === 'select' && (
                <SelectOptionsEditor
                  options={f.options || []}
                  onChange={(opts) => onChange(f.id, { options: opts })}
                />
              )}
              <label style={{ display: 'inline-flex', alignItems: 'center', gap: 4, cursor: 'pointer', fontSize: 11 }}>
                <input
                  type="checkbox"
                  checked={!!f.required}
                  onChange={e => onChange(f.id, { required: e.target.checked })}
                  style={{ accentColor: 'var(--color-primary)' }}
                />
                Required
              </label>
            </div>
          </div>
        );
      })}
    </div>
  );
}

function SelectOptionsEditor({ options, onChange }) {
  const [draft, setDraft] = useState('');
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4, alignItems: 'center' }}>
      {options.map((o, i) => (
        <span key={i} className="fc-tag-chip">
          {o}
          <button onClick={() => onChange(options.filter((_, j) => j !== i))}>
            <Icon name="close" />
          </button>
        </span>
      ))}
      <input
        className="fc-input"
        placeholder="Add option…"
        value={draft}
        onChange={e => setDraft(e.target.value)}
        onKeyDown={e => {
          if (e.key === 'Enter' && draft.trim()) {
            onChange([...options, draft.trim()]);
            setDraft('');
          }
        }}
        style={{ flex: '0 0 140px', fontSize: 11 }}
      />
    </div>
  );
}
