// Add / Edit recipe modal form. Parses textarea input into {amt, name} rows.

function parseIngredientsText(text) {
  return text.trim().split('\n').filter(Boolean).map(line => {
    line = line.trim();
    // Dimension / compound adjective ("2-inch piece", "1/2-inch knob"): a number
    // immediately hyphenated to a word. Keep it intact in the name, no amt.
    if (/^[\d¼½¾⅓⅔⅛⅜⅝⅞\/]+\s*[-–]\s*[a-zA-Z]/.test(line)) {
      return { amt: '', name: line };
    }
    // Quantity may be a range ("4-5") — hyphen between numbers stays in amt.
    const qtyMatch = line.match(/^([\d¼½¾⅓⅔⅛⅜⅝⅞\/\.\s-–]+)/);
    if (!qtyMatch || !qtyMatch[1].trim()) {
      return { amt: '', name: line };
    }
    const qty  = qtyMatch[1].trim();
    const rest = line.slice(qtyMatch[0].length);
    const unitMatch = rest.match(/^(cups?|tbsps?|tablespoons?|tsps?|teaspoons?|oz|ounces?|lbs?|pounds?|kg|kilograms?|grams?|ml|milliliters?|liters?|litres?|pinch(?:es)?|handfuls?|cloves?|sprigs?|sticks?|cans?|packages?|pkgs?)\b\.?\s*/i);
    if (unitMatch) {
      return { amt: `${qty} ${unitMatch[1]}`, name: rest.slice(unitMatch[0].length).trim() };
    }
    return { amt: qty, name: rest.trim() };
  });
}

function parseStepsText(text) {
  return text.trim().split('\n').map(s => s.trim()).filter(Boolean);
}

function ingredientsToText(ings) {
  return (ings || []).map(i => `${i.amt || ''} ${i.name || ''}`.trim()).join('\n');
}

function stepsToText(steps) {
  return (steps || []).join('\n');
}

function RecipeForm({ recipe, onSave, onCancel }) {
  const isEdit = !!recipe && recipe.id;
  const [name, setName]            = React.useState(recipe?.name || '');
  const [category, setCategory]    = React.useState(recipe?.category || '');
  const [author, setAuthor]        = React.useState(recipe?.author || '');
  const [prep, setPrep]            = React.useState(recipe?.prep || '');
  const [cook, setCook]            = React.useState(recipe?.cook || '');
  const [servings, setServings]    = React.useState(recipe?.servings || '');
  const [description, setDescription] = React.useState(recipe?.description || '');
  const [mealTypes, setMealTypes]  = React.useState(recipe?.mealTypes || []);
  const [meatTypes, setMeatTypes]  = React.useState(recipe?.meatTypes || []);
  const [ingText, setIngText]      = React.useState(ingredientsToText(recipe?.ingredients));
  const [stepText, setStepText]    = React.useState(stepsToText(recipe?.steps));
  const [imageUrl, setImageUrl]      = React.useState(recipe?.image || '');
  const [quickAndEasy, setQuickAndEasy] = React.useState(!!recipe?.quickAndEasy);
  const [uploading, setUploading]  = React.useState(false);
  const [saving, setSaving]        = React.useState(false);
  const fileRef = React.useRef(null);

  // Prevent body scroll while form is open
  React.useEffect(() => {
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = prev; };
  }, []);

  function toggleInList(list, setList, value) {
    setList(list.includes(value) ? list.filter(v => v !== value) : [...list, value]);
  }

  async function handleImageSelect(e) {
    const file = e.target.files[0];
    if (!file) return;
    setUploading(true);
    const fd = new FormData();
    fd.append('image', file);
    try {
      const res = await fetch('/api/upload-image', { method: 'POST', body: fd });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'Upload failed');
      setImageUrl(data.url);
    } catch (err) {
      alert('Image upload failed: ' + err.message);
    } finally {
      setUploading(false);
      if (fileRef.current) fileRef.current.value = '';
    }
  }

  function removeImage() {
    // Optimistic local clear; server cleans up on recipe delete
    setImageUrl('');
  }

  async function handleSubmit(e) {
    if (e) e.preventDefault();
    if (!name.trim()) { alert('Please enter a recipe name.'); return; }
    setSaving(true);

    const payload = {
      ...(recipe || {}),
      name: name.trim(),
      category: category.trim() || 'Other',
      author: author.trim(),
      prep: prep.trim(),
      cook: cook.trim(),
      servings: servings.trim(),
      description: description.trim(),
      mealTypes,
      meatTypes,
      ingredients: parseIngredientsText(ingText),
      steps: parseStepsText(stepText),
      image: imageUrl || undefined,
      favorite: !!recipe?.favorite,
      quickAndEasy,
    };
    try { await onSave(payload); }
    finally { setSaving(false); }
  }

  return (
    <>
      <div className="form-backdrop" onClick={onCancel} />
      <div className="form-modal" role="dialog" aria-modal="true">
        <div className="form-head">
          <h2>{isEdit ? 'Edit recipe' : (recipe && recipe.importedFrom ? 'Review imported recipe' : 'New recipe')}</h2>
          <button className="icon-btn" onClick={onCancel} aria-label="Close"><IconX size={18} /></button>
        </div>

        {recipe && recipe.importedFrom && (
          <div className="import-banner">
            <div>
              <strong>Imported from</strong>
              <a href={recipe.importedFrom} target="_blank" rel="noopener noreferrer">{recipe.importedFrom}</a>
            </div>
            {Array.isArray(recipe.missingFields) && recipe.missingFields.length > 0 && (
              <div className="import-warning">
                ⚠️ Couldn't extract: {recipe.missingFields.join(', ')}. Review and fill in below.
              </div>
            )}
          </div>
        )}

        <form className="form-body" onSubmit={handleSubmit}>
          <div className="form-grid">
            <div className="form-photo">
              {imageUrl ? (
                <div className="form-photo-preview">
                  <img src={imageUrl} alt="Recipe" />
                  <button type="button" className="photo-remove" onClick={removeImage} title="Remove">
                    <IconX size={14} />
                  </button>
                </div>
              ) : (
                <button type="button" className="form-photo-empty" onClick={() => fileRef.current?.click()}>
                  <IconCamera size={28} stroke={1.3} />
                  <div className="form-photo-empty-label">
                    {uploading ? 'Uploading…' : 'Add a photo'}
                  </div>
                  <div className="form-photo-empty-hint">JPEG, PNG, WebP · 8 MB max</div>
                </button>
              )}
              <input ref={fileRef} type="file" accept="image/jpeg,image/png,image/webp,image/gif" hidden onChange={handleImageSelect} />
            </div>

            <div className="form-fields">
              <label className="form-field">
                <span className="form-label">Recipe name *</span>
                <input type="text" value={name} onChange={e => setName(e.target.value)} maxLength={200} required autoFocus />
              </label>

              <label className="form-field">
                <span className="form-label">Category</span>
                <input type="text" value={category} onChange={e => setCategory(e.target.value)}
                       maxLength={80} placeholder="Mains, Sides, Desserts…" list="form-categories" />
                <datalist id="form-categories">
                  {['Mains','Sides','Desserts','Baking','Appetizers','Soups & Salads','Breakfast','Drinks','Marinades','Other'].map(c => <option key={c} value={c} />)}
                </datalist>
              </label>

              <label className="form-field">
                <span className="form-label">Author / source <span className="form-hint">— who created the recipe</span></span>
                <input type="text" value={author} onChange={e => setAuthor(e.target.value)} maxLength={80} placeholder="Bobby Flay, NYT Cooking, family recipe…" />
              </label>

              <div className="form-row form-row-3">
                <label className="form-field">
                  <span className="form-label">Prep</span>
                  <input type="text" value={prep} onChange={e => setPrep(e.target.value)} maxLength={60} placeholder="15 min" />
                </label>
                <label className="form-field">
                  <span className="form-label">Cook</span>
                  <input type="text" value={cook} onChange={e => setCook(e.target.value)} maxLength={60} placeholder="30 min" />
                </label>
                <label className="form-field">
                  <span className="form-label">Serves</span>
                  <input type="text" value={servings} onChange={e => setServings(e.target.value)} maxLength={60} placeholder="4" />
                </label>
              </div>
            </div>
          </div>

          <label className="form-field">
            <span className="form-label">Description</span>
            <textarea rows={2} value={description} onChange={e => setDescription(e.target.value)} maxLength={3000} placeholder="A short note about the dish…" />
          </label>

          <div className="form-field">
            <span className="form-label">Meal type</span>
            <div className="form-chips">
              {MEAL_TYPES.map(t => (
                <button key={t} type="button"
                        className={`pill ${mealTypes.includes(t) ? 'is-active' : ''}`}
                        onClick={() => toggleInList(mealTypes, setMealTypes, t)}>
                  {t}
                </button>
              ))}
            </div>
          </div>

          <div className="form-field">
            <span className="form-label">Protein / diet</span>
            <div className="form-chips">
              {MEAT_TYPES.map(t => (
                <button key={t} type="button"
                        className={`pill pill-outline ${meatTypes.includes(t) ? 'is-active' : ''}`}
                        onClick={() => toggleInList(meatTypes, setMeatTypes, t)}>
                  {t}
                </button>
              ))}
            </div>
          </div>

          <label className="form-field form-field-inline">
            <input
              type="checkbox"
              checked={quickAndEasy}
              onChange={e => setQuickAndEasy(e.target.checked)}
              className="form-checkbox"
            />
            <span className="form-label form-label-inline">⚡ Quick &amp; Easy <span className="form-hint">— ready in 20 minutes or less</span></span>
          </label>

          <label className="form-field">
            <span className="form-label">Ingredients <span className="form-hint">— one per line. e.g. "2 cups flour"</span></span>
            <textarea rows={7} value={ingText} onChange={e => setIngText(e.target.value)}
                      placeholder={"2 cups all-purpose flour\n1 tsp salt\n3 large eggs"} />
          </label>

          <label className="form-field">
            <span className="form-label">Steps <span className="form-hint">— one per line</span></span>
            <textarea rows={7} value={stepText} onChange={e => setStepText(e.target.value)}
                      placeholder={"Preheat the oven to 375°F.\nMix the dry ingredients in a bowl.\n…"} />
          </label>

          <div className="form-footer">
            <button type="button" className="ghost-btn big" onClick={onCancel}>Cancel</button>
            <button type="submit" className="primary-btn big" disabled={saving || uploading}>
              {saving ? 'Saving…' : (isEdit ? 'Save changes' : 'Add recipe')}
            </button>
          </div>
        </form>
      </div>
    </>
  );
}

// ── Import from URL modal ──────────────────────────────────
function ImportUrlModal({ onClose, onImported }) {
  const [url, setUrl] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState('');

  React.useEffect(() => {
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = prev; };
  }, []);

  async function handleSubmit(e) {
    e.preventDefault();
    const trimmed = url.trim();
    if (!trimmed) return;
    setLoading(true);
    setError('');
    try {
      const res = await fetch('/api/import-url', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ url: trimmed })
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'Extraction failed');
      onImported(data);
    } catch (err) {
      setError(err.message || 'Something went wrong');
    } finally {
      setLoading(false);
    }
  }

  return (
    <>
      <div className="form-backdrop" onClick={loading ? null : onClose} />
      <div className="import-modal" role="dialog" aria-modal="true">
        <div className="form-head">
          <h2>Import from URL</h2>
          <button className="icon-btn" onClick={onClose} disabled={loading} aria-label="Close">
            <IconX size={18} />
          </button>
        </div>
        <form onSubmit={handleSubmit} className="import-body">
          <p className="import-hint">
            Paste any recipe URL — AllRecipes, NYT Cooking, Food Network, a personal blog.
            Claude will read the page and fill out the recipe form for you to review.
          </p>
          <input
            type="url"
            value={url}
            onChange={e => setUrl(e.target.value)}
            placeholder="https://example.com/great-recipe"
            autoFocus
            disabled={loading}
            required
          />
          {error && <div className="import-error">{error}</div>}
          {loading && (
            <div className="import-status">
              <span className="spinner" /> Extracting recipe… this takes a few seconds.
            </div>
          )}
          <div className="form-footer">
            <button type="button" className="ghost-btn big" onClick={onClose} disabled={loading}>
              Cancel
            </button>
            <button type="submit" className="primary-btn big" disabled={loading || !url.trim()}>
              {loading ? 'Extracting…' : 'Extract recipe'}
            </button>
          </div>
        </form>
      </div>
    </>
  );
}

// ── Scan cookbook page — multi-page (Claude Vision) ────────
const MAX_SCAN_PAGES = 6;

function ScanModal({ onClose, onImported }) {
  // pages: [{ file, previewUrl }]
  const [pages, setPages]     = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [error, setError]     = React.useState('');
  const fileRef = React.useRef(null);

  React.useEffect(() => {
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = prev; };
  }, []);

  // Revoke all blob URLs on unmount
  React.useEffect(() => {
    return () => { pages.forEach(p => URL.revokeObjectURL(p.previewUrl)); };
  }, []);

  function handleFile(e) {
    const f = e.target.files && e.target.files[0];
    if (!f) return;
    if (fileRef.current) fileRef.current.value = '';
    setPages(prev => [...prev, { file: f, previewUrl: URL.createObjectURL(f) }]);
    setError('');
  }

  function removePage(idx) {
    setPages(prev => {
      URL.revokeObjectURL(prev[idx].previewUrl);
      return prev.filter((_, i) => i !== idx);
    });
  }

  async function handleSubmit() {
    if (!pages.length) return;
    setLoading(true); setError('');
    const fd = new FormData();
    pages.forEach(p => fd.append('images', p.file));
    try {
      const res  = await fetch('/api/import-photo', { method: 'POST', body: fd });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'Extraction failed');
      onImported(data);
    } catch (err) {
      setError(err.message || 'Something went wrong');
    } finally {
      setLoading(false);
    }
  }

  const canAddMore = pages.length < MAX_SCAN_PAGES && !loading;

  return (
    <>
      <div className="form-backdrop" onClick={loading ? null : onClose} />
      <div className="import-modal" role="dialog" aria-modal="true">
        <div className="form-head">
          <h2>Scan a cookbook page</h2>
          <button className="icon-btn" onClick={onClose} disabled={loading} aria-label="Close">
            <IconX size={18} />
          </button>
        </div>
        <div className="import-body">
          {pages.length === 0 ? (
            <>
              <p className="import-hint">
                Take a photo of a recipe page or pick one from your library.
                Claude will read the text and pre-fill the recipe form.
              </p>
              <button type="button" className="scan-picker" onClick={() => fileRef.current?.click()}>
                <IconCamera size={32} stroke={1.3} />
                <div className="scan-picker-label">Tap to pick or take a photo</div>
                <div className="scan-picker-hint">JPEG, PNG, WebP · up to {MAX_SCAN_PAGES} pages</div>
              </button>
            </>
          ) : (
            <>
              <p className="import-hint">
                {pages.length} page{pages.length > 1 ? 's' : ''} captured
                {pages.length < MAX_SCAN_PAGES ? ` · up to ${MAX_SCAN_PAGES - pages.length} more` : ' · max reached'}.
              </p>
              <div className="scan-pages-grid">
                {pages.map((p, i) => (
                  <div key={i} className="scan-page-thumb">
                    <img src={p.previewUrl} alt={`Page ${i + 1}`} />
                    <span className="scan-page-num">p.{i + 1}</span>
                    {!loading && (
                      <button
                        type="button"
                        className="scan-page-remove"
                        onClick={() => removePage(i)}
                        aria-label={`Remove page ${i + 1}`}
                      >
                        <IconX size={12} />
                      </button>
                    )}
                  </div>
                ))}
                {canAddMore && (
                  <button
                    type="button"
                    className="scan-page-add"
                    onClick={() => fileRef.current?.click()}
                  >
                    <IconCamera size={22} stroke={1.3} />
                    <span>Add page</span>
                  </button>
                )}
              </div>
            </>
          )}

          <input ref={fileRef} type="file" accept="image/*" capture="environment" hidden onChange={handleFile} />

          {error && <div className="import-error">{error}</div>}
          {loading && (
            <div className="import-status">
              <span className="spinner" /> Reading {pages.length > 1 ? 'pages' : 'page'}… this takes a few seconds.
            </div>
          )}

          <div className="form-footer">
            <button type="button" className="ghost-btn big" onClick={onClose} disabled={loading}>Cancel</button>
            <button
              type="button"
              className="primary-btn big"
              onClick={handleSubmit}
              disabled={loading || pages.length === 0}
            >
              {loading ? 'Reading…' : 'Process recipe'}
            </button>
          </div>
        </div>
      </div>
    </>
  );
}

// ── Dish photo prompt (shown after scan import) ─────────────
function DishPhotoModal({ onDone }) {
  const [uploading, setUploading] = React.useState(false);
  const [error, setError]         = React.useState('');
  const fileRef = React.useRef(null);

  React.useEffect(() => {
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = prev; };
  }, []);

  async function handleFile(e) {
    const f = e.target.files && e.target.files[0];
    if (!f) return;
    if (fileRef.current) fileRef.current.value = '';
    setUploading(true); setError('');
    try {
      const fd = new FormData();
      fd.append('image', f);
      const res  = await fetch('/api/upload-image', { method: 'POST', body: fd });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'Upload failed');
      onDone(data.url);
    } catch (err) {
      setError(err.message || 'Upload failed');
      setUploading(false);
    }
  }

  return (
    <>
      <div className="form-backdrop" />
      <div className="import-modal dish-photo-modal" role="dialog" aria-modal="true">
        <div className="form-head">
          <h2>Add a dish photo?</h2>
        </div>
        <div className="import-body">
          <p className="import-hint">
            Add a photo of the finished dish to show alongside the recipe.
          </p>

          {error && <div className="import-error">{error}</div>}
          {uploading && (
            <div className="import-status">
              <span className="spinner" /> Uploading photo…
            </div>
          )}

          <div className="dish-photo-options">
            <button
              type="button"
              className="dish-photo-btn"
              onClick={() => fileRef.current?.click()}
              disabled={uploading}
            >
              <IconCamera size={24} stroke={1.3} />
              <span>Take / upload a photo</span>
            </button>
            <button
              type="button"
              className="ghost-btn big dish-photo-skip"
              onClick={() => onDone(null)}
              disabled={uploading}
            >
              Skip for now
            </button>
          </div>

          <input ref={fileRef} type="file" accept="image/*" capture="environment" hidden onChange={handleFile} />
        </div>
      </div>
    </>
  );
}

Object.assign(window, { RecipeForm, ImportUrlModal, ScanModal, DishPhotoModal, parseIngredientsText, parseStepsText });
