/**
 * Oveyo PWA — Page Producteur (V9.4)
 * 
 * Composants :
 *   - AccountTypeChoice : écran de choix initial (Boutique / Producteur / Coopérative)
 *   - ProducerRegisterForm : formulaire d'inscription producteur
 *   - ProducerDashboard : accueil producteur (profil + annonces)
 *   - NewListingForm : formulaire de publication d'annonce
 *   - ProducerView : composant routeur principal (orchestration)
 * 
 * Exposé : window.OveyoPages.ProducerView
 */

const LuPr = window.LucideReact || {};
const { Card: Cpr, Spinner: Sppr, EmptyState: ESpr, useFlash: uFpr, Sheet: ShPr } = window.OveyoUI;
const { api: apiPr } = window.OveyoState;

// ============================================================
// LISTE DES CULTURES (synchro avec backend producer_crops.py)
// ============================================================
const CROPS_BY_CATEGORY = {
  cereales:     { label: 'Céréales',     icon: '🌾', items: ['riz', 'mil', 'mais', 'sorgho', 'fonio'] },
  legumes:      { label: 'Légumes',      icon: '🥬', items: ['oignon', 'pomme-terre', 'tomate', 'carotte', 'chou', 'aubergine', 'navet', 'manioc', 'patate-douce', 'gombo', 'piment'] },
  fruits:       { label: 'Fruits',       icon: '🥭', items: ['mangue', 'papaye', 'banane', 'pasteque', 'melon', 'citron'] },
  legumineuses: { label: 'Légumineuses', icon: '🫘', items: ['arachide', 'niebe'] },
  elevage:      { label: 'Élevage',      icon: '🐄', items: ['boeuf', 'mouton', 'volaille', 'oeuf', 'lait'] },
  peche:        { label: 'Pêche',        icon: '🐟', items: ['poisson', 'poisson-fume', 'crevette'] },
};
const CROP_LABELS = {
  riz: 'Riz', mil: 'Mil', mais: 'Maïs', sorgho: 'Sorgho', fonio: 'Fonio',
  oignon: 'Oignon', 'pomme-terre': 'Pomme de terre', tomate: 'Tomate',
  carotte: 'Carotte', chou: 'Chou', aubergine: 'Aubergine', navet: 'Navet',
  manioc: 'Manioc', 'patate-douce': 'Patate douce', gombo: 'Gombo', piment: 'Piment',
  mangue: 'Mangue', papaye: 'Papaye', banane: 'Banane', pasteque: 'Pastèque',
  melon: 'Melon', citron: 'Citron',
  arachide: 'Arachide', niebe: 'Niébé',
  boeuf: 'Bétail', mouton: 'Mouton', volaille: 'Volaille', oeuf: 'Œufs', lait: 'Lait',
  poisson: 'Poisson frais', 'poisson-fume': 'Poisson fumé', crevette: 'Crevette',
};

// ============================================================
// AccountTypeChoice — Écran initial : quel type de compte ?
// ============================================================
const AccountTypeChoice = ({ onSelect, onBack }) => {
  const { ChevronLeft, Store, Wheat, Users } = LuPr;
  
  const types = [
    { id: 'shop',        icon: Store, color: '#F4632B', bgColor: '#FFF1E9',
      title: 'Boutique',
      desc: 'Tu tiens une boutique de quartier, station-service ou enseigne.' },
    { id: 'producer',    icon: Wheat, color: '#15803D', bgColor: '#E8F5E9',
      title: 'Producteur',
      desc: 'Tu cultives, élèves ou produis pour vendre en gros.' },
    { id: 'cooperative', icon: Users, color: '#7C3AED', bgColor: '#F3EBFF',
      title: 'Coopérative',
      desc: 'Vous êtes plusieurs producteurs regroupés.' },
  ];
  
  return (
    <div className="min-h-screen pb-24" style={{ background: '#FBFAF7' }}>
      {/* Header */}
      <div className="px-4 pt-4 pb-3 flex items-center gap-3" style={{ background: '#FFFFFF' }}>
        <button onClick={onBack} className="w-10 h-10 rounded-full flex items-center justify-center" style={{ background: '#F1F4F9' }}>
          <ChevronLeft size={20} />
        </button>
        <div>
          <div className="font-display font-bold text-lg">Espace Pro</div>
          <div className="text-xs text-slate">Choisis ton type de compte</div>
        </div>
      </div>
      
      {/* Hero */}
      <div className="px-4 pt-6 pb-4">
        <div className="font-display font-extrabold text-2xl text-ink leading-tight">
          Bienvenue 👋
        </div>
        <div className="text-sm text-slate mt-2 leading-relaxed">
          Pour activer ton espace, dis-nous quel type d'acteur tu es. Tu pourras toujours ajouter d'autres profils plus tard.
        </div>
      </div>
      
      {/* Cartes */}
      <div className="px-4 space-y-3">
        {types.map((t) => {
          const Icon = t.icon;
          return (
            <button
              key={t.id}
              onClick={() => onSelect(t.id)}
              className="w-full p-4 rounded-2xl text-left transition-all active:scale-[0.98]"
              style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
            >
              <div className="flex items-start gap-3">
                <div className="w-14 h-14 rounded-2xl flex items-center justify-center flex-shrink-0" style={{ background: t.bgColor }}>
                  <Icon size={26} style={{ color: t.color }} strokeWidth={2} />
                </div>
                <div className="flex-1 min-w-0">
                  <div className="font-display font-bold text-base text-ink">{t.title}</div>
                  <div className="text-xs mt-1 text-slate leading-relaxed">{t.desc}</div>
                </div>
              </div>
            </button>
          );
        })}
      </div>
      
      {/* Footer note */}
      <div className="px-4 mt-6">
        <div className="p-3 rounded-xl text-xs text-slate leading-relaxed" style={{ background: '#F1F4F9' }}>
          💡 Ton inscription est gratuite. Ton profil sera vérifié par notre équipe sous 48h pour activer le badge ✓.
        </div>
      </div>
    </div>
  );
};

// ============================================================
// CropPicker — Multi-select avec accordéon par catégorie + "Autre"
// ============================================================
const CropPicker = ({ value, onChange }) => {
  // value: { slugs: [...], others: [...] }
  const [expanded, setExpanded] = React.useState(null);
  const [otherInput, setOtherInput] = React.useState('');
  const { Plus, X } = LuPr;
  
  const slugs = value?.slugs || [];
  const others = value?.others || [];
  
  const toggleSlug = (slug) => {
    if (slugs.includes(slug)) {
      onChange({ slugs: slugs.filter((s) => s !== slug), others });
    } else {
      onChange({ slugs: [...slugs, slug], others });
    }
  };
  
  const addOther = () => {
    const t = otherInput.trim();
    if (!t || others.includes(t)) return;
    onChange({ slugs, others: [...others, t] });
    setOtherInput('');
  };
  
  const removeOther = (t) => {
    onChange({ slugs, others: others.filter((o) => o !== t) });
  };
  
  const totalSelected = slugs.length + others.length;
  
  return (
    <div className="space-y-2">
      <div className="flex items-center justify-between">
        <div className="text-xs font-bold text-slate uppercase tracking-wide">
          Tes productions
        </div>
        <div className="text-xs text-slate">
          {totalSelected > 0 ? `${totalSelected} sélectionné(s)` : 'Aucune sélection'}
        </div>
      </div>
      
      {/* Catégories */}
      {Object.entries(CROPS_BY_CATEGORY).map(([catSlug, cat]) => (
        <div key={catSlug} className="rounded-xl overflow-hidden" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
          <button
            type="button"
            onClick={() => setExpanded(expanded === catSlug ? null : catSlug)}
            className="w-full px-3 py-2.5 flex items-center justify-between text-left"
          >
            <div className="flex items-center gap-2">
              <span className="text-lg">{cat.icon}</span>
              <span className="font-bold text-sm text-ink">{cat.label}</span>
            </div>
            <span className="text-xs text-slate">
              {cat.items.filter((s) => slugs.includes(s)).length}/{cat.items.length}
            </span>
          </button>
          
          {expanded === catSlug && (
            <div className="px-3 pb-3 flex flex-wrap gap-1.5">
              {cat.items.map((slug) => {
                const sel = slugs.includes(slug);
                return (
                  <button
                    type="button"
                    key={slug}
                    onClick={() => toggleSlug(slug)}
                    className="px-3 py-1.5 rounded-full text-xs font-bold transition-all"
                    style={sel ? {
                      background: '#15803D', color: '#FFFFFF',
                    } : {
                      background: '#F1F4F9', color: '#0F1B36',
                    }}
                  >
                    {CROP_LABELS[slug] || slug}
                  </button>
                );
              })}
            </div>
          )}
        </div>
      ))}
      
      {/* Section "Autre" */}
      <div className="rounded-xl p-3" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
        <div className="text-xs font-bold text-slate uppercase tracking-wide mb-2">
          Autre (texte libre)
        </div>
        <div className="flex gap-2">
          <input
            type="text"
            value={otherInput}
            onChange={(e) => setOtherInput(e.target.value)}
            onKeyDown={(e) => e.key === 'Enter' && (e.preventDefault(), addOther())}
            placeholder="Ex: Kinkéliba, Bissap, Moringa..."
            maxLength={60}
            className="flex-1 px-3 py-2 rounded-lg text-sm"
            style={{ background: '#F1F4F9', border: 'none' }}
          />
          <button
            type="button"
            onClick={addOther}
            disabled={!otherInput.trim()}
            className="px-3 py-2 rounded-lg disabled:opacity-50"
            style={{ background: '#F4632B', color: '#FFFFFF' }}
          >
            <Plus size={18} />
          </button>
        </div>
        {others.length > 0 && (
          <div className="flex flex-wrap gap-1.5 mt-2">
            {others.map((t) => (
              <span key={t} className="inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-bold" style={{ background: '#FFF1E9', color: '#F4632B' }}>
                {t}
                <button type="button" onClick={() => removeOther(t)} className="hover:opacity-70">
                  <X size={12} />
                </button>
              </span>
            ))}
          </div>
        )}
      </div>
    </div>
  );
};


// ============================================================
// ProducerRegisterForm — Formulaire d'inscription producteur
// ============================================================
const ProducerRegisterForm = ({ token, accountType, onSuccess, onBack }) => {
  const { ChevronLeft, MapPin, Loader2, Wheat, Users } = LuPr;
  const flash = uFpr();
  
  const [busy, setBusy] = React.useState(false);
  const [form, setForm] = React.useState({
    name: '',
    region: '',
    village: '',
    lat: 14.6928,   // Dakar par défaut, l'utilisateur peut changer
    lng: -17.4467,
    crops: { slugs: [], others: [] },
    surface_hectares: '',
    description: '',
  });
  const [gpsLoading, setGpsLoading] = React.useState(false);
  
  const setField = (key, val) => setForm({ ...form, [key]: val });
  
  const detectGPS = () => {
    if (!navigator.geolocation) {
      flash.show('error', 'GPS non disponible sur ce téléphone');
      return;
    }
    setGpsLoading(true);
    navigator.geolocation.getCurrentPosition(
      (pos) => {
        setForm((f) => ({ ...f, lat: pos.coords.latitude, lng: pos.coords.longitude }));
        setGpsLoading(false);
        flash.show('success', 'Position détectée');
      },
      () => {
        setGpsLoading(false);
        flash.show('error', 'Impossible de détecter la position');
      },
      { enableHighAccuracy: true, timeout: 10000 }
    );
  };
  
  const submit = async () => {
    // Validation
    if (form.name.trim().length < 3) {
      flash.show('error', 'Le nom doit faire au moins 3 caractères');
      return;
    }
    if (form.region.trim().length < 2) {
      flash.show('error', 'Indique ta région');
      return;
    }
    if (form.crops.slugs.length + form.crops.others.length === 0) {
      flash.show('error', 'Sélectionne au moins une production');
      return;
    }
    
    setBusy(true);
    try {
      const allCrops = [...form.crops.slugs, ...form.crops.others];
      const payload = {
        name: form.name.trim(),
        region: form.region.trim(),
        village: form.village.trim() || null,
        lat: form.lat,
        lng: form.lng,
        crops: allCrops,
        surface_hectares: form.surface_hectares ? parseFloat(form.surface_hectares) : null,
        description: form.description.trim() || null,
        account_type: accountType,
      };
      
      const res = await apiPr('/api/pwa/merchant/producer/register', {
        method: 'POST',
        headers: { Authorization: 'Bearer ' + token },
        body: JSON.stringify(payload),
      });
      
      flash.show('success', 'Inscription réussie ✓');
      if (onSuccess) onSuccess(res);
    } catch (e) {
      const msg = String(e);
      if (msg.match(/409/)) {
        flash.show('error', 'Tu as déjà un profil — recharge la page');
      } else {
        flash.show('error', 'Erreur lors de l\'inscription');
      }
    } finally {
      setBusy(false);
    }
  };
  
  const Icon = accountType === 'cooperative' ? Users : Wheat;
  const accentColor = accountType === 'cooperative' ? '#7C3AED' : '#15803D';
  const accentBg = accountType === 'cooperative' ? '#F3EBFF' : '#E8F5E9';
  
  return (
    <div className="min-h-screen pb-24" style={{ background: '#FBFAF7' }}>
      {/* Header */}
      <div className="px-4 pt-4 pb-3 flex items-center gap-3 sticky top-0 z-10" style={{ background: '#FFFFFF', borderBottom: '1px solid #EAEEF4' }}>
        <button onClick={onBack} className="w-10 h-10 rounded-full flex items-center justify-center" style={{ background: '#F1F4F9' }}>
          <ChevronLeft size={20} />
        </button>
        <div className="flex-1 min-w-0">
          <div className="font-display font-bold text-base">
            {accountType === 'cooperative' ? 'Inscription Coopérative' : 'Inscription Producteur'}
          </div>
        </div>
        <div className="w-10 h-10 rounded-2xl flex items-center justify-center" style={{ background: accentBg }}>
          <Icon size={20} style={{ color: accentColor }} />
        </div>
      </div>
      
      <div className="px-4 pt-4 space-y-4">
        {/* Nom */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">
            Nom de l'exploitation *
          </label>
          <input
            type="text"
            value={form.name}
            onChange={(e) => setField('name', e.target.value)}
            placeholder={accountType === 'cooperative' ? "Ex: Coopérative Niayes" : "Ex: Ferme Diop & Fils"}
            maxLength={100}
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
        </div>
        
        {/* Région */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">
            Région *
          </label>
          <input
            type="text"
            value={form.region}
            onChange={(e) => setField('region', e.target.value)}
            placeholder="Ex: Diourbel, Kaolack, Saint-Louis..."
            maxLength={80}
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
        </div>
        
        {/* Village */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">
            Village / Commune
          </label>
          <input
            type="text"
            value={form.village}
            onChange={(e) => setField('village', e.target.value)}
            placeholder="Ex: Touba Mosquée, Mboro..."
            maxLength={80}
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
        </div>
        
        {/* GPS */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">
            Position GPS *
          </label>
          <button
            type="button"
            onClick={detectGPS}
            disabled={gpsLoading}
            className="w-full px-3 py-2.5 rounded-xl text-sm flex items-center justify-between"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          >
            <span className="flex items-center gap-2">
              <MapPin size={16} style={{ color: accentColor }} />
              <span className="text-ink">
                {form.lat.toFixed(4)}, {form.lng.toFixed(4)}
              </span>
            </span>
            <span className="text-xs font-bold" style={{ color: accentColor }}>
              {gpsLoading ? <Loader2 size={14} className="animate-spin" /> : 'Détecter'}
            </span>
          </button>
        </div>
        
        {/* Cultures */}
        <CropPicker
          value={form.crops}
          onChange={(v) => setField('crops', v)}
        />
        
        {/* Surface */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">
            Surface cultivée (hectares) — optionnel
          </label>
          <input
            type="number"
            step="0.1"
            min="0"
            value={form.surface_hectares}
            onChange={(e) => setField('surface_hectares', e.target.value)}
            placeholder="Ex: 5.5"
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
        </div>
        
        {/* Description */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">
            Présentation — optionnel
          </label>
          <textarea
            value={form.description}
            onChange={(e) => setField('description', e.target.value)}
            placeholder="Présente ton exploitation, tes méthodes, ton expérience..."
            maxLength={500}
            rows={4}
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
          <div className="text-[10px] text-slate mt-1 text-right">
            {form.description.length}/500
          </div>
        </div>
        
        {/* Submit */}
        <button
          onClick={submit}
          disabled={busy}
          className="w-full py-3.5 rounded-xl font-display font-bold text-white text-sm flex items-center justify-center gap-2 disabled:opacity-60"
          style={{ background: accentColor }}
        >
          {busy && <Loader2 size={16} className="animate-spin" />}
          Créer mon profil
        </button>
        
        <div className="text-[11px] text-slate text-center pt-2 leading-relaxed">
          Ton profil sera vérifié par notre équipe sous 48h.<br/>
          Le badge ✓ sera ajouté après validation.
        </div>
      </div>
    </div>
  );
};


// ============================================================
// NewListingForm — Formulaire de création d'annonce
// ============================================================
const NewListingForm = ({ token, accentColor, onSuccess, onCancel }) => {
  const { ChevronLeft, Loader2, Package } = LuPr;
  const flash = uFpr();
  const [busy, setBusy] = React.useState(false);
  const [form, setForm] = React.useState({
    product_name: '',
    variety: '',
    unit: 'sac',
    unit_weight_kg: 25,
    price_per_unit: '',
    quantity_available: '',
    quantity_min_order: 1,
    pickup_location: '',
    available_from: '',
    available_to: '',
    delivery_possible: false,
    delivery_max_km: '',
    delivery_extra_cost: 0,
    caution_percent: 20,
    notes: '',
  });
  
  const setField = (key, val) => setForm({ ...form, [key]: val });
  
  const submit = async () => {
    if (form.product_name.trim().length < 2) {
      flash.show('error', 'Indique le nom du produit');
      return;
    }
    if (!form.price_per_unit || parseFloat(form.price_per_unit) <= 0) {
      flash.show('error', 'Indique le prix');
      return;
    }
    if (!form.quantity_available || parseFloat(form.quantity_available) <= 0) {
      flash.show('error', 'Indique la quantité disponible');
      return;
    }
    
    setBusy(true);
    try {
      const payload = {
        product_name: form.product_name.trim(),
        variety: form.variety.trim() || null,
        unit: form.unit,
        unit_weight_kg: form.unit_weight_kg ? parseFloat(form.unit_weight_kg) : null,
        price_per_unit: parseFloat(form.price_per_unit),
        quantity_available: parseFloat(form.quantity_available),
        quantity_min_order: parseFloat(form.quantity_min_order) || 1,
        pickup_location: form.pickup_location.trim() || null,
        available_from: form.available_from || null,
        available_to: form.available_to || null,
        delivery_possible: form.delivery_possible,
        delivery_max_km: form.delivery_max_km ? parseInt(form.delivery_max_km) : null,
        delivery_extra_cost: parseFloat(form.delivery_extra_cost) || 0,
        caution_percent: parseFloat(form.caution_percent) || 20,
        notes: form.notes.trim() || null,
      };
      
      const res = await apiPr('/api/pwa/merchant/producer/listings', {
        method: 'POST',
        headers: { Authorization: 'Bearer ' + token },
        body: JSON.stringify(payload),
      });
      
      flash.show('success', 'Annonce publiée ✓');
      if (onSuccess) onSuccess(res);
    } catch (e) {
      flash.show('error', 'Erreur lors de la publication');
    } finally {
      setBusy(false);
    }
  };
  
  return (
    <div className="min-h-screen pb-24" style={{ background: '#FBFAF7' }}>
      {/* Header */}
      <div className="px-4 pt-4 pb-3 flex items-center gap-3 sticky top-0 z-10" style={{ background: '#FFFFFF', borderBottom: '1px solid #EAEEF4' }}>
        <button onClick={onCancel} className="w-10 h-10 rounded-full flex items-center justify-center" style={{ background: '#F1F4F9' }}>
          <ChevronLeft size={20} />
        </button>
        <div className="flex-1 min-w-0">
          <div className="font-display font-bold text-base">Nouvelle annonce</div>
          <div className="text-xs text-slate">Publier une disponibilité</div>
        </div>
      </div>
      
      <div className="px-4 pt-4 space-y-3">
        {/* Produit */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Produit *</label>
          <input
            type="text"
            value={form.product_name}
            onChange={(e) => setField('product_name', e.target.value)}
            placeholder="Ex: Oignon, Riz, Tomate, Mil..."
            maxLength={80}
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
        </div>
        
        {/* Variété */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Variété — optionnel</label>
          <input
            type="text"
            value={form.variety}
            onChange={(e) => setField('variety', e.target.value)}
            placeholder="Ex: Galmi, Bombay, Roma..."
            maxLength={60}
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
        </div>
        
        {/* Unité + poids */}
        <div className="grid grid-cols-2 gap-2">
          <div>
            <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Unité *</label>
            <select
              value={form.unit}
              onChange={(e) => setField('unit', e.target.value)}
              className="w-full px-3 py-2.5 rounded-xl text-sm"
              style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
            >
              <option value="sac">Sac</option>
              <option value="kg">Kilogramme</option>
              <option value="caisse">Caisse</option>
              <option value="botte">Botte</option>
              <option value="piece">Pièce</option>
              <option value="litre">Litre</option>
            </select>
          </div>
          {form.unit !== 'kg' && (
            <div>
              <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Poids (kg)</label>
              <input
                type="number"
                step="0.1"
                value={form.unit_weight_kg}
                onChange={(e) => setField('unit_weight_kg', e.target.value)}
                placeholder="25"
                className="w-full px-3 py-2.5 rounded-xl text-sm"
                style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
              />
            </div>
          )}
        </div>
        
        {/* Prix + Quantité dispo */}
        <div className="grid grid-cols-2 gap-2">
          <div>
            <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Prix unité (F) *</label>
            <input
              type="number"
              min="1"
              value={form.price_per_unit}
              onChange={(e) => setField('price_per_unit', e.target.value)}
              placeholder="18000"
              className="w-full px-3 py-2.5 rounded-xl text-sm"
              style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
            />
          </div>
          <div>
            <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Qté dispo *</label>
            <input
              type="number"
              min="0.1"
              step="0.1"
              value={form.quantity_available}
              onChange={(e) => setField('quantity_available', e.target.value)}
              placeholder="50"
              className="w-full px-3 py-2.5 rounded-xl text-sm"
              style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
            />
          </div>
        </div>
        
        {/* Min order */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Commande minimum</label>
          <input
            type="number"
            min="1"
            value={form.quantity_min_order}
            onChange={(e) => setField('quantity_min_order', e.target.value)}
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
        </div>
        
        {/* Lieu retrait */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Lieu de retrait</label>
          <input
            type="text"
            value={form.pickup_location}
            onChange={(e) => setField('pickup_location', e.target.value)}
            placeholder="Ex: Champ à 3km de Touba"
            maxLength={200}
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
        </div>
        
        {/* Dates */}
        <div className="grid grid-cols-2 gap-2">
          <div>
            <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Dispo dès</label>
            <input
              type="date"
              value={form.available_from}
              onChange={(e) => setField('available_from', e.target.value)}
              className="w-full px-3 py-2.5 rounded-xl text-sm"
              style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
            />
          </div>
          <div>
            <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Jusqu'au</label>
            <input
              type="date"
              value={form.available_to}
              onChange={(e) => setField('available_to', e.target.value)}
              className="w-full px-3 py-2.5 rounded-xl text-sm"
              style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
            />
          </div>
        </div>
        
        {/* Livraison */}
        <div className="rounded-xl p-3" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
          <label className="flex items-center gap-2 cursor-pointer">
            <input
              type="checkbox"
              checked={form.delivery_possible}
              onChange={(e) => setField('delivery_possible', e.target.checked)}
            />
            <span className="text-sm font-bold">Livraison possible</span>
          </label>
          {form.delivery_possible && (
            <div className="grid grid-cols-2 gap-2 mt-3">
              <div>
                <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Distance max (km)</label>
                <input
                  type="number"
                  value={form.delivery_max_km}
                  onChange={(e) => setField('delivery_max_km', e.target.value)}
                  placeholder="50"
                  className="w-full px-3 py-2 rounded-lg text-sm"
                  style={{ background: '#F1F4F9', border: 'none' }}
                />
              </div>
              <div>
                <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Frais (F)</label>
                <input
                  type="number"
                  value={form.delivery_extra_cost}
                  onChange={(e) => setField('delivery_extra_cost', e.target.value)}
                  className="w-full px-3 py-2 rounded-lg text-sm"
                  style={{ background: '#F1F4F9', border: 'none' }}
                />
              </div>
            </div>
          )}
        </div>
        
        {/* Caution */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">
            Caution exigée (%) — pour précommande
          </label>
          <input
            type="number"
            min="0"
            max="100"
            value={form.caution_percent}
            onChange={(e) => setField('caution_percent', e.target.value)}
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
          <div className="text-[10px] text-slate mt-1">
            0% = pas de caution requise. 20% = standard recommandé.
          </div>
        </div>
        
        {/* Notes */}
        <div>
          <label className="text-xs font-bold text-slate uppercase tracking-wide mb-1.5 block">Notes — optionnel</label>
          <textarea
            value={form.notes}
            onChange={(e) => setField('notes', e.target.value)}
            placeholder="Récolte fraîche, qualité, conditions de visite..."
            maxLength={500}
            rows={3}
            className="w-full px-3 py-2.5 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
          />
        </div>
        
        <button
          onClick={submit}
          disabled={busy}
          className="w-full py-3.5 rounded-xl font-display font-bold text-white text-sm flex items-center justify-center gap-2 disabled:opacity-60"
          style={{ background: accentColor }}
        >
          {busy && <Loader2 size={16} className="animate-spin" />}
          Publier l'annonce
        </button>
      </div>
    </div>
  );
};


// ============================================================
// ProducerDashboard — Vue principale producteur (profil + annonces)
// ============================================================
const ProducerDashboard = ({ state, token, onBack, onLogout }) => {
  const { ChevronLeft, Plus, MapPin, Package, Eye, Users2, Trash2, Loader2, Wheat, ShieldCheck } = LuPr;
  const flash = uFpr();
  
  const [profile, setProfile] = React.useState(null);
  const [listings, setListings] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [showNewForm, setShowNewForm] = React.useState(false);
  
  const isCoop = profile?.shop_type === 'cooperative';
  const accentColor = isCoop ? '#7C3AED' : '#15803D';
  const accentBg = isCoop ? '#F3EBFF' : '#E8F5E9';
  
  const fetchData = React.useCallback(async () => {
    if (!token) return;
    setLoading(true);
    try {
      const [pRes, lRes] = await Promise.all([
        apiPr('/api/pwa/merchant/producer/profile', {
          headers: { Authorization: 'Bearer ' + token },
        }),
        apiPr('/api/pwa/merchant/producer/listings?status=active', {
          headers: { Authorization: 'Bearer ' + token },
        }),
      ]);
      setProfile(pRes);
      setListings(lRes.listings || []);
    } catch (e) {
      console.error('Producer dashboard fetch:', e);
    } finally {
      setLoading(false);
    }
  }, [token]);
  
  React.useEffect(() => { fetchData(); }, [fetchData]);
  
  const deleteListing = async (id) => {
    if (!confirm('Supprimer cette annonce ?')) return;
    try {
      await apiPr(`/api/pwa/merchant/producer/listings/${id}`, {
        method: 'DELETE',
        headers: { Authorization: 'Bearer ' + token },
      });
      flash.show('success', 'Annonce supprimée');
      fetchData();
    } catch {
      flash.show('error', 'Erreur');
    }
  };
  
  if (showNewForm) {
    return (
      <NewListingForm
        token={token}
        accentColor={accentColor}
        onSuccess={() => { setShowNewForm(false); fetchData(); }}
        onCancel={() => setShowNewForm(false)}
      />
    );
  }
  
  if (loading) {
    return (
      <div className="min-h-screen flex items-center justify-center" style={{ background: '#FBFAF7' }}>
        <Sppr />
      </div>
    );
  }
  
  if (!profile) {
    return (
      <div className="min-h-screen p-4" style={{ background: '#FBFAF7' }}>
        <button onClick={onBack} className="text-sm" style={{ color: accentColor }}>← Retour</button>
        <div className="mt-8 text-center text-slate">Profil introuvable</div>
      </div>
    );
  }
  
  const cropsCount = (profile.crops?.slugs?.length || 0) + (profile.crops?.others?.length || 0);
  
  return (
    <div className="min-h-screen pb-24" style={{ background: '#FBFAF7' }}>
      {/* Header */}
      <div className="px-4 pt-4 pb-3 flex items-center gap-3" style={{ background: '#FFFFFF', borderBottom: '1px solid #EAEEF4' }}>
        <button onClick={onBack} className="w-10 h-10 rounded-full flex items-center justify-center" style={{ background: '#F1F4F9' }}>
          <ChevronLeft size={20} />
        </button>
        <div className="flex-1 min-w-0">
          <div className="font-display font-bold text-base truncate flex items-center gap-1.5">
            {profile.name}
            {profile.verified && <ShieldCheck size={14} style={{ color: accentColor }} />}
          </div>
          <div className="text-xs text-slate">
            {isCoop ? 'Coopérative' : 'Producteur'} · {profile.region}
            {profile.village ? ` · ${profile.village}` : ''}
          </div>
        </div>
        <div className="w-10 h-10 rounded-2xl flex items-center justify-center" style={{ background: accentBg }}>
          <Wheat size={20} style={{ color: accentColor }} />
        </div>
      </div>
      
      {/* Badge vérif */}
      {!profile.verified && (
        <div className="mx-4 mt-3 p-3 rounded-xl text-xs leading-relaxed" style={{ background: '#FFF8E1', color: '#92400E' }}>
          ⏳ Profil en cours de vérification (48h max). Tu peux déjà publier tes annonces.
        </div>
      )}
      
      {/* Stats */}
      <div className="px-4 mt-3 grid grid-cols-3 gap-2">
        <div className="rounded-xl p-3 text-center" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
          <Package size={18} className="mx-auto" style={{ color: accentColor }} />
          <div className="font-display font-extrabold text-lg text-ink mt-1">{listings.length}</div>
          <div className="text-[10px] text-slate uppercase tracking-wide">Annonces</div>
        </div>
        <div className="rounded-xl p-3 text-center" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
          <Wheat size={18} className="mx-auto" style={{ color: accentColor }} />
          <div className="font-display font-extrabold text-lg text-ink mt-1">{cropsCount}</div>
          <div className="text-[10px] text-slate uppercase tracking-wide">Cultures</div>
        </div>
        <div className="rounded-xl p-3 text-center" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
          <Eye size={18} className="mx-auto" style={{ color: accentColor }} />
          <div className="font-display font-extrabold text-lg text-ink mt-1">
            {listings.reduce((s, l) => s + (l.views_count || 0), 0)}
          </div>
          <div className="text-[10px] text-slate uppercase tracking-wide">Vues</div>
        </div>
      </div>
      
      {/* Bouton nouvelle annonce */}
      <div className="px-4 mt-4">
        <button
          onClick={() => setShowNewForm(true)}
          className="w-full py-3 rounded-xl font-display font-bold text-white text-sm flex items-center justify-center gap-2"
          style={{ background: accentColor }}
        >
          <Plus size={18} />
          Publier une nouvelle annonce
        </button>
      </div>
      
      {/* Liste annonces */}
      <div className="px-4 mt-4">
        <div className="text-xs font-bold text-slate uppercase tracking-wide mb-2">
          Mes annonces actives
        </div>
        
        {listings.length === 0 ? (
          <div className="rounded-xl p-6 text-center" style={{ background: '#FFFFFF', border: '1px dashed #CBD5E1' }}>
            <Package size={32} className="mx-auto text-slate" />
            <div className="text-sm font-bold text-ink mt-2">Aucune annonce</div>
            <div className="text-xs text-slate mt-1">Publie ta première disponibilité ci-dessus</div>
          </div>
        ) : (
          <div className="space-y-2">
            {listings.map((l) => (
              <div key={l.id} className="rounded-xl p-3" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
                <div className="flex items-start justify-between gap-2">
                  <div className="flex-1 min-w-0">
                    <div className="font-display font-bold text-sm text-ink">
                      {l.product_name}
                      {l.variety ? <span className="text-xs text-slate font-normal"> · {l.variety}</span> : null}
                    </div>
                    <div className="text-xs text-slate mt-1">
                      {l.quantity_remaining}/{l.quantity_available} {l.unit}(s) · {Math.round(l.price_per_unit).toLocaleString('fr-FR')} F/{l.unit}
                    </div>
                    {l.pickup_location && (
                      <div className="text-[11px] text-slate mt-1 flex items-center gap-1">
                        <MapPin size={11} />
                        {l.pickup_location}
                      </div>
                    )}
                  </div>
                  <button
                    onClick={() => deleteListing(l.id)}
                    className="w-9 h-9 rounded-lg flex items-center justify-center"
                    style={{ background: '#FFF1F2', color: '#E11D48' }}
                  >
                    <Trash2 size={14} />
                  </button>
                </div>
                <div className="flex items-center gap-3 mt-2 pt-2 text-[11px] text-slate" style={{ borderTop: '1px solid #F1F4F9' }}>
                  <span className="flex items-center gap-1"><Eye size={11} /> {l.views_count || 0}</span>
                  <span className="flex items-center gap-1"><Users2 size={11} /> {l.contact_clicks || 0} contacts</span>
                  {l.available_to && (
                    <span className="ml-auto">jusqu'au {l.available_to}</span>
                  )}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
};


// ============================================================
// ProducerView — Routeur principal (orchestre les écrans)
// ============================================================
const ProducerHubView = ({ state, setState, onBack, onOpenSheet }) => {
  const flash = uFpr();
  const token = state.user?.session_token;
  
  const [step, setStep] = React.useState('loading'); // loading | choice | register | dashboard
  const [chosenType, setChosenType] = React.useState(null);
  
  const checkAccountType = React.useCallback(async () => {
    if (!token) {
      setStep('not_logged_in');
      return;
    }
    try {
      const r = await apiPr('/api/pwa/merchant/account-type', {
        headers: { Authorization: 'Bearer ' + token },
      });
      const t = r.account_type;
      if (t === 'producer' || t === 'cooperative') {
        setStep('dashboard');
      } else if (t === 'shop') {
        // Pas notre vue — laisse le MerchantView gérer
        setStep('shop_redirect');
        if (onBack) onBack();
      } else {
        // null → choix initial
        setStep('choice');
      }
    } catch (e) {
      console.error('Account type fetch:', e);
      setStep('error');
    }
  }, [token, onBack]);
  
  React.useEffect(() => { checkAccountType(); }, [checkAccountType]);
  
  if (step === 'loading') {
    return (
      <div className="min-h-screen flex items-center justify-center" style={{ background: '#FBFAF7' }}>
        <Sppr />
      </div>
    );
  }
  
  if (step === 'not_logged_in') {
    return (
      <div className="min-h-screen p-4 flex flex-col items-center justify-center text-center" style={{ background: '#FBFAF7' }}>
        <div className="text-base font-bold text-ink">Connecte-toi d'abord</div>
        <div className="text-xs text-slate mt-2 mb-4">L'espace pro nécessite une session active</div>
        <button onClick={onBack} className="px-4 py-2 rounded-xl text-sm font-bold text-white" style={{ background: '#F4632B' }}>
          Retour
        </button>
      </div>
    );
  }
  
  if (step === 'error') {
    return (
      <div className="min-h-screen p-4 flex flex-col items-center justify-center" style={{ background: '#FBFAF7' }}>
        <div className="text-sm text-slate">Erreur — recharge la page</div>
      </div>
    );
  }
  
  if (step === 'choice') {
    return (
      <AccountTypeChoice
        onBack={onBack}
        onSelect={(type) => {
          if (type === 'shop') {
            // Pour les boutiques : retour pour utiliser le flow merchant_me classique
            flash.show('info', 'Pour les boutiques, réclame ta boutique depuis la Carte');
            onBack();
            return;
          }
          setChosenType(type);
          setStep('register');
        }}
      />
    );
  }
  
  if (step === 'register') {
    return (
      <ProducerRegisterForm
        token={token}
        accountType={chosenType}
        onBack={() => setStep('choice')}
        onSuccess={() => setStep('dashboard')}
      />
    );
  }
  
  if (step === 'dashboard') {
    return (
      <ProducerDashboard
        state={state}
        token={token}
        onBack={onBack}
      />
    );
  }
  
  return null;
};


// ============================================================
// EXPORT — expose au reste de l'app
// ============================================================
window.OveyoPages = window.OveyoPages || {};
window.OveyoPages.ProducerHubView = ProducerHubView;


// ============================================================
// V9.4 Phase 1 — PRODUCTEUR CÔTÉ ACHETEUR
// ============================================================
// Composants ajoutés :
//   - ListingCard          : carte d'annonce réutilisable
//   - ListingDetailSheet   : sheet plein écran au clic d'une annonce
//   - ProducerAcheteurPage : écran principal de l'onglet "Producteur"
//   - ProducerView         : routeur (acheteur si onglet, hub si Espace Pro)
// ============================================================

// Helpers d'affichage
const _formatCFA = (n) => {
  if (!n && n !== 0) return '—';
  return Math.round(n).toLocaleString('fr-FR') + ' F';
};

const _formatDistance = (lat1, lng1, lat2, lng2) => {
  if (!lat1 || !lng1 || !lat2 || !lng2) return null;
  const R = 6371;
  const dLat = (lat2 - lat1) * Math.PI / 180;
  const dLng = (lng2 - lng1) * Math.PI / 180;
  const a = Math.sin(dLat/2)**2 + Math.cos(lat1*Math.PI/180)*Math.cos(lat2*Math.PI/180)*Math.sin(dLng/2)**2;
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  return Math.round(R * c);
};

// Icônes selon produit (best effort)
const _productIcon = (name) => {
  if (!name) return '📦';
  const n = name.toLowerCase();
  if (n.includes('oignon')) return '🧅';
  if (n.includes('tomate')) return '🍅';
  if (n.includes('riz')) return '🌾';
  if (n.includes('mil') || n.includes('sorgho')) return '🌾';
  if (n.includes('mais')) return '🌽';
  if (n.includes('mangue')) return '🥭';
  if (n.includes('papaye')) return '🥭';
  if (n.includes('banane')) return '🍌';
  if (n.includes('pasteq') || n.includes('pastèq') || n.includes('melon')) return '🍉';
  if (n.includes('citron')) return '🍋';
  if (n.includes('carotte')) return '🥕';
  if (n.includes('pomme de terre') || n.includes('patate')) return '🥔';
  if (n.includes('chou')) return '🥬';
  if (n.includes('piment')) return '🌶️';
  if (n.includes('arachide') || n.includes('niebe') || n.includes('niébé')) return '🥜';
  if (n.includes('boeuf') || n.includes('bœuf') || n.includes('mouton')) return '🐄';
  if (n.includes('volaille') || n.includes('oeuf')) return '🐔';
  if (n.includes('poisson') || n.includes('crevette')) return '🐟';
  if (n.includes('lait')) return '🥛';
  return '📦';
};


// ============================================================
// ListingCard — Carte d'annonce (verticale, format liste)
// ============================================================
const ListingCard = ({ listing, onOpen, userLat, userLng }) => {
  const { MapPin, ShieldCheck, Package, Truck } = LuPr;
  
  const distance = _formatDistance(userLat, userLng, listing.pickup_lat || null, listing.pickup_lng || null);
  const icon = _productIcon(listing.product_name);
  
  return (
    <button
      onClick={() => onOpen(listing)}
      className="w-full p-3 rounded-2xl text-left active:scale-[0.98] transition-transform"
      style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
    >
      <div className="flex items-start gap-3">
        {/* Icône produit */}
        <div className="w-14 h-14 rounded-xl flex items-center justify-center flex-shrink-0 text-3xl"
             style={{ background: '#E8F5E9' }}>
          {icon}
        </div>
        
        {/* Contenu */}
        <div className="flex-1 min-w-0">
          {/* Titre + variété */}
          <div className="font-display font-bold text-sm text-ink leading-tight">
            {listing.product_name}
            {listing.variety && (
              <span className="font-normal text-slate text-xs"> · {listing.variety}</span>
            )}
          </div>
          
          {/* Prix */}
          <div className="mt-1 flex items-baseline gap-1">
            <span className="font-display font-extrabold text-lg" style={{ color: '#15803D' }}>
              {_formatCFA(listing.price_per_unit)}
            </span>
            <span className="text-xs text-slate">/{listing.unit}</span>
            {listing.unit_weight_kg && (
              <span className="text-xs text-slate">({listing.unit_weight_kg} kg)</span>
            )}
          </div>
          
          {/* Producteur */}
          <div className="text-xs text-slate mt-1 flex items-center gap-1">
            <span className="font-bold text-ink truncate">{listing.producer_name}</span>
            {listing.producer_verified && <ShieldCheck size={11} style={{ color: '#15803D' }} />}
          </div>
          
          {/* Localisation + distance */}
          <div className="text-[11px] text-slate mt-0.5 flex items-center gap-1">
            <MapPin size={10} />
            <span className="truncate">
              {listing.producer_region}
              {listing.producer_village ? ` · ${listing.producer_village}` : ''}
              {distance !== null && ` · ${distance} km`}
            </span>
          </div>
          
          {/* Badges qté + livraison */}
          <div className="flex flex-wrap items-center gap-1.5 mt-2">
            <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-bold"
                  style={{ background: '#F1F4F9', color: '#0F1B36' }}>
              <Package size={10} />
              {listing.quantity_remaining || listing.quantity_available} {listing.unit}(s)
            </span>
            {listing.delivery_possible && (
              <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-bold"
                    style={{ background: '#FFF1E9', color: '#F4632B' }}>
                <Truck size={10} />
                Livraison
              </span>
            )}
          </div>
        </div>
      </div>
    </button>
  );
};


// ============================================================
// ListingCardCompact — Variante horizontale (pour scroll horizontal)
// ============================================================
const ListingCardCompact = ({ listing, onOpen }) => {
  const { ShieldCheck } = LuPr;
  const icon = _productIcon(listing.product_name);
  
  return (
    <button
      onClick={() => onOpen(listing)}
      className="flex-shrink-0 w-44 p-3 rounded-2xl text-left active:scale-[0.98]"
      style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}
    >
      <div className="w-full h-20 rounded-xl flex items-center justify-center text-4xl mb-2"
           style={{ background: '#E8F5E9' }}>
        {icon}
      </div>
      <div className="font-display font-bold text-sm text-ink truncate">
        {listing.product_name}
      </div>
      <div className="font-display font-extrabold text-base mt-0.5" style={{ color: '#15803D' }}>
        {_formatCFA(listing.price_per_unit)}<span className="text-[10px] font-normal text-slate">/{listing.unit}</span>
      </div>
      <div className="text-[10px] text-slate mt-1 flex items-center gap-0.5 truncate">
        <span className="truncate">{listing.producer_name}</span>
        {listing.producer_verified && <ShieldCheck size={9} style={{ color: '#15803D' }} />}
      </div>
      <div className="text-[10px] text-slate truncate">
        {listing.producer_region}
      </div>
    </button>
  );
};


// ============================================================
// ListingDetailSheet — Détail d'une annonce (plein écran)
// ============================================================
const ListingDetailSheet = ({ listing, open, onClose, token }) => {
  const { MapPin, ShieldCheck, Package, Truck, MessageCircle, Calendar, Loader2 } = LuPr;
  const flash = uFpr();
  
  const [detail, setDetail] = React.useState(null);
  const [contactLoading, setContactLoading] = React.useState(false);
  
  // Fetch détail enrichi quand le sheet s'ouvre
  React.useEffect(() => {
    if (!open || !listing) {
      setDetail(null);
      return;
    }
    apiPr(`/api/pwa/listings/${listing.id}`)
      .then((r) => setDetail(r))
      .catch(() => setDetail(listing)); // fallback sur ce qu'on a déjà
  }, [open, listing]);
  
  const requestContact = async () => {
    if (contactLoading || !listing) return;
    setContactLoading(true);
    try {
      const r = await apiPr(`/api/pwa/listings/${listing.id}/contact`, { method: 'POST' });
      if (r.wa_me_link) {
        window.open(r.wa_me_link, '_blank', 'noopener');
      } else {
        flash.show('error', "Numéro de contact indisponible");
      }
    } catch (e) {
      flash.show('error', "Impossible de récupérer le contact");
    } finally {
      setContactLoading(false);
    }
  };
  
  if (!open || !listing) return null;
  
  const l = detail || listing;
  const icon = _productIcon(l.product_name);
  
  return (
    <ShPr open={open} onClose={onClose} title={l.product_name}>
      <div className="space-y-3">
        {/* Icône produit en grand */}
        <div className="w-full h-36 rounded-2xl flex items-center justify-center"
             style={{ background: '#E8F5E9' }}>
          <span style={{ fontSize: '88px', lineHeight: 1 }}>{icon}</span>
        </div>
        
        {/* Prix */}
        <div className="rounded-2xl p-4" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
          <div className="text-xs font-bold text-slate uppercase tracking-wide">Prix</div>
          <div className="flex items-baseline gap-1 mt-1">
            <span className="font-display font-extrabold text-3xl" style={{ color: '#15803D' }}>
              {_formatCFA(l.price_per_unit)}
            </span>
            <span className="text-base text-slate">/{l.unit}</span>
          </div>
          {l.unit_weight_kg && (
            <div className="text-xs text-slate mt-1">
              1 {l.unit} = {l.unit_weight_kg} kg
              {' · '}{_formatCFA(l.price_per_unit / l.unit_weight_kg)}/kg
            </div>
          )}
          {l.quantity_min_order > 1 && (
            <div className="text-xs text-slate mt-2 inline-block px-2 py-1 rounded-full" style={{ background: '#F1F4F9' }}>
              Commande minimum : {l.quantity_min_order} {l.unit}(s)
            </div>
          )}
        </div>
        
        {/* Producteur */}
        <div className="rounded-2xl p-4" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
          <div className="text-xs font-bold text-slate uppercase tracking-wide mb-2">Producteur</div>
          <div className="flex items-center gap-2">
            <div className="font-display font-bold text-base text-ink">{l.producer_name}</div>
            {l.producer_verified && <ShieldCheck size={16} style={{ color: '#15803D' }} />}
          </div>
          <div className="text-sm text-slate mt-1 flex items-center gap-1">
            <MapPin size={12} />
            {l.producer_region}
            {l.producer_village ? ` · ${l.producer_village}` : ''}
          </div>
          {l.producer_description && (
            <div className="text-xs text-slate mt-2 leading-relaxed">
              {l.producer_description}
            </div>
          )}
        </div>
        
        {/* Disponibilité */}
        <div className="rounded-2xl p-4" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
          <div className="text-xs font-bold text-slate uppercase tracking-wide mb-2">Disponibilité</div>
          <div className="flex items-center gap-2 text-sm">
            <Package size={14} style={{ color: '#15803D' }} />
            <span className="font-bold">{l.quantity_remaining || l.quantity_available}</span>
            <span className="text-slate">{l.unit}(s) disponibles</span>
          </div>
          {(l.available_from || l.available_to) && (
            <div className="flex items-center gap-2 text-sm mt-2">
              <Calendar size={14} style={{ color: '#15803D' }} />
              <span className="text-slate">
                {l.available_from && `Du ${l.available_from}`}
                {l.available_from && l.available_to && ' '}
                {l.available_to && `au ${l.available_to}`}
              </span>
            </div>
          )}
        </div>
        
        {/* Livraison */}
        {l.delivery_possible && (
          <div className="rounded-2xl p-4" style={{ background: '#FFF1E9', border: '1px solid #FFD7BD' }}>
            <div className="flex items-center gap-2">
              <Truck size={16} style={{ color: '#F4632B' }} />
              <span className="font-bold text-sm" style={{ color: '#F4632B' }}>
                Livraison possible
              </span>
            </div>
            <div className="text-xs text-slate mt-1">
              {l.delivery_max_km && `Distance max : ${l.delivery_max_km} km`}
              {l.delivery_extra_cost > 0 && ` · Frais : ${_formatCFA(l.delivery_extra_cost)}`}
            </div>
          </div>
        )}
        
        {/* Lieu retrait */}
        {l.pickup_location && (
          <div className="rounded-2xl p-4" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
            <div className="text-xs font-bold text-slate uppercase tracking-wide mb-2">Lieu de retrait</div>
            <div className="text-sm text-ink flex items-start gap-2">
              <MapPin size={14} className="mt-0.5 flex-shrink-0" style={{ color: '#15803D' }} />
              <span>{l.pickup_location}</span>
            </div>
          </div>
        )}
        
        {/* Notes du producteur */}
        {l.notes && (
          <div className="rounded-2xl p-4" style={{ background: '#FFFFFF', border: '1px solid #EAEEF4' }}>
            <div className="text-xs font-bold text-slate uppercase tracking-wide mb-2">Notes du producteur</div>
            <div className="text-sm text-ink leading-relaxed">{l.notes}</div>
          </div>
        )}
        
        {/* Caution info */}
        {l.caution_percent > 0 && (
          <div className="rounded-xl p-3" style={{ background: '#F1F4F9' }}>
            <div className="text-xs text-slate leading-relaxed">
              💳 Pour précommander, une caution de {l.caution_percent}% sera demandée
              (système de paiement en cours d'intégration).
            </div>
          </div>
        )}
        
        {/* Actions (intégrées au flux, pas en sticky) */}
        <div className="pt-2 space-y-2">
          <button
            onClick={requestContact}
            disabled={contactLoading}
            className="w-full py-3.5 rounded-xl font-display font-bold text-white text-sm flex items-center justify-center gap-2 disabled:opacity-60"
            style={{ background: '#15803D' }}
          >
            {contactLoading && <Loader2 size={16} className="animate-spin" />}
            {!contactLoading && <MessageCircle size={16} />}
            Contacter via WhatsApp
          </button>
          <button
            disabled
            className="w-full py-3 rounded-xl font-bold text-sm opacity-50 cursor-not-allowed"
            style={{ background: '#F1F4F9', color: '#0F1B36' }}
          >
            Précommander avec caution — Bientôt
          </button>
        </div>
      </div>
    </ShPr>
  );
};

// ============================================================
// ProducerAcheteurPage — Écran principal de l'onglet "Producteur"
// ============================================================
const ProducerAcheteurPage = ({ state, setState, onBack, onOpenSheet, isProducer }) => {
  const { Search, MapPin, Wheat, X, Filter, ChevronRight } = LuPr;
  
  const [listings, setListings] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [searchQuery, setSearchQuery] = React.useState('');
  const [regionFilter, setRegionFilter] = React.useState('');
  const [categoryFilter, setCategoryFilter] = React.useState('');
  const [filterOpen, setFilterOpen] = React.useState(false);
  const [selectedListing, setSelectedListing] = React.useState(null);
  
  const userLat = state.user?.lat || null;
  const userLng = state.user?.lng || null;
  const token = state.user?.session_token || null;
  
  // Fetch listings
  const fetchListings = React.useCallback(async () => {
    setLoading(true);
    try {
      const params = new URLSearchParams();
      if (searchQuery.trim()) params.append('product', searchQuery.trim());
      if (regionFilter.trim()) params.append('region', regionFilter.trim());
      params.append('limit', '50');
      const r = await apiPr(`/api/pwa/listings?${params.toString()}`);
      setListings(r.listings || []);
    } catch (e) {
      console.error('Listings fetch error:', e);
      setListings([]);
    } finally {
      setLoading(false);
    }
  }, [searchQuery, regionFilter]);
  
  React.useEffect(() => { fetchListings(); }, [fetchListings]);
  
  // Calcul des annonces "près de chez toi" (tri par distance si user a un GPS)
  const listingsNearby = React.useMemo(() => {
    if (!userLat || !userLng) return listings.slice(0, 3);
    return [...listings]
      .map((l) => ({
        ...l,
        _distance: _formatDistance(userLat, userLng, l.pickup_lat || null, l.pickup_lng || null),
      }))
      .filter((l) => l._distance !== null)
      .sort((a, b) => a._distance - b._distance)
      .slice(0, 5);
  }, [listings, userLat, userLng]);
  
  // Header réutilisé depuis page-others
  const HeaderC = window.OveyoPages?.Header;
  
  return (
    <div className="pb-24">
      {/* Header gradient (réutilise composant Oveyo) */}
      {HeaderC ? (
        <HeaderC
          onBack={onBack}
          title="🌾 Producteurs"
          subtitle="Achète direct chez les producteurs"
        />
      ) : (
        // Fallback minimal si Header pas dispo
        <div className="px-5 pt-12 pb-5" style={{ background: 'linear-gradient(115deg, #102A43 0%, #1f3a5f 60%, #F4632B 130%)' }}>
          <div className="text-[10px] uppercase tracking-widest font-bold" style={{ color: '#FFA45B' }}>
            Espace Commerçant
          </div>
          <div className="font-display text-xl font-bold text-white">🌾 Producteurs</div>
        </div>
      )}
      
      {/* Bandeau Cas C — si user est producteur */}
      {isProducer && (
        <div className="mx-4 mt-3 rounded-xl p-3 flex items-center gap-3"
             style={{ background: '#E8F5E9', border: '1px solid #15803D33' }}>
          <Wheat size={20} style={{ color: '#15803D' }} />
          <div className="flex-1 min-w-0">
            <div className="text-xs font-bold text-ink">Tu es producteur</div>
            <div className="text-[11px] text-slate mt-0.5">Gère tes annonces depuis l'Espace pro</div>
          </div>
          <ChevronRight size={16} style={{ color: '#15803D' }} />
        </div>
      )}
      
      {/* Recherche */}
      <div className="px-4 mt-4">
        <div className="relative">
          <input
            type="text"
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            placeholder="Cherche un produit : oignon, mil, mangue..."
            className="w-full px-4 py-3 rounded-xl text-sm"
            style={{ background: '#FFFFFF', border: '1px solid #EAEEF4', paddingRight: searchQuery ? '40px' : '16px' }}
          />
          {searchQuery && (
            <button
              onClick={() => setSearchQuery('')}
              className="absolute inset-y-0 right-0 flex items-center pr-3 text-slate"
              aria-label="Effacer"
            >
              <X size={16} />
            </button>
          )}
        </div>
      </div>
      
      {/* Filtre région — select natif */}
      <div className="px-4 mt-2">
        <div className="relative">
          <select
            value={regionFilter}
            onChange={(e) => setRegionFilter(e.target.value)}
            className="w-full appearance-none px-4 py-2.5 rounded-xl text-sm font-bold"
            style={{
              background: regionFilter ? '#15803D' : '#FFFFFF',
              color: regionFilter ? '#FFFFFF' : '#0F1B36',
              border: '1px solid #EAEEF4',
              paddingRight: '40px',
            }}
          >
            <option value="">Toutes régions</option>
            <option value="Dakar">Dakar</option>
            <option value="Thiès">Thiès</option>
            <option value="Diourbel">Diourbel</option>
            <option value="Saint-Louis">Saint-Louis</option>
            <option value="Kaolack">Kaolack</option>
            <option value="Fatick">Fatick</option>
            <option value="Louga">Louga</option>
            <option value="Ziguinchor">Ziguinchor</option>
            <option value="Tambacounda">Tambacounda</option>
            <option value="Kolda">Kolda</option>
            <option value="Kaffrine">Kaffrine</option>
            <option value="Kédougou">Kédougou</option>
            <option value="Matam">Matam</option>
            <option value="Sédhiou">Sédhiou</option>
          </select>
          {/* Chevron custom (appearance-none cache celui par défaut) */}
          <div className="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={regionFilter ? '#FFFFFF' : '#8A99B0'} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
              <polyline points="6 9 12 15 18 9"></polyline>
            </svg>
          </div>
        </div>
      </div>
      
      {/* Loading */}
      {loading && (
        <div className="flex justify-center py-12">
          <Sppr />
        </div>
      )}
      
      {/* Empty */}
      {!loading && listings.length === 0 && (
        <div className="px-4 mt-8 text-center">
          <div className="w-20 h-20 rounded-full mx-auto flex items-center justify-center mb-3"
               style={{ background: '#E8F5E9' }}>
            <Wheat size={32} style={{ color: '#15803D' }} />
          </div>
          <div className="font-display font-bold text-base text-ink">Aucune annonce</div>
          <div className="text-sm text-slate mt-1">
            {searchQuery || regionFilter ? 'Essaie d\'élargir tes critères' : 'Reviens bientôt — les producteurs arrivent !'}
          </div>
        </div>
      )}
      
      {/* Section "Près de chez toi" (si on a GPS et annonces) */}
      {!loading && listingsNearby.length > 0 && userLat && (
        <div className="mt-4">
          <div className="px-4 flex items-center gap-2 mb-2">
            <MapPin size={14} style={{ color: '#15803D' }} />
            <h2 className="font-display font-bold text-base text-ink">Près de chez toi</h2>
          </div>
          <div className="flex gap-2 overflow-x-auto px-4 pb-1">
            {listingsNearby.map((l) => (
              <ListingCardCompact
                key={`nearby-${l.id}`}
                listing={l}
                onOpen={setSelectedListing}
              />
            ))}
          </div>
        </div>
      )}
      
      {/* Section "Toutes les annonces" */}
      {!loading && listings.length > 0 && (
        <div className="mt-4 px-4">
          <div className="flex items-center justify-between mb-2">
            <h2 className="font-display font-bold text-base text-ink">
              Toutes les annonces
            </h2>
            <span className="text-xs text-slate">{listings.length} résultat(s)</span>
          </div>
          <div className="space-y-2">
            {listings.map((l) => (
              <ListingCard
                key={l.id}
                listing={l}
                onOpen={setSelectedListing}
                userLat={userLat}
                userLng={userLng}
              />
            ))}
          </div>
        </div>
      )}
      
      {/* Sheet détail annonce */}
      <ListingDetailSheet
        listing={selectedListing}
        open={!!selectedListing}
        onClose={() => setSelectedListing(null)}
        token={token}
      />
    </div>
  );
};


// ============================================================
// ProducerView — Routeur final
// Si appelé depuis l'onglet bottom (default) → ProducerAcheteurPage
// Si appelé depuis Espace Pro → ProducerHubView (dashboard / inscription)
// ============================================================
const ProducerView = ({ state, setState, onBack, onOpenSheet, mode }) => {
  const token = state.user?.session_token;
  const [isProducer, setIsProducer] = React.useState(false);
  
  // On vérifie le type de compte juste pour afficher le bandeau "Tu es producteur"
  React.useEffect(() => {
    if (!token) { setIsProducer(false); return; }
    apiPr('/api/pwa/merchant/account-type', {
      headers: { Authorization: 'Bearer ' + token },
    }).then((r) => {
      setIsProducer(r.account_type === 'producer' || r.account_type === 'cooperative');
    }).catch(() => setIsProducer(false));
  }, [token]);
  
  // Mode hub (Espace Pro) → utilise l'ancien composant
  if (mode === 'hub') {
    return <ProducerHubView state={state} setState={setState} onBack={onBack} onOpenSheet={onOpenSheet} />;
  }
  
  // Mode acheteur par défaut (onglet bottom)
  return (
    <ProducerAcheteurPage
      state={state}
      setState={setState}
      onBack={onBack}
      onOpenSheet={onOpenSheet}
      isProducer={isProducer}
    />
  );
};


// ============================================================
// EXPORTS finaux
// ============================================================
window.OveyoPages = window.OveyoPages || {};
window.OveyoPages.ProducerView = ProducerView;
window.OveyoPages.ProducerAcheteurPage = ProducerAcheteurPage;
window.OveyoPages.ListingDetailSheet = ListingDetailSheet;
