const { useEffect, useMemo, useState } = React;

const API_BASE =
  window.__SHOP_API_BASE__ ||
  localStorage.getItem("shop-api-base") ||
  (window.location.protocol === "file:" ? "http://127.0.0.1:8000/api" : "/api");

const SESSION_TOKEN_KEY = "shop-session-token";

const navItems = [
  { id: "home", label: "Home", icon: "icon-home-fill" },
  { id: "favorites", label: "Favorites", icon: "icon-heart-fill" },
  { id: "cart", label: "Cart", icon: "icon-bag-fill" },
  { id: "profile", label: "Profile", icon: "icon-user-fill" },
];

const sortModes = [
  { id: "featured", label: "По популярности" },
  { id: "priceAsc", label: "Цена: ниже" },
  { id: "priceDesc", label: "Цена: выше" },
];

const emptyPromoForm = {
  code: "",
  discount_type: "percent",
  amount: "10",
  description: "",
  usage_limit: "",
  is_active: true,
};

const emptyProductForm = {
  title: "",
  price: "2990",
  category: "ФУТБОЛКИ",
  sort_order: "0",
  is_active: true,
  imagesText: "",
  sizesText: "S\nM\nL\nXL",
  descriptionText: "",
};

function rub(value) {
  return `${new Intl.NumberFormat("ru-RU").format(value)} \u20bd`;
}

function getStoredToken() {
  return localStorage.getItem(SESSION_TOKEN_KEY) || "";
}

function setStoredToken(token) {
  localStorage.setItem(SESSION_TOKEN_KEY, token);
}

function clearStoredToken() {
  localStorage.removeItem(SESSION_TOKEN_KEY);
}

function getTelegramInitData() {
  return window.Telegram?.WebApp?.initData || "";
}

function isLocalPreview() {
  return (
    window.location.protocol === "file:" ||
    window.location.hostname === "127.0.0.1" ||
    window.location.hostname === "localhost"
  );
}

function parseTimestamp(value) {
  if (!value) {
    return null;
  }

  if (typeof value === "number") {
    return new Date(value * 1000);
  }

  return new Date(`${value.replace(" ", "T")}Z`);
}

function formatOrderDate(value) {
  const date = parseTimestamp(value);
  if (!date || Number.isNaN(date.getTime())) {
    return "\u2014";
  }
  return new Intl.DateTimeFormat("ru-RU", {
    day: "2-digit",
    month: "short",
    hour: "2-digit",
    minute: "2-digit",
  }).format(date);
}

function getDisplayName(user) {
  if (!user) {
    return "Покупатель";
  }
  return (
    user.display_name ||
    [user.first_name, user.last_name].filter(Boolean).join(" ").trim() ||
    (user.username ? `@${user.username}` : "Покупатель")
  );
}

function getInitials(user) {
  const name = getDisplayName(user).replace("@", "").trim();
  const parts = name.split(/\s+/).filter(Boolean);
  const letters = parts.slice(0, 2).map((part) => part[0]?.toUpperCase() || "");
  return letters.join("") || "TG";
}

async function copyText(text) {
  if (navigator.clipboard?.writeText) {
    await navigator.clipboard.writeText(text);
    return;
  }

  const input = document.createElement("textarea");
  input.value = text;
  input.setAttribute("readonly", "");
  input.style.position = "absolute";
  input.style.left = "-9999px";
  document.body.appendChild(input);
  input.select();
  document.execCommand("copy");
  document.body.removeChild(input);
}

async function apiRequest(path, options = {}) {
  const headers = {
    "Content-Type": "application/json",
    ...(options.headers || {}),
  };

  if (!options.skipAuth) {
    const token = getStoredToken();
    if (token) {
      headers.Authorization = `Bearer ${token}`;
    }
  }

  const response = await fetch(`${API_BASE}${path}`, {
    ...options,
    headers,
  });

  if (!response.ok) {
    const payload = await response.json().catch(() => ({}));
    if (response.status === 401 && !options.skipAuth) {
      clearStoredToken();
    }
    const detail = payload.detail;
    const error = new Error(
      typeof detail === "string" ? detail : payload.message || `API error ${response.status}`
    );
    error.status = response.status;
    error.payload = payload;
    error.path = path;
    throw error;
  }

  return response.json();
}

function makeCartKey(productId, size = "") {
  return `${productId}::${size || ""}`;
}

function buildCartIndex(items) {
  return Object.fromEntries(items.map((item) => [item.key, item]));
}

function normalizeState(payload) {
  const favorites = payload.favorites || [];
  const cartItems = (payload.cart || []).map((item) => ({
    ...item,
    size: item.size || "",
    key: item.key || makeCartKey(item.product_id, item.size || ""),
  }));

  return {
    user: payload.user || null,
    favorites,
    cartItems,
    cartIndex: buildCartIndex(cartItems),
    orders: payload.orders || [],
    supportUrl: payload.support_url || null,
    supportUsername: payload.support_username || null,
  };
}

function Icon({ id }) {
  return (
    <svg aria-hidden="true">
      <use href={`#${id}`}></use>
    </svg>
  );
}

function CatalogHeader({
  activeCategory,
  searchOpen,
  searchQuery,
  onSearchToggle,
  onSearchChange,
  onOpenCategories,
  onCycleSort,
  onOpenProfile,
  categoryButtons,
}) {
  return (
    <>
      <header className="catalog-top">
        <button className="icon-button accent" onClick={onOpenProfile} aria-label="Профиль">
          <Icon id="icon-menu" />
        </button>
        <h1>TEST</h1>
        <button className="icon-button accent" onClick={onSearchToggle} aria-label="Поиск">
          <Icon id="icon-search" />
        </button>
      </header>

      <section className="toolbar">
        <div className="chips-row">
          <button className="chip chip-round" onClick={onCycleSort} aria-label="Сортировка">
            <Icon id="icon-sort" />
          </button>

          <button className="chip chip-wide" onClick={onOpenCategories}>
            <span>{activeCategory === "ALL" ? "Categories" : activeCategory}</span>
            <svg className="chevron" aria-hidden="true">
              <use href="#icon-chevron"></use>
            </svg>
          </button>

          <div className="chip-strip">{categoryButtons}</div>
        </div>

        {searchOpen ? (
          <div className="search-panel">
            <label className="search-field">
              <Icon id="icon-search" />
              <input
                type="search"
                placeholder="Поиск товаров"
                autoComplete="off"
                value={searchQuery}
                onChange={(event) => onSearchChange(event.target.value)}
              />
            </label>
          </div>
        ) : null}
      </section>
    </>
  );
}

function ProductCard({ product, isFavorite, onToggleFavorite, onOpen }) {
  return (
    <article className="product-card">
      <div className="product-image">
        <button
          className={`product-heart ${isFavorite ? "active" : ""}`}
          onClick={() => onToggleFavorite(product.id)}
          aria-label="Добавить в избранное"
        >
          <Icon id={isFavorite ? "icon-heart-fill" : "icon-heart-outline"} />
        </button>

        <button className="product-media-button" onClick={() => onOpen(product.id)} aria-label={product.title}>
          <div className="product-photo-frame">
            <img className="product-photo" src={product.images[0]} alt={product.title} loading="lazy" />
          </div>
        </button>

        <div className="product-dots">
          {product.images.map((_, index) => (
            <span key={index} className={index === 0 ? "active" : ""}></span>
          ))}
        </div>
      </div>

      <button className="product-copy-button" onClick={() => onOpen(product.id)}>
        <div className="product-price">{rub(product.price)}</div>
        <h2 className="product-title">{product.title}</h2>
        <div className="product-meta">{product.category}</div>
      </button>
    </article>
  );
}

function FavoritesEmpty({ onBackToShop }) {
  return (
    <div className="empty-state favorite-empty tab-screen">
      <div className="favorite-empty-art" aria-hidden="true">
        <svg viewBox="0 0 140 140">
          <path className="duck-body" d="M71 21c17 0 31 13 31 31 0 9-4 17-10 23 10 5 18 14 22 25 2 6-2 12-9 12H42c-7 0-11-6-9-12 4-11 12-20 22-25-6-6-10-14-10-23 0-18 14-31 31-31Z" />
          <path className="duck-shade" d="M71 21c17 0 31 13 31 31 0 9-4 17-10 23 5 2 9 5 13 9-8 4-18 6-29 6-26 0-47-13-47-29 0-7 4-14 11-19a31 31 0 0 1 31-21Z" />
          <ellipse className="duck-eye" cx="56" cy="59" rx="4.8" ry="6.2" />
          <ellipse className="duck-eye" cx="84" cy="59" rx="4.8" ry="6.2" />
          <path className="duck-beak" d="M52 74c0-6 8-10 18-10s18 4 18 10c0 7-8 13-18 13s-18-6-18-13Z" />
          <path d="M56 74c5 3 10 4 14 4s9-1 14-4" fill="none" stroke="#b54c18" strokeWidth="3" strokeLinecap="round" />
          <path className="duck-heart" d="M26 96c-1.7 0-3-.5-4.1-1.4-4.2-3.1-11.4-9-12.2-14.4-.6-3.7 1.8-7.1 5.6-7.6 2.3-.3 4.5.6 5.9 2.3 1.5-1.7 3.6-2.6 5.9-2.3 3.7.5 6.2 3.9 5.6 7.6-.8 5.4-8 11.3-12.2 14.4-1.1.9-2.5 1.4-4.1 1.4Z" />
          <path className="duck-heart" d="M106 35c-1.5 0-2.8-.5-3.8-1.3-3.8-2.8-10.2-8-10.9-12.8-.5-3.4 1.6-6.4 4.9-6.9 2.1-.3 4 .5 5.3 2.1 1.3-1.6 3.3-2.4 5.4-2.1 3.3.5 5.4 3.5 4.9 6.9-.8 4.8-7.2 10-10.9 12.8-1 .8-2.3 1.3-3.9 1.3Z" />
          <path className="duck-heart" d="M113 72c-1.4 0-2.5-.4-3.5-1.2-3.3-2.5-8.9-7-9.5-11.1-.4-3 1.4-5.6 4.3-6.1 1.8-.3 3.6.5 4.7 1.9 1.1-1.4 2.9-2.2 4.7-1.9 2.9.5 4.8 3.1 4.3 6.1-.6 4.1-6.2 8.6-9.5 11.1-.9.8-2.1 1.2-3.5 1.2Z" />
          <circle className="duck-heart-shine" cx="104" cy="18" r="2" />
          <circle className="duck-heart-shine" cx="111" cy="55" r="1.8" />
          <path d="M67 40c-9 0-17 4-22 10" fill="none" stroke="#fff8d8" strokeWidth="4" strokeLinecap="round" />
        </svg>
      </div>
      <h2>В избранном пока пусто</h2>
      <p>Сохраняйте понравившиеся вещи, чтобы быстро вернуться к ним позже.</p>
      <button className="primary-action" onClick={onBackToShop}>
        Вернуться в каталог
      </button>
    </div>
  );
}

function CartScreen({
  cartItems,
  productMap,
  couponCode,
  promoPreview,
  applyingPromo,
  onCouponChange,
  onApplyPromo,
  onClearCart,
  onIncrement,
  onDecrement,
  onCheckout,
}) {
  if (!cartItems.length) {
    return (
      <div className="empty-state tab-screen">
        <h2>Корзина пока пустая</h2>
        <p>Добавьте товары в корзину, чтобы оформить заказ.</p>
      </div>
    );
  }

  const totalItems = cartItems.reduce((sum, item) => sum + item.quantity, 0);
  const subtotalAmount = cartItems.reduce((sum, item) => {
    const product = productMap[item.product_id];
    return sum + (product ? product.price * item.quantity : 0);
  }, 0);
  const discountAmount = promoPreview?.coupon_applied ? promoPreview.discount_amount || 0 : 0;
  const totalAmount = promoPreview?.coupon_applied
    ? promoPreview.total_amount || Math.max(0, subtotalAmount - discountAmount)
    : subtotalAmount;
  const appliedCouponCode = promoPreview?.coupon_applied ? promoPreview.coupon_code : "";

  return (
    <div className="tab-screen cart-screen">
      <div className="cart-header">
        <h2>Shopping Cart</h2>
        <button className="cart-clear" onClick={onClearCart}>
          Clear
        </button>
      </div>

      <div className="cart-body">
        <div className="cart-items-stack">
          {cartItems.map((item) => {
            const product = productMap[item.product_id];
            if (!product) {
              return null;
            }
            return (
              <div className="cart-item-card" key={item.key}>
                <div className="cart-line">
                  <div className="cart-thumb">
                    <img className="cart-thumb-image" src={product.images[0]} alt={product.title} />
                  </div>

                  <div>
                    <h3 className="cart-item-title">{product.title}</h3>
                    <div className="cart-size">Размер одежды {item.size || "ONE SIZE"}</div>

                    <div className="cart-controls-row">
                      <div className="qty-control">
                        <button className="qty-btn" onClick={() => onDecrement(item)} aria-label="Уменьшить">
                          <Icon id="icon-minus" />
                        </button>
                        <span className="qty-value">{item.quantity}</span>
                        <button className="qty-btn" onClick={() => onIncrement(item)} aria-label="Увеличить">
                          <Icon id="icon-plus" />
                        </button>
                      </div>
                      <div className="cart-item-price">{rub(product.price * item.quantity)}</div>
                    </div>
                  </div>
                </div>
              </div>
            );
          })}
        </div>

        <div className="cart-totals">
          <div className="discount-row">
            <input
              className="discount-input"
              type="text"
              placeholder="Discount code"
              value={couponCode}
              onChange={(event) => onCouponChange(event.target.value.toUpperCase())}
            />
            <button className="discount-apply-btn" onClick={onApplyPromo} disabled={applyingPromo}>
              {applyingPromo ? "..." : "Apply"}
            </button>
          </div>
          {promoPreview?.promo_error ? (
            <div className="discount-note error">{promoPreview.promo_error}</div>
          ) : null}
          {promoPreview?.coupon_applied ? (
            <div className="discount-note success">
              Promo {appliedCouponCode} applied, discount {rub(discountAmount)}
            </div>
          ) : null}
          <div className="summary-row">
            <span>Items ({totalItems})</span>
            <span>{rub(subtotalAmount)}</span>
          </div>
          {discountAmount > 0 ? (
            <div className="summary-row discount">
              <span>Discount</span>
              <span>-{rub(discountAmount)}</span>
            </div>
          ) : null}
          <div className="summary-row total">
            <span>Total</span>
            <strong>{rub(totalAmount)}</strong>
          </div>
        </div>
      </div>

      <div className="cart-footer">
        <button className="primary-action checkout-btn" onClick={onCheckout}>
          Go to checkout • {rub(totalAmount)}
        </button>
      </div>
    </div>
  );
}

function ProfileScreen({
  user,
  orders,
  favoritesCount,
  cartCount,
  productMap,
  supportUrl,
  supportUsername,
  onOpenAdmin,
}) {
  const displayName = getDisplayName(user);
  const username = user?.username ? `@${user.username}` : "не указан";
  const authDate = user?.last_auth_date ? formatOrderDate(user.last_auth_date) : "\u2014";

  return (
    <div className="tab-screen profile-screen">
      <div className="profile-hero">
        <div className="profile-avatar">
          {user?.photo_url ? (
            <img src={user.photo_url} alt={displayName} />
          ) : (
            <div className="profile-avatar-fallback">{getInitials(user)}</div>
          )}
        </div>
        <h2 className="profile-name">{displayName}</h2>
        <div className="profile-history-note">{username}</div>
      </div>

      <section className="profile-card profile-stats-grid">
        <div className="profile-stat">
          <span>Orders</span>
          <strong>{orders.length}</strong>
        </div>
        <div className="profile-stat">
          <span>Favorites</span>
          <strong>{favoritesCount}</strong>
        </div>
        <div className="profile-stat">
          <span>Cart items</span>
          <strong>{cartCount}</strong>
        </div>
      </section>

      <section className="profile-card">
        <div className="profile-section-title">Профиль</div>
        <div className="profile-detail-row">
          <span>Username</span>
          <strong>{username}</strong>
        </div>
        <div className="profile-detail-row">
          <span>Язык</span>
          <strong>{user?.language_code || "ru"}</strong>
        </div>
        <div className="profile-detail-row">
          <span>Последний вход</span>
          <strong>{authDate}</strong>
        </div>
        {supportUsername ? (
          <div className="profile-detail-row">
            <span>Поддержка</span>
            <a className="profile-link" href={supportUrl} target="_blank" rel="noreferrer">
              @{supportUsername}
            </a>
          </div>
        ) : null}
        {user?.is_admin ? (
          <button className="admin-entry-btn" onClick={onOpenAdmin}>
            Open Admin Panel
          </button>
        ) : null}
      </section>

      <section className="profile-card">
        <div className="profile-section-title">История заказов</div>
        {orders.length ? (
          <div className="profile-orders">
            {orders.map((order) => (
              <article className="order-card" key={order.id}>
                <div className="order-card-top">
                  <div>
                    <div className="order-card-title">Order #{order.id}</div>
                    <div className="order-card-meta">{formatOrderDate(order.created_at)}</div>
                  </div>
                  <div className="order-card-total">{rub(order.total_amount)}</div>
                </div>
                <div className="order-card-items">
                  {order.items.map((item, index) => {
                    const product = productMap[item.product_id];
                    return (
                      <div className="order-card-line" key={`${order.id}-${item.product_id}-${index}`}>
                        <span>{product?.title || `Product #${item.product_id}`}</span>
                        <strong>
                          {item.quantity} × {rub(item.unit_price)}
                        </strong>
                      </div>
                    );
                  })}
                </div>
                {order.coupon_code ? <div className="order-card-note">Coupon: {order.coupon_code}</div> : null}
              </article>
            ))}
          </div>
        ) : (
          <div className="profile-empty-note">У вас пока нет заказов. Когда оформите первую покупку, она появится здесь.</div>
        )}
      </section>
    </div>
  );
}

function AdminScreen({
  dashboard,
  loading,
  promoForm,
  productForm,
  editingPromoId,
  editingProductId,
  onPromoFormChange,
  onProductFormChange,
  onSavePromo,
  onEditPromo,
  onResetPromo,
  onSaveProduct,
  onEditProduct,
  onToggleProduct,
  onResetProduct,
  onRefresh,
}) {
  if (loading) {
    return (
      <div className="tab-screen admin-screen">
        <div className="empty-state app-loading">
          <h2>Загружаем данные</h2>
          <p>Еще немного, и все будет готово.</p>
        </div>
      </div>
    );
  }

  return (
    <div className="tab-screen admin-screen">
      <section className="admin-card">
        <div className="admin-header-row">
          <div>
            <h2>Admin Panel</h2>
            <p>Заказы, промокоды и управление товарами</p>
          </div>
          <button className="admin-refresh-btn" onClick={onRefresh}>
            Refresh
          </button>
        </div>
      </section>

      <section className="admin-card">
        <div className="admin-section-title">All Orders</div>
        <div className="admin-orders">
          {dashboard.orders.length ? (
            dashboard.orders.map((order) => (
              <article className="admin-order-card" key={order.id}>
                <div className="admin-order-top">
                  <div>
                    <strong>Order #{order.id}</strong>
                    <div className="admin-order-meta">
                      {order.customer.display_name}
                      {order.customer.username ? ` • @${order.customer.username}` : ""}
                    </div>
                  </div>
                  <div className="admin-order-total">{rub(order.total_amount)}</div>
                </div>
                <div className="admin-order-meta">{formatOrderDate(order.created_at)}</div>
                {order.coupon_code ? (
                  <div className="admin-order-meta">
                    Promo: {order.coupon_code} • discount {rub(order.discount_amount || 0)}
                  </div>
                ) : null}
                <div className="admin-order-lines">
                  {order.items.map((item, index) => (
                    <div className="admin-order-line" key={`${order.id}-${index}`}>
                      <span>{item.product_title || `Product #${item.product_id}`}</span>
                      <strong>
                        {item.quantity} × {rub(item.unit_price)} {item.size ? `• ${item.size}` : ""}
                      </strong>
                    </div>
                  ))}
                </div>
              </article>
            ))
          ) : (
            <div className="profile-empty-note">Заказов пока нет.</div>
          )}
        </div>
      </section>

      <section className="admin-card">
        <div className="admin-section-title">Promo Codes</div>
        <div className="admin-form-grid">
          <label>
            <span>Code</span>
            <input value={promoForm.code} onChange={(e) => onPromoFormChange("code", e.target.value.toUpperCase())} />
          </label>
          <label>
            <span>Type</span>
            <select value={promoForm.discount_type} onChange={(e) => onPromoFormChange("discount_type", e.target.value)}>
              <option value="percent">percent</option>
              <option value="fixed">fixed</option>
            </select>
          </label>
          <label>
            <span>Amount</span>
            <input type="number" min="1" value={promoForm.amount} onChange={(e) => onPromoFormChange("amount", e.target.value)} />
          </label>
          <label>
            <span>Usage limit</span>
            <input type="number" min="1" value={promoForm.usage_limit} onChange={(e) => onPromoFormChange("usage_limit", e.target.value)} />
          </label>
          <label className="admin-form-full">
            <span>Description</span>
            <input value={promoForm.description} onChange={(e) => onPromoFormChange("description", e.target.value)} />
          </label>
          <label className="admin-checkbox">
            <input type="checkbox" checked={promoForm.is_active} onChange={(e) => onPromoFormChange("is_active", e.target.checked)} />
            <span>Active</span>
          </label>
        </div>
        <div className="admin-actions-row">
          <button className="admin-primary-btn" onClick={onSavePromo}>
            {editingPromoId ? "Update promo" : "Create promo"}
          </button>
          {editingPromoId ? (
            <button className="admin-secondary-btn" onClick={onResetPromo}>
              Cancel
            </button>
          ) : null}
        </div>
        <div className="admin-list">
          {dashboard.promoCodes.map((promo) => (
            <div className="admin-list-card" key={promo.id}>
              <div>
                <strong>{promo.code}</strong>
                <div className="admin-order-meta">
                  {promo.discount_type} • {promo.amount}
                  {promo.usage_limit ? ` • ${promo.uses_count}/${promo.usage_limit}` : ` • used ${promo.uses_count}`}
                </div>
              </div>
              <div className="admin-inline-actions">
                <span className={`admin-status ${promo.is_active ? "active" : "hidden"}`}>
                  {promo.is_active ? "active" : "inactive"}
                </span>
                <button className="admin-link-btn" onClick={() => onEditPromo(promo)}>
                  Edit
                </button>
              </div>
            </div>
          ))}
        </div>
      </section>

      <section className="admin-card">
        <div className="admin-section-title">Products</div>
        <div className="admin-form-grid">
          <label className="admin-form-full">
            <span>Title</span>
            <input value={productForm.title} onChange={(e) => onProductFormChange("title", e.target.value)} />
          </label>
          <label>
            <span>Price</span>
            <input type="number" min="1" value={productForm.price} onChange={(e) => onProductFormChange("price", e.target.value)} />
          </label>
          <label>
            <span>Category</span>
            <input value={productForm.category} onChange={(e) => onProductFormChange("category", e.target.value)} />
          </label>
          <label>
            <span>Sort order</span>
            <input type="number" value={productForm.sort_order} onChange={(e) => onProductFormChange("sort_order", e.target.value)} />
          </label>
          <label className="admin-checkbox">
            <input type="checkbox" checked={productForm.is_active} onChange={(e) => onProductFormChange("is_active", e.target.checked)} />
            <span>Visible in catalog</span>
          </label>
          <label className="admin-form-full">
            <span>Images, one per line</span>
            <textarea value={productForm.imagesText} onChange={(e) => onProductFormChange("imagesText", e.target.value)} />
          </label>
          <label className="admin-form-full">
            <span>Sizes, one per line</span>
            <textarea value={productForm.sizesText} onChange={(e) => onProductFormChange("sizesText", e.target.value)} />
          </label>
          <label className="admin-form-full">
            <span>Description, one per line</span>
            <textarea value={productForm.descriptionText} onChange={(e) => onProductFormChange("descriptionText", e.target.value)} />
          </label>
        </div>
        <div className="admin-actions-row">
          <button className="admin-primary-btn" onClick={onSaveProduct}>
            {editingProductId ? "Update product" : "Create product"}
          </button>
          {editingProductId ? (
            <button className="admin-secondary-btn" onClick={onResetProduct}>
              Cancel
            </button>
          ) : null}
        </div>
        <div className="admin-list">
          {dashboard.products.map((product) => (
            <div className="admin-list-card" key={product.id}>
              <div>
                <strong>{product.title}</strong>
                <div className="admin-order-meta">
                  {rub(product.price)} • {product.category} • #{product.sort_order}
                </div>
              </div>
              <div className="admin-inline-actions">
                <span className={`admin-status ${product.is_active ? "active" : "hidden"}`}>
                  {product.is_active ? "visible" : "hidden"}
                </span>
                <button className="admin-link-btn" onClick={() => onEditProduct(product)}>
                  Edit
                </button>
                <button className="admin-link-btn" onClick={() => onToggleProduct(product)}>
                  {product.is_active ? "Hide" : "Show"}
                </button>
              </div>
            </div>
          ))}
        </div>
      </section>
    </div>
  );
}

function CategorySheet({ categories, activeCategory, onSelect, onClose }) {
  return (
    <>
      <div className="sheet-backdrop" onClick={onClose}></div>
      <section className="category-sheet">
        <div className="sheet-handle"></div>
        <div className="sheet-title">Категории</div>
        <div className="category-sheet-grid">
          {categories.map((category) => (
            <button
              key={category}
              className={`category-option ${activeCategory === category ? "active" : ""}`}
              onClick={() => onSelect(category)}
            >
              <span>{category === "ALL" ? "ВСЕ" : category}</span>
              {activeCategory === category ? <span>Selected</span> : null}
            </button>
          ))}
        </div>
      </section>
    </>
  );
}

function ProductModal({
  product,
  slideIndex,
  selectedSize,
  isFavorite,
  quantity,
  hasSupport,
  onClose,
  onPrevSlide,
  onNextSlide,
  onToggleFavorite,
  onSelectSize,
  onQtyMinus,
  onQtyPlus,
  onGoToCart,
  onShare,
  onShowSizeChart,
  onContactSeller,
}) {
  if (!product) {
    return null;
  }

  const imageSrc = product.images[slideIndex];
  const imageFitClass = slideIndex === product.images.length - 1 ? "contain" : "";

  return (
    <>
      <div className="sheet-backdrop" onClick={onClose}></div>
      <section className="product-sheet" aria-live="polite">
        <div className="sheet-handle"></div>
        <div className="product-view">
          <div className="product-view-topbar">
            <button className="product-close-btn" onClick={onClose} aria-label="Закрыть просмотр">
              <Icon id="icon-close" />
            </button>
          </div>

          <section className="product-view-media">
            <div className="product-view-progress">
              {product.images.map((_, index) => (
                <span key={index} className={`product-view-progress-bar ${index === slideIndex ? "active" : ""}`}></span>
              ))}
            </div>

            <div className="product-view-fabs">
              <button
                className={`product-view-fab ${isFavorite ? "active" : ""}`}
                onClick={() => onToggleFavorite(product.id)}
                aria-label="В избранное"
              >
                <Icon id={isFavorite ? "icon-heart-fill" : "icon-heart-outline"} />
              </button>
              <button className="product-view-fab" onClick={onShare} aria-label="Поделиться">
                <Icon id="icon-share" />
              </button>
            </div>

            <div className="product-view-image-shell">
              <button className="product-view-hotspot prev" onClick={onPrevSlide} aria-label="Предыдущее фото"></button>
              <img className={`sheet-product-image ${imageFitClass}`} src={imageSrc} alt={product.title} />
              <button className="product-view-hotspot next" onClick={onNextSlide} aria-label="Следующее фото"></button>
            </div>
          </section>

          <section className="product-view-section size">
            <div className="product-view-section-label">
              Размер одежды: <strong>{selectedSize}</strong>
            </div>
            <div className="size-row product-view-sizes">
              {product.sizes.map((size) => (
                <button
                  key={size}
                  className={`size-chip ${size === selectedSize ? "active" : ""}`}
                  onClick={() => onSelectSize(size)}
                >
                  {size}
                </button>
              ))}
            </div>
          </section>

          <section className="product-view-section details">
            <h2 className="product-view-title">{product.title}</h2>
            <div className="product-view-price">{rub(product.price)}</div>
            <div className="product-view-subtitle">Product details</div>
            <div className="product-view-copy">
              {product.description.map((line) => (
                <p key={line}>{line}</p>
              ))}
            </div>
            <button className="product-view-readmore" onClick={onShowSizeChart}>
              Размерная сетка
              <Icon id="icon-chevron" />
            </button>
          </section>

          <section className="product-view-section support">
            <div className="product-view-subtitle">Still have questions?</div>
            <button
              className="product-view-contact"
              onClick={onContactSeller}
              disabled={!hasSupport}
            >
              Contact Seller
            </button>
          </section>
        </div>
      </section>

      <div className="product-view-bottom">
        <div className="qty-control product-view-qty">
          <button className="qty-btn" onClick={onQtyMinus} aria-label="Уменьшить">
            <Icon id="icon-minus" />
          </button>
          <span className="qty-value">{quantity}</span>
          <button className="qty-btn" onClick={onQtyPlus} aria-label="Увеличить">
            <Icon id="icon-plus" />
          </button>
        </div>

        <button className="primary-action product-view-cart-btn" onClick={onGoToCart}>
          Go to Cart
        </button>
      </div>
    </>
  );
}

function Toast({ message }) {
  if (!message) {
    return null;
  }
  return <div className="toast">{message}</div>;
}

function App() {
  const [viewer, setViewer] = useState(null);
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [activeTab, setActiveTab] = useState("home");
  const [activeCategory, setActiveCategory] = useState("ALL");
  const [favorites, setFavorites] = useState([]);
  const [cartItems, setCartItems] = useState([]);
  const [cartIndex, setCartIndex] = useState({});
  const [orders, setOrders] = useState([]);
  const [searchOpen, setSearchOpen] = useState(false);
  const [searchQuery, setSearchQuery] = useState("");
  const [sortMode, setSortMode] = useState("featured");
  const [activeProductId, setActiveProductId] = useState(null);
  const [selectedSize, setSelectedSize] = useState({});
  const [draftQuantities, setDraftQuantities] = useState({});
  const [couponCode, setCouponCode] = useState("");
  const [promoPreview, setPromoPreview] = useState(null);
  const [applyingPromo, setApplyingPromo] = useState(false);
  const [productSlides, setProductSlides] = useState({});
  const [categorySheetOpen, setCategorySheetOpen] = useState(false);
  const [toast, setToast] = useState("");
  const [supportUrl, setSupportUrl] = useState(null);
  const [supportUsername, setSupportUsername] = useState(null);
  const [adminDashboard, setAdminDashboard] = useState({
    orders: [],
    promoCodes: [],
    products: [],
  });
  const [adminLoading, setAdminLoading] = useState(false);
  const [promoForm, setPromoForm] = useState(emptyPromoForm);
  const [productForm, setProductForm] = useState(emptyProductForm);
  const [editingPromoId, setEditingPromoId] = useState(null);
  const [editingProductId, setEditingProductId] = useState(null);

  const favoritesSet = useMemo(() => new Set(favorites), [favorites]);
  const productMap = useMemo(
    () => Object.fromEntries(products.map((product) => [product.id, product])),
    [products]
  );
  const cartCount = useMemo(
    () => cartItems.reduce((sum, entry) => sum + entry.quantity, 0),
    [cartItems]
  );
  const categories = useMemo(
    () => ["ALL", ...new Set(products.map((product) => product.category))],
    [products]
  );
  const activeProduct = useMemo(
    () => products.find((product) => product.id === activeProductId) || null,
    [activeProductId, products]
  );

  function showToast(message) {
    setToast(message);
  }

  function applyState(payload) {
    const next = normalizeState(payload);
    setViewer((prev) => next.user || prev);
    setFavorites(next.favorites);
    setCartItems(next.cartItems);
    setCartIndex(next.cartIndex);
    setOrders(next.orders);
    setSupportUrl(next.supportUrl);
    setSupportUsername(next.supportUsername);
  }

  function resetPromoPreview() {
    setPromoPreview(null);
  }

  function handleCouponChange(value) {
    setCouponCode(value);
    resetPromoPreview();
  }

  function getCartItem(productId, size = "") {
    return cartIndex[makeCartKey(productId, size || "")] || null;
  }

  function getDefaultSize(productId) {
    const product = productMap[productId];
    const existingSize = cartItems.find((item) => item.product_id === productId)?.size;
    return (
      selectedSize[productId] ||
      existingSize ||
      product?.sizes[1] ||
      product?.sizes[0] ||
      "M"
    );
  }

  function getDraftQuantity(productId, size) {
    const key = makeCartKey(productId, size || "");
    return draftQuantities[key] || getCartItem(productId, size)?.quantity || 1;
  }

  async function loadAdminDashboard() {
    setAdminLoading(true);
    try {
      const payload = await apiRequest("/admin/dashboard");
      setAdminDashboard({
        orders: payload.orders || [],
        promoCodes: payload.promo_codes || [],
        products: payload.products || [],
      });
    } catch (err) {
      showToast(err.message || "Не удалось загрузить админку");
    } finally {
      setAdminLoading(false);
    }
  }

  async function authenticate() {
    const existingToken = getStoredToken();

    if (existingToken) {
      try {
        const session = await apiRequest("/me");
        setViewer(session.user || null);
        setSupportUrl(session.support_url || null);
        setSupportUsername(session.support_username || null);
        return;
      } catch (err) {
        clearStoredToken();
      }
    }

    const initData = getTelegramInitData();
    if (initData) {
      try {
        const authPayload = await apiRequest("/auth/telegram", {
          method: "POST",
          body: JSON.stringify({ init_data: initData }),
          skipAuth: true,
        });
        setStoredToken(authPayload.token);
        setViewer(authPayload.user || null);
        setSupportUrl(authPayload.support_url || null);
        setSupportUsername(authPayload.support_username || null);
        return;
      } catch (err) {
        const message = err?.message || "";
        if (!isLocalPreview()) {
          throw err;
        }

        console.warn("Telegram auth failed in local preview, falling back to dev auth.", message);
      }
    }

    if (!isLocalPreview()) {
      throw new Error("Откройте миниапп внутри Telegram, чтобы пройти авторизацию");
    }

    const devPayload = await apiRequest("/auth/dev", {
      method: "POST",
      body: JSON.stringify({ display_name: "Local Tester" }),
      skipAuth: true,
    });
    setStoredToken(devPayload.token);
    setViewer(devPayload.user || null);
    setSupportUrl(devPayload.support_url || null);
    setSupportUsername(devPayload.support_username || null);
  }

  async function syncState() {
    const payload = await apiRequest("/state");
    applyState(payload);
  }

  useEffect(() => {
    let cancelled = false;

    async function bootstrap() {
      try {
        setLoading(true);
        await authenticate();
        const [productsPayload, statePayload] = await Promise.all([
          apiRequest("/products"),
          apiRequest("/state"),
        ]);

        if (cancelled) {
          return;
        }

        setProducts(productsPayload.products || []);
        applyState(statePayload);
        setError("");
      } catch (err) {
        if (!cancelled) {
          setError(err.message || "Не удалось загрузить данные");
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    }

    bootstrap();

    return () => {
      cancelled = true;
    };
  }, []);

  useEffect(() => {
    const webApp = window.Telegram?.WebApp;
    if (!webApp) {
      return;
    }

    webApp.ready();
    webApp.expand();

    try {
      webApp.setHeaderColor("#eceef3");
      webApp.setBackgroundColor("#eceef3");
    } catch (err) {
      console.warn("Telegram WebApp styling is not available in this client.", err);
    }
  }, []);

  useEffect(() => {
    if (!toast) {
      return undefined;
    }
    const id = window.setTimeout(() => setToast(""), 1800);
    return () => window.clearTimeout(id);
  }, [toast]);

  useEffect(() => {
    const onKeyDown = (event) => {
      if (event.key === "Escape") {
        setActiveProductId(null);
        setCategorySheetOpen(false);
      }
    };
    window.addEventListener("keydown", onKeyDown);
    return () => window.removeEventListener("keydown", onKeyDown);
  }, []);

  const visibleProducts = useMemo(() => {
    let list = [...products];

    if (activeTab === "favorites") {
      list = list.filter((product) => favoritesSet.has(product.id));
    }

    if (activeTab === "home" && activeCategory !== "ALL") {
      list = list.filter((product) => product.category === activeCategory);
    }

    if (searchQuery.trim()) {
      const query = searchQuery.trim().toLowerCase();
      list = list.filter(
        (product) =>
          product.title.toLowerCase().includes(query) ||
          product.category.toLowerCase().includes(query)
      );
    }

    if (sortMode === "priceAsc") {
      list.sort((a, b) => a.price - b.price);
    }

    if (sortMode === "priceDesc") {
      list.sort((a, b) => b.price - a.price);
    }

    return list;
  }, [activeTab, activeCategory, favoritesSet, products, searchQuery, sortMode]);

  function cycleSort() {
    const currentIndex = sortModes.findIndex((mode) => mode.id === sortMode);
    const nextMode = sortModes[(currentIndex + 1) % sortModes.length];
    setSortMode(nextMode.id);
    showToast(nextMode.label);
  }

  async function toggleFavorite(productId) {
    const favorite = !favoritesSet.has(productId);
    try {
      const payload = await apiRequest("/favorites", {
        method: "PUT",
        body: JSON.stringify({ product_id: productId, favorite }),
      });
      applyState(payload);
      showToast(favorite ? "Добавили в избранное" : "Убрали из избранного");
    } catch (err) {
      showToast(err.message || "Не удалось обновить избранное");
    }
  }

  async function saveCartItem(productId, quantity, size) {
    try {
      const payload = await apiRequest("/cart/items", {
        method: "PUT",
        body: JSON.stringify({
          product_id: productId,
          quantity,
          size,
        }),
      });
      applyState(payload);
      resetPromoPreview();
      return true;
    } catch (err) {
      showToast(err.message || "Не удалось обновить корзину");
      return false;
    }
  }

  async function goToCartFromProduct(productId, quantity, size) {
    const updated = await saveCartItem(productId, quantity, size || getDefaultSize(productId));
    if (!updated) {
      return;
    }
    setActiveProductId(null);
    setActiveTab("cart");
  }

  function openProduct(productId) {
    setActiveProductId(productId);
    setCategorySheetOpen(false);
  }

  function closeProduct() {
    setActiveProductId(null);
  }

  function nextSlide(productId, direction) {
    const product = productMap[productId];
    if (!product) {
      return;
    }

    setProductSlides((prev) => ({
      ...prev,
      [productId]: ((prev[productId] || 0) + direction + product.images.length) % product.images.length,
    }));
  }

  function switchTab(tab) {
    setActiveProductId(null);
    setCategorySheetOpen(false);
    setActiveTab(tab);
    if (tab !== "home") {
      setActiveCategory("ALL");
      setSearchOpen(false);
    }
    if (tab === "admin" && viewer?.is_admin) {
      loadAdminDashboard();
    }
  }

  async function clearCart() {
    try {
      const payload = await apiRequest("/cart", {
        method: "DELETE",
      });
      applyState(payload);
      setCouponCode("");
      resetPromoPreview();
      showToast("Корзина очищена");
    } catch (err) {
      showToast(err.message || "Не удалось очистить корзину");
    }
  }

  async function applyPromoCode() {
    const normalizedCode = couponCode.trim().toUpperCase();
    setCouponCode(normalizedCode);

    if (!normalizedCode) {
      resetPromoPreview();
      showToast("Введите промокод");
      return;
    }

    try {
      setApplyingPromo(true);
      const payload = await apiRequest("/cart/promo-preview", {
        method: "POST",
        body: JSON.stringify({
          coupon_code: normalizedCode,
        }),
      });
      setPromoPreview(payload);
      if (payload.coupon_applied) {
        showToast("Промокод применен");
      } else if (payload.promo_error) {
        showToast(payload.promo_error);
      }
    } catch (err) {
      setPromoPreview({
        coupon_code: normalizedCode,
        coupon_applied: false,
        promo_error: err.message || "Не удалось проверить промокод",
      });
      showToast(err.message || "Не удалось проверить промокод");
    } finally {
      setApplyingPromo(false);
    }
  }

  async function checkout() {
    const normalizedCoupon = couponCode.trim().toUpperCase();
    if (normalizedCoupon && !promoPreview?.coupon_applied) {
      showToast("Сначала примените промокод");
      return;
    }

    try {
      const payload = await apiRequest("/orders/checkout", {
        method: "POST",
        body: JSON.stringify({
          coupon_code: promoPreview?.coupon_applied ? normalizedCoupon : null,
        }),
      });
      applyState(payload);
      setCouponCode("");
      resetPromoPreview();
      setActiveTab("profile");
      showToast("Заказ сохранен в историю");
    } catch (err) {
      showToast(err.message || "Не удалось оформить заказ");
    }
  }

  async function handleShare() {
    if (!activeProduct) {
      return;
    }

    const shareText = `${activeProduct.title} • ${rub(activeProduct.price)}`;

    try {
      if (navigator.share) {
        await navigator.share({
          title: activeProduct.title,
          text: shareText,
        });
      } else {
        await copyText(shareText);
        showToast("Название товара скопировано");
        return;
      }
    } catch (err) {
      return;
    }

    showToast("Поделились товаром");
  }

  function openSupport() {
    if (!supportUrl) {
      showToast("Добавьте SHOP_SUPPORT_USERNAME на сервере");
      return;
    }

    const webApp = window.Telegram?.WebApp;
    if (webApp?.openTelegramLink) {
      webApp.openTelegramLink(supportUrl);
      return;
    }

    window.open(supportUrl, "_blank", "noopener,noreferrer");
  }

  function updatePromoForm(field, value) {
    setPromoForm((prev) => ({ ...prev, [field]: value }));
  }

  function resetPromoForm() {
    setPromoForm(emptyPromoForm);
    setEditingPromoId(null);
  }

  function editPromo(promo) {
    setEditingPromoId(promo.id);
    setPromoForm({
      code: promo.code,
      discount_type: promo.discount_type,
      amount: String(promo.amount),
      description: promo.description || "",
      usage_limit: promo.usage_limit ? String(promo.usage_limit) : "",
      is_active: promo.is_active,
    });
    setActiveTab("admin");
  }

  async function savePromo() {
    try {
      const payload = {
        code: promoForm.code.trim(),
        discount_type: promoForm.discount_type,
        amount: Number(promoForm.amount),
        description: promoForm.description.trim() || null,
        usage_limit: promoForm.usage_limit ? Number(promoForm.usage_limit) : null,
        is_active: promoForm.is_active,
      };
      if (!payload.code || !payload.amount) {
        showToast("Заполните промокод и размер скидки");
        return;
      }
      const path = editingPromoId ? `/admin/promo-codes/${editingPromoId}` : "/admin/promo-codes";
      const method = editingPromoId ? "PUT" : "POST";
      const response = await apiRequest(path, {
        method,
        body: JSON.stringify(payload),
      });
      setAdminDashboard((prev) => ({ ...prev, promoCodes: response.promo_codes || [] }));
      resetPromoForm();
      showToast(editingPromoId ? "Промокод обновлен" : "Промокод создан");
    } catch (err) {
      showToast(err.message || "Не удалось сохранить промокод");
    }
  }

  function updateProductForm(field, value) {
    setProductForm((prev) => ({ ...prev, [field]: value }));
  }

  function resetProductForm() {
    setProductForm(emptyProductForm);
    setEditingProductId(null);
  }

  function editProduct(product) {
    setEditingProductId(product.id);
    setProductForm({
      title: product.title,
      price: String(product.price),
      category: product.category,
      sort_order: String(product.sort_order || 0),
      is_active: Boolean(product.is_active),
      imagesText: (product.images || []).join("\n"),
      sizesText: (product.sizes || []).join("\n"),
      descriptionText: (product.description || []).join("\n"),
    });
    setActiveTab("admin");
  }

  async function saveProduct() {
    try {
      const payload = {
        title: productForm.title.trim(),
        price: Number(productForm.price),
        category: productForm.category.trim(),
        sort_order: Number(productForm.sort_order || 0),
        is_active: productForm.is_active,
        images: productForm.imagesText.split("\n").map((item) => item.trim()).filter(Boolean),
        sizes: productForm.sizesText.split("\n").map((item) => item.trim()).filter(Boolean),
        description: productForm.descriptionText.split("\n").map((item) => item.trim()).filter(Boolean),
      };
      if (!payload.title || !payload.category || !payload.price) {
        showToast("Заполните title, price и category");
        return;
      }
      const path = editingProductId ? `/admin/products/${editingProductId}` : "/admin/products";
      const method = editingProductId ? "PUT" : "POST";
      const response = await apiRequest(path, {
        method,
        body: JSON.stringify(payload),
      });
      const nextProducts = response.products || [];
      setAdminDashboard((prev) => ({ ...prev, products: nextProducts }));
      setProducts(nextProducts.filter((item) => item.is_active));
      resetProductForm();
      showToast(editingProductId ? "Товар обновлен" : "Товар создан");
    } catch (err) {
      showToast(err.message || "Не удалось сохранить товар");
    }
  }

  async function toggleProduct(product) {
    try {
      const response = await apiRequest(`/admin/products/${product.id}`, {
        method: "PUT",
        body: JSON.stringify({
          title: product.title,
          price: product.price,
          category: product.category,
          sort_order: product.sort_order || 0,
          is_active: !product.is_active,
          images: product.images || [],
          sizes: product.sizes || [],
          description: product.description || [],
        }),
      });
      const nextProducts = response.products || [];
      setAdminDashboard((prev) => ({ ...prev, products: nextProducts }));
      setProducts(nextProducts.filter((item) => item.is_active));
      showToast(product.is_active ? "Товар скрыт" : "Товар снова видим");
    } catch (err) {
      showToast(err.message || "Не удалось изменить видимость товара");
    }
  }

  const categoryButtons = categories
    .filter((category) => category !== "ALL")
    .map((category) => (
      <button
        key={category}
        className={`chip chip-filter ${activeCategory === category ? "active" : ""}`}
        onClick={() => {
          setActiveCategory(category);
          setActiveTab("home");
        }}
      >
        {category}
      </button>
    ));

  const currentProductSize = activeProduct ? getDefaultSize(activeProduct.id) : "";
  const currentProductQty = activeProduct ? Math.max(1, getDraftQuantity(activeProduct.id, currentProductSize)) : 1;

  return (
    <div className="page-shell">
      <div className="device-frame">
        <div className="miniapp">
          {activeTab === "home" ? (
            <CatalogHeader
              activeCategory={activeCategory}
              searchOpen={searchOpen}
              searchQuery={searchQuery}
              onSearchToggle={() => setSearchOpen((prev) => !prev)}
              onSearchChange={setSearchQuery}
              onOpenCategories={() => setCategorySheetOpen(true)}
              onCycleSort={cycleSort}
              onOpenProfile={() => switchTab("profile")}
              categoryButtons={categoryButtons}
            />
          ) : null}

          <main className="content-area">
            <section className="products-grid">
              {loading ? (
                <div className="empty-state tab-screen app-loading">
                  <h2>Открываем магазин</h2>
                  <p>Еще чуть-чуть, загружаем каталог и ваш профиль.</p>
                </div>
              ) : null}

              {!loading && error ? (
                <div className="empty-state tab-screen app-loading">
                  <h2>Не удалось подключиться</h2>
                  <p>{error}</p>
                  <button
                    className="primary-action"
                    onClick={async () => {
                      setError("");
                      setLoading(true);
                      try {
                        await authenticate();
                        const [productsPayload, statePayload] = await Promise.all([
                          apiRequest("/products"),
                          apiRequest("/state"),
                        ]);
                        setProducts(productsPayload.products || []);
                        applyState(statePayload);
                      } catch (err) {
                        setError(err.message || "Не удалось загрузить данные");
                      } finally {
                        setLoading(false);
                      }
                    }}
                  >
                    Попробовать снова
                  </button>
                </div>
              ) : null}

              {!loading && !error && activeTab === "favorites" && !visibleProducts.length ? (
                <FavoritesEmpty onBackToShop={() => switchTab("home")} />
              ) : null}

              {!loading && !error && activeTab === "cart" ? (
                <CartScreen
                  cartItems={cartItems}
                  productMap={productMap}
                  couponCode={couponCode}
                  promoPreview={promoPreview}
                  applyingPromo={applyingPromo}
                  onCouponChange={handleCouponChange}
                  onApplyPromo={applyPromoCode}
                  onClearCart={clearCart}
                  onIncrement={(item) => saveCartItem(item.product_id, item.quantity + 1, item.size)}
                  onDecrement={(item) => saveCartItem(item.product_id, Math.max(0, item.quantity - 1), item.size)}
                  onCheckout={checkout}
                />
              ) : null}

              {!loading && !error && activeTab === "profile" ? (
                <ProfileScreen
                  user={viewer}
                  orders={orders}
                  favoritesCount={favorites.length}
                  cartCount={cartCount}
                  productMap={productMap}
                  supportUrl={supportUrl}
                  supportUsername={supportUsername}
                  onOpenAdmin={() => switchTab("admin")}
                />
              ) : null}

              {!loading && !error && activeTab === "admin" && viewer?.is_admin ? (
                <AdminScreen
                  dashboard={adminDashboard}
                  loading={adminLoading}
                  promoForm={promoForm}
                  productForm={productForm}
                  editingPromoId={editingPromoId}
                  editingProductId={editingProductId}
                  onPromoFormChange={updatePromoForm}
                  onProductFormChange={updateProductForm}
                  onSavePromo={savePromo}
                  onEditPromo={editPromo}
                  onResetPromo={resetPromoForm}
                  onSaveProduct={saveProduct}
                  onEditProduct={editProduct}
                  onToggleProduct={toggleProduct}
                  onResetProduct={resetProductForm}
                  onRefresh={loadAdminDashboard}
                />
              ) : null}

              {!loading &&
              !error &&
              (activeTab === "home" || (activeTab === "favorites" && visibleProducts.length))
                ? visibleProducts.map((product) => (
                    <ProductCard
                      key={product.id}
                      product={product}
                      isFavorite={favoritesSet.has(product.id)}
                      onToggleFavorite={toggleFavorite}
                      onOpen={openProduct}
                    />
                  ))
                : null}
            </section>
          </main>

          <nav className={`bottom-nav ${activeProduct ? "hidden" : ""}`}>
            {navItems.map((item) => (
              <button
                key={item.id}
                className={`nav-item ${activeTab === item.id ? "active" : ""}`}
                onClick={() => switchTab(item.id)}
              >
                {item.id === "cart" && cartCount ? <span className="badge">{cartCount}</span> : null}
                <Icon id={item.icon} />
                <span>{item.label}</span>
              </button>
            ))}
          </nav>
        </div>
      </div>

      {categorySheetOpen ? (
        <CategorySheet
          categories={categories}
          activeCategory={activeCategory}
          onClose={() => setCategorySheetOpen(false)}
          onSelect={(category) => {
            setActiveCategory(category);
            setActiveTab("home");
            setCategorySheetOpen(false);
          }}
        />
      ) : null}

      <ProductModal
        product={activeProduct}
        slideIndex={activeProduct ? productSlides[activeProduct.id] || 0 : 0}
        selectedSize={currentProductSize || ""}
        isFavorite={activeProduct ? favoritesSet.has(activeProduct.id) : false}
        quantity={currentProductQty}
        hasSupport={Boolean(supportUrl)}
        onClose={closeProduct}
        onPrevSlide={() => activeProduct && nextSlide(activeProduct.id, -1)}
        onNextSlide={() => activeProduct && nextSlide(activeProduct.id, 1)}
        onToggleFavorite={toggleFavorite}
        onSelectSize={(size) => {
          if (!activeProduct) return;
          setSelectedSize((prev) => ({
            ...prev,
            [activeProduct.id]: size,
          }));
        }}
        onQtyMinus={() => {
          if (!activeProduct) return;
          setDraftQuantities((prev) => ({
            ...prev,
            [makeCartKey(activeProduct.id, currentProductSize)]: Math.max(1, currentProductQty - 1),
          }));
        }}
        onQtyPlus={() => {
          if (!activeProduct) return;
          setDraftQuantities((prev) => ({
            ...prev,
            [makeCartKey(activeProduct.id, currentProductSize)]: currentProductQty + 1,
          }));
        }}
        onGoToCart={async () => {
          if (!activeProduct) return;
          await goToCartFromProduct(activeProduct.id, currentProductQty, currentProductSize);
        }}
        onShare={handleShare}
        onShowSizeChart={() => {
          if (!activeProduct) return;
          setProductSlides((prev) => ({
            ...prev,
            [activeProduct.id]: activeProduct.images.length - 1,
          }));
        }}
        onContactSeller={openSupport}
      />

      <Toast message={toast} />
    </div>
  );
}

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