(function attachRecipeBuilder(global) {
  const React = global.React;
  if (!React) return;

  function clone(value) { return JSON.parse(JSON.stringify(value)); }

  function RecipeBuilder({ template, stepTypes, activeRecipe, onSaved }) {
    const [name, setName] = React.useState('');
    const [description, setDescription] = React.useState('');
    const [visibility, setVisibility] = React.useState('organization');
    const [category, setCategory] = React.useState('custom');
    const [steps, setSteps] = React.useState([]);
    const [saving, setSaving] = React.useState(false);
    const [error, setError] = React.useState('');

    React.useEffect(() => {
      const source = activeRecipe || template;
      if (!source) return;
      setName(source.name || '');
      setDescription(source.description || '');
      setVisibility(source.visibility || 'organization');
      setCategory(source.category || 'custom');
      setSteps(clone(source.steps || []));
    }, [template && template.id, activeRecipe && activeRecipe.id]);

    function updateStep(index, next) { setSteps((items) => items.map((item, idx) => idx === index ? next : item)); }
    function moveStep(index, delta) { setSteps((items) => { const copy = items.slice(); const next = index + delta; if (next < 0 || next >= copy.length) return copy; const [item] = copy.splice(index, 1); copy.splice(next, 0, item); return copy; }); }
    function removeStep(index) { setSteps((items) => items.filter((_, idx) => idx !== index)); }
    function addStep() { const type = stepTypes && stepTypes[0] && stepTypes[0].type || 'freeSeo.deepCrawl'; setSteps((items) => items.concat([{ id: `step_${items.length + 1}`, type, name: type, config: {}, dependsOn: [] }])); }

    async function save(event) {
      event.preventDefault();
      setSaving(true); setError('');
      try {
        const payload = { name, description, visibility, category, steps };
        const response = activeRecipe ? await global.JS_API.freeSeo.agencyRecipes.update(activeRecipe.id, payload) : await global.JS_API.freeSeo.agencyRecipes.create(payload);
        onSaved && onSaved(response.data || response);
      } catch (err) { setError(err.message || 'Unable to save recipe.'); }
      finally { setSaving(false); }
    }

    return <form className="free-seo-card" onSubmit={save}>
      <h2>{activeRecipe ? 'Edit recipe' : 'Create recipe'}</h2>
      {error ? <div className="alert alert-error">{error}</div> : null}
      <div className="grid two">
        <label>Name<input required value={name} onChange={(e) => setName(e.target.value)} /></label>
        <label>Visibility<select value={visibility} onChange={(e) => setVisibility(e.target.value)}><option value="organization">Organization</option><option value="private">Private</option></select></label>
        <label>Category<input value={category} onChange={(e) => setCategory(e.target.value)} /></label>
        <label>Description<textarea rows="3" value={description} onChange={(e) => setDescription(e.target.value)} /></label>
      </div>
      <div className="row between"><h3>Steps</h3><button type="button" className="button" onClick={addStep}>Add step</button></div>
      {steps.map((step, index) => <global.RecipeStepEditor key={step.id || index} step={step} index={index} stepTypes={stepTypes} onChange={(next) => updateStep(index, next)} onMove={(delta) => moveStep(index, delta)} onRemove={() => removeStep(index)} />)}
      <button className="button primary" type="submit" disabled={saving}>{saving ? 'Saving...' : 'Save recipe'}</button>
    </form>;
  }

  global.RecipeBuilder = RecipeBuilder;
})(window);
