const { useEffect, useMemo, useRef, useState } = React;
const { createRoot } = ReactDOM;

// The anon key is intentionally used in the public browser app. Never put a Supabase
// service_role key in this file. Security is enforced by PostgreSQL RLS policies.
const SUPABASE_URL = 'https://uowvzcczuznptbxsuilb.supabase.co';
const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InVvd3Z6Y2N6dXpucHRieHN1aWxiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3OTAwNDI5MjAsImV4cCI6MjEwNTYxODkyMH0.zb10r9IKpg2XdHsvfPGBuMIxZ_p1rQuElw4x6FQ4wVo';

const supabaseFactory = window.supabase?.createClient || window.supabaseClient?.createClient;
const supabase = supabaseFactory ? supabaseFactory(SUPABASE_URL, SUPABASE_ANON_KEY) : null;

const phone = '919931526322';
const fallbackCategories = ['Bridal', 'Bridesmaid', 'Vintage', 'Date Night', 'Festive', 'Glass Bangles', 'Payal', 'Maang Tikka', 'Earrings', 'Necklace Sets'];
const instagramUrl = 'https://www.instagram.com/kalyanibangles?stkn=MWsyMHg4MWE4eHo0Mw==';

const COOKIE_CONSENT_KEY = 'kalyani_cookie_consent';
const COOKIE_CONSENT_VALUE = 'accepted';

function hasCookieConsent() {
  try {
    const localValue = window.localStorage.getItem(COOKIE_CONSENT_KEY);
    const cookieValue = document.cookie.split('; ').find(row => row.startsWith(`${COOKIE_CONSENT_KEY}=`))?.split('=')[1];
    return localValue === COOKIE_CONSENT_VALUE || cookieValue === COOKIE_CONSENT_VALUE;
  } catch {
    return false;
  }
}

function saveCookieConsent() {
  try {
    window.localStorage.setItem(COOKIE_CONSENT_KEY, COOKIE_CONSENT_VALUE);
  } catch {}
  try {
    document.cookie = `${COOKIE_CONSENT_KEY}=${COOKIE_CONSENT_VALUE}; max-age=31536000; path=/; SameSite=Lax`;
  } catch {}
}

function Logo({ compact = false }) {
  return (
    <div className={`logo ${compact ? 'compact' : ''}`} aria-label="Kalyani">
      <svg className="brand-mark" viewBox="0 0 120 54" aria-hidden="true">
        <path d="M60 5C48 21 45 29 60 42C75 29 72 21 60 5Z" fill="#c89b34"/>
        <path d="M44 16C29 22 28 37 54 42C44 34 42 26 44 16ZM76 16C91 22 92 37 66 42C76 34 78 26 76 16Z" fill="#800000"/>
        <path d="M28 39C42 31 50 40 60 45C70 40 78 31 92 39C82 48 71 50 60 47C49 50 38 48 28 39Z" fill="#b8860b"/>
        <ellipse cx="60" cy="49" rx="22" ry="3" fill="#b8860b"/>
        <ellipse cx="60" cy="49" rx="12" ry="2" fill="none" stroke="#800000" strokeWidth="2"/>
      </svg>
      <span>KALYANI</span>
      {!compact && <small>ADORN EVERY MOMENT</small>}
    </div>
  );
}

function ProductArt({ tone = 'gold' }) {
  return <div className={`product-art ${tone}`}><i/><i/><i/><i/><b/></div>;
}

function getProductImages(product) {
  const list = Array.isArray(product?.image_urls) ? product.image_urls.filter(Boolean) : [];
  if (list.length) return list;
  if (product?.image_url) return [product.image_url];
  if (product?.imageUrl) return [product.imageUrl];
  return [];
}

// Warm product images before they are shown so gallery swipes do not trigger a fresh network load.
const imagePreloadCache = new Map();
function preloadImage(url) {
  if (!url) return Promise.resolve(false);
  if (imagePreloadCache.has(url)) return imagePreloadCache.get(url);
  const promise = new Promise(resolve => {
    const img = new Image();
    img.decoding = 'async';
    img.onload = () => resolve(true);
    img.onerror = () => resolve(false);
    img.src = url;
  });
  imagePreloadCache.set(url, promise);
  return promise;
}

function preloadProductImages(products) {
  products.flatMap(getProductImages).filter(Boolean).forEach(preloadImage);
}

function ProductVisual({ product, className = '' }) {
  const images = getProductImages(product);
  return images.length ? (
    <img
      className={`product-upload ${className}`}
      src={images[0]}
      alt={product.name || 'Kalyani Bangles product'}
      loading="eager"
      fetchPriority="high"
      decoding="async"
    />
  ) : <ProductArt tone={product.image || 'gold'} />;
}

function whatsapp(product) {
  const message = `Hello Kalyani, I am interested in ${product.name}${product.price ? ` - ${product.price}` : ''}. Please share availability.`;
  window.open(`https://wa.me/${phone}?text=${encodeURIComponent(message)}`, '_blank', 'noopener,noreferrer');
}

function friendlyError(error) {
  return error?.message || 'Something went wrong. Please try again.';
}

function App() {
  const [products, setProducts] = useState([]);
  const [categoryRows, setCategoryRows] = useState([]);
  const [user, setUser] = useState(null);
  const [profile, setProfile] = useState(null);
  const [favourites, setFavourites] = useState([]);
  const [category, setCategory] = useState('All');
  const [query, setQuery] = useState('');
  const [selected, setSelected] = useState(null);
  const [menu, setMenu] = useState(false);
  const [authModal, setAuthModal] = useState(false);
  const [profileModal, setProfileModal] = useState(false);
  const [adminModal, setAdminModal] = useState(false);
  const [showFavsOnly, setShowFavsOnly] = useState(false);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [showCookieConsent, setShowCookieConsent] = useState(() => !hasCookieConsent());

  const acceptCookies = () => {
    saveCookieConsent();
    setShowCookieConsent(false);
  };

  const page = new URLSearchParams(window.location.search).get('view') || 'home';
  const categories = categoryRows.length ? categoryRows.map(c => c.name) : fallbackCategories;

  const fetchProducts = async () => {
    if (!supabase) return;
    const { data, error: fetchError } = await supabase.from('products').select('*').order('created_at', { ascending: false });
    if (fetchError) setError(friendlyError(fetchError));
    else {
      const nextProducts = data || [];
      setProducts(nextProducts);
      preloadProductImages(nextProducts);
    }
    setLoading(false);
  };

  const fetchCategories = async () => {
    if (!supabase) return;
    const { data } = await supabase.from('categories').select('id,name,created_at').order('name');
    if (data?.length) setCategoryRows(data);
  };

  const fetchUserData = async (userId) => {
    if (!supabase || !userId) return;
    const [{ data: profileData }, { data: favData }] = await Promise.all([
      supabase.from('profiles').select('id,email,name,phone,role').eq('id', userId).maybeSingle(),
      supabase.from('favourites').select('product_id').eq('user_id', userId)
    ]);
    setProfile(profileData || null);
    setFavourites((favData || []).map(row => row.product_id));
  };

  useEffect(() => {
    if (!supabase) {
      setError('Supabase could not load. Please check the internet connection and deployment.');
      setLoading(false);
      return undefined;
    }

    fetchProducts();
    fetchCategories();

    supabase.auth.getSession().then(({ data: { session } }) => {
      setUser(session?.user || null);
      if (session?.user) fetchUserData(session.user.id);
    });

    const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => {
      setUser(session?.user || null);
      if (session?.user) fetchUserData(session.user.id);
      else {
        setProfile(null);
        setFavourites([]);
      }
    });

    return () => subscription.unsubscribe();
  }, []);

  const toggleFavourite = async (productId, e) => {
    e?.stopPropagation();
    if (!user) {
      setAuthModal(true);
      return;
    }

    const isFav = favourites.includes(productId);
    if (isFav) {
      const { error: deleteError } = await supabase.from('favourites').delete().eq('user_id', user.id).eq('product_id', productId);
      if (deleteError) return alert(friendlyError(deleteError));
      setFavourites(prev => prev.filter(id => id !== productId));
    } else {
      const { error: insertError } = await supabase.from('favourites').insert({ user_id: user.id, product_id: productId });
      if (insertError) return alert(friendlyError(insertError));
      setFavourites(prev => [...prev, productId]);
    }
  };

  const visible = useMemo(() => products.filter(p => {
    const matchesCategory = category === 'All' || p.category === category;
    const matchesQuery = `${p.name || ''} ${p.color || ''} ${p.category || ''}`.toLowerCase().includes(query.toLowerCase());
    const matchesFav = !showFavsOnly || favourites.includes(p.id);
    return matchesCategory && matchesQuery && matchesFav;
  }), [products, category, query, showFavsOnly, favourites]);

  const handleSignOut = async () => {
    await supabase.auth.signOut();
    setProfileModal(false);
    setAdminModal(false);
    setShowFavsOnly(false);
  };

  if (!supabase) return <div className="site"><div className="login standalone-error"><Logo compact/><h2>Connection error</h2><p>Supabase could not be initialized. Check the published site and try again.</p></div></div>;

  return (
    <div className={`site page-${page}`}>
      <div className="announcement">Curated bangles for every celebration <span>•</span> Enquire on WhatsApp</div>
      <header>
        <a href="/"><Logo/></a>
        <button className="menu" onClick={() => setMenu(!menu)} aria-label="Open menu">☰</button>
        <nav className={menu ? 'open' : ''}>
          <a href="/?view=shop">Shop</a>
          <a href="/#collections">Collections</a>
          <a href="/?view=story">Our Story</a>
          <a href="/#contact">Contact</a>
          <a href={instagramUrl} target="_blank" rel="noopener noreferrer">Instagram</a>
          {profile?.role === 'admin' && <button className="admin-link" onClick={() => setAdminModal(true)}>Owner Dashboard</button>}
          {user ? (
            <button className="admin-link" onClick={() => setProfileModal(true)}>Profile ({favourites.length} ♥)</button>
          ) : (
            <button className="admin-link" onClick={() => setAuthModal(true)}>Sign In / Sign Up</button>
          )}
        </nav>
      </header>

      <main id="home">
        <section className="hero">
          <div className="hero-copy">
            <p className="eyebrow">A CURATED BANGLE HOUSE</p>
            <h1>Adorning<br/><em>every moment.</em></h1>
            <p>Thoughtfully chosen bangles for the everyday, the celebration, and every beautiful moment in between.</p>
            <a className="gold-button" href="/?view=shop">Explore collection <span>→</span></a>
          </div>
          <div className="hero-art"><div className="sun"/><ProductArt tone="ruby"/><p>Made to be treasured</p></div>
        </section>

        <section className="intro" id="collections">
          <p className="eyebrow">DISCOVER KALYANI</p>
          <h2>Small details. <em>Lasting delight.</em></h2>
          <div className="collection-links">
            <a href="/?view=shop" onClick={() => { setCategory('Bridal'); setShowFavsOnly(false); }}><span>01</span> Bridal edit <b>→</b></a>
            <a href="/?view=shop" onClick={() => { setCategory('Festive'); setShowFavsOnly(false); }}><span>02</span> Festive glow <b>→</b></a>
            <a href="/?view=shop" onClick={() => { setCategory('Glass Bangles'); setShowFavsOnly(false); }}><span>03</span> Everyday colour <b>→</b></a>
          </div>
        </section>

        <section className="shop" id="shop">
          <div className="section-head">
            <div><p className="eyebrow">THE COLLECTION</p><h2>{showFavsOnly ? 'Your Favourites' : 'Find your favourite.'}</h2></div>
            <div className="search"><input value={query} onChange={e => setQuery(e.target.value)} placeholder="Search bangles"/><span>⌕</span></div>
          </div>

          <div className="filters">
            {showFavsOnly ? (
              <button className="active" onClick={() => setShowFavsOnly(false)}>← Back to All Products</button>
            ) : (
              ['All', ...categories].map(c => <button className={category === c ? 'active' : ''} key={c} onClick={() => setCategory(c)}>{c}</button>)
            )}
          </div>

          {error && <div className="notice">{error}</div>}
          {loading ? <p className="empty">Loading collection…</p> : (
            <div className="product-grid">
              {visible.map(p => {
                const isFav = favourites.includes(p.id);
                return (
                  <article className="product-card" key={p.id}>
                    <div className="photo" onClick={() => setSelected(p)} role="button" tabIndex="0" onKeyDown={e => e.key === 'Enter' && setSelected(p)}>
                      <ProductVisual product={p}/>
                      <button className={`fav-btn ${isFav ? 'active' : ''}`} onClick={e => toggleFavourite(p.id, e)} title={isFav ? 'Remove from favourites' : 'Add to favourites'} aria-label={isFav ? 'Remove from favourites' : 'Add to favourites'}>{isFav ? '♥' : '♡'}</button>
                      <span>View details</span>
                    </div>
                    <div className="product-info">
                      <p>{p.category}</p><h3>{p.name}</h3><strong>{p.price}</strong>
                      <button onClick={() => whatsapp(p)}>Enquire on WhatsApp <b>↗</b></button>
                    </div>
                  </article>
                );
              })}
            </div>
          )}
          {!loading && !visible.length && <p className="empty">No pieces found for this selection.</p>}
        </section>

        <section className="story">
          <div className="story-image"><ProductArt tone="rose"/></div>
          <div><p className="eyebrow">OUR STORY</p><h2>Made for moments that <em>matter.</em></h2><p>We believe the smallest details can make an occasion feel unforgettable. Kalyani brings together colour, tradition and modern styling in pieces chosen with love for bangles and the stories they carry.</p><p className="story-signoff">Curated with love. Inspired by India. Made to be yours.</p></div>
        </section>

        <section className="occasion"><p className="eyebrow">FOR EVERY OCCASION</p><h2>Wear what feels <em>like you.</em></h2><div><span>Bridal</span><span>Festive</span><span>Everyday</span><span>Gifting</span></div></section>

        <section className="contact" id="contact">
          <p className="eyebrow">LET'S CONNECT</p><h2>Looking for something <em>special?</em></h2>
          <button className="gold-button" onClick={() => whatsapp({ name: 'Kalyani Bangles collection', price: '' })}>Chat on WhatsApp <span>→</span></button>
          <a className="instagram-button" href={instagramUrl} target="_blank" rel="noopener noreferrer">Follow us on Instagram <span>↗</span></a>
        </section>
      </main>

      <footer><Logo compact/><p>Beautiful bangles, thoughtfully curated for every celebration.</p><small>© {new Date().getFullYear()} Kalyani Bangles. All rights reserved.</small></footer>

      {selected && <ProductModal product={selected} close={() => setSelected(null)} toggleFav={toggleFavourite} isFav={favourites.includes(selected.id)} user={user} profile={profile} openAuth={() => setAuthModal(true)} />}
      {authModal && <AuthModal close={() => setAuthModal(false)} />}
      {profileModal && <ProfileModal user={user} profile={profile} close={() => setProfileModal(false)} signOut={handleSignOut} viewFavs={() => { setShowFavsOnly(true); setCategory('All'); setProfileModal(false); window.location.hash = 'shop'; }} />}
      {adminModal && <AdminModal close={() => setAdminModal(false)} refresh={() => { fetchProducts(); fetchCategories(); }} products={products} categories={categories} />}
      {showCookieConsent && <CookieConsent onAccept={acceptCookies} />}
    </div>
  );
}

function CookieConsent({ onAccept }) {
  return (
    <aside className="cookie-consent" role="dialog" aria-label="Cookie consent">
      <div>
        <strong>We use cookies</strong>
        <p>We use cookies and local storage to keep the website working smoothly and remember your preferences.</p>
      </div>
      <button className="gold-button cookie-accept" onClick={onAccept}>Accept</button>
    </aside>
  );
}

function AuthModal({ close }) {
  const [isSignUp, setIsSignUp] = useState(false);
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async e => {
    e.preventDefault();
    if (isSignUp && !name.trim()) return alert('Please enter your name.');
    setLoading(true);
    try {
      const result = isSignUp
        ? await supabase.auth.signUp({
            email: email.trim(),
            password,
            options: { data: { name: name.trim() } }
          })
        : await supabase.auth.signInWithPassword({ email: email.trim(), password });
      if (result.error) alert(friendlyError(result.error));
      else if (isSignUp && !result.data.session) {
        alert('Account created. Please verify your email, then sign in.');
        close();
      } else close();
    } finally {
      setLoading(false);
    }
  };

  return <div className="modal-backdrop" onMouseDown={close}><div className="login" onMouseDown={e => e.stopPropagation()}>
    <button className="close" onClick={close}>×</button><Logo compact/><h2>{isSignUp ? 'Create Account' : 'Sign In'}</h2>
    <form onSubmit={handleSubmit}>
      {isSignUp && <input required maxLength="80" type="text" autoComplete="name" placeholder="Full Name" value={name} onChange={e => setName(e.target.value)}/>} 
      <input required type="email" autoComplete="email" placeholder="Email" value={email} onChange={e => setEmail(e.target.value)}/>
      <input required minLength="6" type="password" autoComplete={isSignUp ? 'new-password' : 'current-password'} placeholder="Password (6+ characters)" value={password} onChange={e => setPassword(e.target.value)}/>
      <button className="gold-button full" type="submit" disabled={loading}>{loading ? 'Processing…' : isSignUp ? 'Sign Up →' : 'Sign In →'}</button>
    </form>
    <p className="switch-auth" onClick={() => setIsSignUp(!isSignUp)}>{isSignUp ? 'Already have an account? Sign In' : "Don't have an account? Sign Up"}</p>
  </div></div>;
}

function ProfileModal({ user, profile, close, signOut, viewFavs }) {
  return <div className="modal-backdrop" onMouseDown={close}><div className="login" onMouseDown={e => e.stopPropagation()}>
    <button className="close" onClick={close}>×</button><Logo compact/><h2>Your Profile</h2>
    <p><strong>Name:</strong> {profile?.name || '—'}</p>
    <p><strong>Email:</strong> {user?.email}</p>
    <div className="profile-actions"><button className="gold-button full" onClick={viewFavs}>View Favourites ♥</button><button className="admin-list-btn" onClick={signOut}>Sign Out</button></div>
  </div></div>;
}

function Stars({ value = 0, interactive = false, onChange }) {
  return <div className={`review-stars ${interactive ? 'interactive' : ''}`} aria-label={`${value} out of 5 stars`}>
    {[1, 2, 3, 4, 5].map(star => <button
      key={star}
      type="button"
      className={star <= value ? 'filled' : ''}
      onClick={() => interactive && onChange?.(star)}
      aria-label={`${star} star${star > 1 ? 's' : ''}`}
      disabled={!interactive}
    >★</button>)}
  </div>;
}

function ProductReviews({ productId, user, profile, openAuth }) {
  const [reviews, setReviews] = useState([]);
  const [rating, setRating] = useState(0);
  const [comment, setComment] = useState('');
  const [editing, setEditing] = useState(false);
  const [busy, setBusy] = useState(false);
  const [loaded, setLoaded] = useState(false);

  const loadReviews = async () => {
    const { data, error } = await supabase.from('product_reviews')
      .select('id,product_id,user_id,rating,review,display_name,created_at,updated_at')
      .eq('product_id', productId)
      .order('created_at', { ascending: false });
    if (error) {
      console.error(error);
      return;
    }
    setReviews(data || []);
    const own = (data || []).find(r => r.user_id === user?.id);
    if (own) {
      setRating(own.rating);
      setComment(own.review || '');
    } else {
      setRating(0);
      setComment('');
    }
    setEditing(false);
    setLoaded(true);
  };

  useEffect(() => { loadReviews(); }, [productId, user?.id]);

  const ownReview = reviews.find(r => r.user_id === user?.id);
  const average = reviews.length ? (reviews.reduce((sum, r) => sum + Number(r.rating || 0), 0) / reviews.length).toFixed(1) : '0.0';

  const submitReview = async e => {
    e.preventDefault();
    if (!user) return openAuth?.();
    if (!rating) return alert('Please choose a star rating.');
    if (!comment.trim()) return alert('Please write a short review.');
    setBusy(true);
    try {
      const payload = { product_id: productId, user_id: user.id, rating, review: comment.trim() };
      const result = ownReview
        ? await supabase.from('product_reviews').update(payload).eq('id', ownReview.id).eq('user_id', user.id)
        : await supabase.from('product_reviews').insert(payload);
      if (result.error) throw result.error;
      await loadReviews();
    } catch (err) {
      alert(friendlyError(err));
    } finally {
      setBusy(false);
    }
  };

  const deleteReview = async () => {
    if (!ownReview || !confirm('Delete your review?')) return;
    setBusy(true);
    try {
      const { error } = await supabase.from('product_reviews').delete().eq('id', ownReview.id).eq('user_id', user.id);
      if (error) throw error;
      await loadReviews();
    } catch (err) {
      alert(friendlyError(err));
    } finally {
      setBusy(false);
    }
  };

  return <section className="reviews-section">
    <div className="reviews-head">
      <div><p className="eyebrow">CUSTOMER REVIEWS</p><h3>{reviews.length ? `${average} / 5` : 'Be the first to review'}</h3></div>
      {reviews.length > 0 && <div><Stars value={Math.round(Number(average))}/><small>{reviews.length} review{reviews.length === 1 ? '' : 's'}</small></div>}
    </div>

    {user ? (
      <form className="review-form" onSubmit={submitReview}>
        <strong>{ownReview && !editing ? 'Your review' : ownReview ? 'Edit your review' : 'Write a review'}</strong>
        <Stars value={rating} interactive={editing || !ownReview} onChange={setRating}/>
        {(editing || !ownReview) && <textarea maxLength="600" required placeholder="Share your experience with this product…" value={comment} onChange={e => setComment(e.target.value)}/>} 
        {ownReview && !editing ? (
          <div className="review-own-actions"><button type="button" className="admin-list-btn" onClick={() => setEditing(true)}>Edit</button><button type="button" className="admin-list-btn review-delete" onClick={deleteReview} disabled={busy}>Delete</button></div>
        ) : <button className="gold-button" type="submit" disabled={busy}>{busy ? 'Saving…' : ownReview ? 'Update Review →' : 'Post Review →'}</button>}
      </form>
    ) : (
      <div className="review-signin"><p>Have you purchased this piece? Share your experience with others.</p><button className="gold-button" onClick={openAuth}>Sign in to review →</button></div>
    )}

    <div className="review-list">
      {!loaded ? <p className="empty">Loading reviews…</p> : !reviews.length ? <p className="empty">No reviews yet.</p> : reviews.map(review => (
        <article className="review-item" key={review.id}>
          <div className="review-item-top"><strong>{review.display_name || 'Customer'}</strong><Stars value={Number(review.rating)}/></div>
          <p>{review.review}</p>
          <small>{new Date(review.created_at).toLocaleDateString(undefined, { day: 'numeric', month: 'short', year: 'numeric' })}</small>
        </article>
      ))}
    </div>
  </section>;
}

function ProductModal({ product: p, close, toggleFav, isFav, user, profile, openAuth }) {
  const images = getProductImages(p);
  const [index, setIndex] = useState(0);
  const [size, setSize] = useState(p.sizes?.[0]);
  const touchStartX = useRef(null);
  useEffect(() => {
    images.forEach(preloadImage);
  }, [p.id, images.join('|')]);
  const next = () => setIndex(i => (i + 1) % images.length);
  const prev = () => setIndex(i => (i - 1 + images.length) % images.length);
  const handleTouchStart = e => {
    if (images.length > 1) touchStartX.current = e.touches[0].clientX;
  };
  const handleTouchEnd = e => {
    if (images.length < 2 || touchStartX.current === null) return;
    const endX = e.changedTouches[0].clientX;
    const deltaX = endX - touchStartX.current;
    touchStartX.current = null;
    if (Math.abs(deltaX) < 45) return;
    if (deltaX < 0) next();
    else prev();
  };

  return <div className="modal-backdrop" onMouseDown={close}><div className="product-modal" onMouseDown={e => e.stopPropagation()}>
    <button className="close" onClick={close}>×</button>
    <div className="modal-image" onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd}>
      {images.length ? <img key={images[index]} src={images[index]} alt={`${p.name} ${index + 1}`} loading="eager" fetchPriority="high" decoding="async"/> : <ProductArt tone={p.image || 'gold'} />}
      {images.length > 1 && <>
        <button className="carousel-arrow prev" onClick={prev} aria-label="Previous photo">‹</button>
        <button className="carousel-arrow next" onClick={next} aria-label="Next photo">›</button>
        <div className="carousel-dots">{images.map((_, i) => <button key={i} className={i === index ? 'active' : ''} onClick={() => setIndex(i)} aria-label={`Photo ${i + 1}`}/>)}</div>
      </>}
    </div>
    <div className="modal-content">
      <p className="eyebrow">{p.category}</p><h2>{p.name}</h2><strong>{p.price}</strong><p>{p.description}</p>
      <dl><div><dt>Material</dt><dd>{p.material || '—'}</dd></div><div><dt>Colour</dt><dd>{p.color || '—'}</dd></div></dl>
      {!!(p.sizes || []).length && <><label>Select bangle size</label><div className="sizes">{p.sizes.map(s => <button className={size === s ? 'chosen' : ''} onClick={() => setSize(s)} key={s}>{s}</button>)}</div></>}
      <div className="modal-actions"><button className="gold-button full" onClick={() => whatsapp(p)}>Ask about this piece <span>→</span></button><button className="gold-button" onClick={e => toggleFav(p.id, e)}>{isFav ? '♥' : '♡'}</button></div>
      <ProductReviews productId={p.id} user={user} profile={profile} openAuth={openAuth}/>
    </div>
  </div></div>;
}

function AdminModal({ close, refresh, products, categories }) {
  const [editing, setEditing] = useState(null);
  const [categoryName, setCategoryName] = useState('');
  const [categoryBusy, setCategoryBusy] = useState(false);
  const blank = { name: '', price: '', category: categories[0] || 'Bridal', color: '', material: '', sizes: ['2.4', '2.6', '2.8'], image_urls: [], description: '', image: 'gold' };

  const handleDelete = async id => {
    if (!confirm('Remove this product?')) return;
    const product = products.find(p => p.id === id);
    const { error } = await supabase.from('products').delete().eq('id', id);
    if (error) return alert(friendlyError(error));
    await removeStorageFiles(product?.image_urls || (product?.image_url ? [product.image_url] : []));
    refresh();
  };

  const addCategory = async e => {
    e.preventDefault();
    const name = categoryName.trim();
    if (!name) return;
    setCategoryBusy(true);
    const { error } = await supabase.from('categories').insert({ name });
    if (error) alert(friendlyError(error)); else { setCategoryName(''); refresh(); }
    setCategoryBusy(false);
  };

  const renameCategory = async name => {
    const next = prompt(`Rename category “${name}” to:`, name);
    if (next === null) return;
    const clean = next.trim();
    if (!clean || clean === name) return;
    const { error } = await supabase.from('categories').update({ name: clean }).eq('name', name);
    if (error) return alert(friendlyError(error));
    const used = products.filter(p => p.category === name);
    if (used.length) {
      const { error: productError } = await supabase.from('products').update({ category: clean }).eq('category', name);
      if (productError) alert('Category renamed, but some product categories could not be updated: ' + friendlyError(productError));
    }
    refresh();
  };

  const deleteCategory = async name => {
    const inUse = products.some(p => p.category === name);
    if (inUse) return alert('This category is still used by a product. Edit those products first.');
    if (!confirm(`Delete category “${name}”?`)) return;
    const { error } = await supabase.from('categories').delete().eq('name', name);
    if (error) alert(friendlyError(error)); else refresh();
  };

  return <div className="modal-backdrop" onMouseDown={close}><div className="admin-panel" onMouseDown={e => e.stopPropagation()}>
    <button className="close" onClick={close}>×</button>
    <div className="admin-title"><div><p className="eyebrow">KALYANI OWNER</p><h2>Manage Catalogue</h2></div><button className="gold-button" onClick={() => setEditing(blank)}>Add Product <span>+</span></button></div>
    {editing && <ProductForm product={editing} categories={categories} closeForm={() => { setEditing(null); refresh(); }} />}
    <div className="category-manager"><strong>Categories</strong><form onSubmit={addCategory}><input value={categoryName} onChange={e => setCategoryName(e.target.value)} placeholder="New category"/><button className="gold-button" disabled={categoryBusy}>Add</button></form><div className="category-chips">{categories.map(c => <span key={c}>{c}<button type="button" onClick={() => renameCategory(c)} aria-label={`Rename ${c}`}>✎</button><button type="button" onClick={() => deleteCategory(c)} aria-label={`Delete ${c}`}>×</button></span>)}</div></div>
    <div className="admin-list">{products.map(p => <div key={p.id}><ProductVisual product={p}/><span><b>{p.name}</b><small>{p.price} · {p.category} · {getProductImages(p).length} photo{getProductImages(p).length === 1 ? '' : 's'}</small></span><button onClick={() => setEditing(p)}>Edit</button><button className="delete" onClick={() => handleDelete(p.id)}>Remove</button></div>)}</div>
  </div></div>;
}

function storagePathFromUrl(url) {
  if (!url || !url.includes('/storage/v1/object/public/product-images/')) return null;
  return decodeURIComponent(url.split('/storage/v1/object/public/product-images/')[1].split('?')[0]);
}

async function removeStorageFiles(urls) {
  const paths = [...new Set(urls.map(storagePathFromUrl).filter(Boolean))];
  if (paths.length) await supabase.storage.from('product-images').remove(paths);
}

async function uploadImages(files) {
  const uploaded = [];
  for (const file of files) {
    if (!file.type.startsWith('image/')) throw new Error(`${file.name} is not an image.`);
    if (file.size > 8 * 1024 * 1024) throw new Error(`${file.name} is larger than 8 MB.`);
    const safeName = file.name.toLowerCase().replace(/[^a-z0-9._-]/g, '-');
    const path = `products/${crypto.randomUUID()}-${safeName}`;
    const { error } = await supabase.storage.from('product-images').upload(path, file, { cacheControl: '31536000', upsert: false, contentType: file.type });
    if (error) throw error;
    const { data } = supabase.storage.from('product-images').getPublicUrl(path);
    uploaded.push(data.publicUrl);
  }
  return uploaded;
}

function ProductForm({ product, categories, closeForm }) {
  const [data, setData] = useState({ ...product, image_urls: getProductImages(product), sizes: (product.sizes || []).join(', ') });
  const [files, setFiles] = useState([]);
  const [uploading, setUploading] = useState(false);
  const upd = (k, v) => setData(prev => ({ ...prev, [k]: v }));
  const removeImage = url => upd('image_urls', data.image_urls.filter(x => x !== url));

  const handleSubmit = async e => {
    e.preventDefault();
    setUploading(true);
    try {
      const newUrls = files.length ? await uploadImages(files) : [];
      const finalUrls = [...data.image_urls, ...newUrls];
      const oldUrls = getProductImages(product);
      const removedOld = oldUrls.filter(url => !finalUrls.includes(url));

      const payload = {
        name: data.name.trim(), price: data.price.trim(), category: data.category,
        color: data.color?.trim() || null, material: data.material?.trim() || null,
        sizes: data.sizes.split(',').map(x => x.trim()).filter(Boolean),
        image_urls: finalUrls, image_url: finalUrls[0] || null,
        description: data.description?.trim() || null, image: data.image || 'gold'
      };
      const result = data.id
        ? await supabase.from('products').update(payload).eq('id', data.id)
        : await supabase.from('products').insert(payload);
      if (result.error) {
        await removeStorageFiles(newUrls);
        throw result.error;
      }
      await removeStorageFiles(removedOld);
      closeForm();
    } catch (err) {
      alert(friendlyError(err));
      setUploading(false);
    }
  };

  return <form className="product-form" onSubmit={handleSubmit}>
    <input required maxLength="120" value={data.name} onChange={e => upd('name', e.target.value)} placeholder="Product name"/>
    <input required maxLength="50" value={data.price} onChange={e => upd('price', e.target.value)} placeholder="Price (e.g. ₹999)"/>
    <select value={data.category} onChange={e => upd('category', e.target.value)}>{categories.map(x => <option key={x}>{x}</option>)}</select>
    <input maxLength="80" value={data.color || ''} onChange={e => upd('color', e.target.value)} placeholder="Colour"/>
    <input maxLength="80" value={data.material || ''} onChange={e => upd('material', e.target.value)} placeholder="Material"/>
    <input value={data.sizes} onChange={e => upd('sizes', e.target.value)} placeholder="Sizes, comma separated"/>
    <div className="image-manager">
      <label>Product photos — select multiple</label>
      <input type="file" accept="image/jpeg,image/png,image/webp,image/avif" multiple onChange={e => setFiles([...e.target.files])} disabled={uploading}/>
      <small>{files.length ? `${files.length} new photo${files.length === 1 ? '' : 's'} selected.` : 'Up to 8 MB per image. Photos are stored in Supabase Storage.'}</small>
      {!!data.image_urls.length && <div className="image-preview-row">{data.image_urls.map(url => <div className="image-preview" key={url}><img src={url} alt="Product preview"/><button type="button" onClick={() => removeImage(url)}>×</button></div>)}</div>}
    </div>
    <textarea maxLength="1200" value={data.description || ''} onChange={e => upd('description', e.target.value)} placeholder="Product description"/>
    <div><button type="button" onClick={closeForm}>Cancel</button><button className="gold-button" type="submit" disabled={uploading}>{uploading ? 'Uploading…' : 'Save Product →'}</button></div>
  </form>;
}

createRoot(document.getElementById('root')).render(<App/>);
