/* ============================================================
   Төрмен — Catalog from Medusa Store API
   Любой Published товар в категории Төрмен → на витрине
   ============================================================ */
const { createContext:createCtxCG, useContext:useCtxCG, useState:useStateCG, useEffect:useEffectCG } = React;

const LEGACY_SECTION_MAP = {
  beshbarmak: 'sets', grill: 'sets', kazan: 'sets', sogym: 'sets', steaks: 'meat',
};
const DEPRECATED_CATEGORY_HANDLES = new Set([
  'shirts', 'sweatshirts', 'merch', 'pants', 'beshbarmak', 'grill', 'kazan', 'sogym', 'steaks',
]);

function parseMeta(meta){
  if(!meta) return {};
  if(typeof meta === 'string'){
    try{ return JSON.parse(meta); }catch(_){ return {}; }
  }
  return meta;
}

const DEFAULT_SHOP_SECTIONS = [
  { handle: 'sets', name: 'Наборы', name_kz: 'Жинақтар', icon: 'utensils-crossed', sort_order: 1 },
  { handle: 'meat', name: 'Мясная лавка', name_kz: 'Ет дүкені', icon: 'beef', sort_order: 2 },
  { handle: 'delicacy', name: 'Деликатесы', name_kz: 'Деликатестер', icon: 'crown', sort_order: 3 },
  { handle: 'broths', name: 'Бульоны', name_kz: 'Сорпалар', icon: 'soup', sort_order: 4 },
  { handle: 'semi', name: 'Полуфабрикаты', name_kz: 'Жартылай фабрикаттар', icon: 'package', sort_order: 5 },
];

function isTormenSectionMeta(meta){
  const v = meta?.tormen_section;
  return v === true || v === 'true';
}

function mapStoreSection(cat){
  if(!cat?.handle || cat.is_active === false || cat.is_internal) return null;
  if(DEPRECATED_CATEGORY_HANDLES.has(cat.handle)) return null;
  const meta = parseMeta(cat.metadata);
  if(meta.deprecated === true || meta.deprecated === 'true') return null;
  if(!isTormenSectionMeta(meta) && meta.tormen_section === false) return null;
  return {
    id: cat.id,
    handle: cat.handle,
    name: cat.name || cat.handle,
    name_kz: meta.name_kz || cat.name || cat.handle,
    icon: meta.icon || 'package',
    sort_order: parseInt(meta.sort_order ?? cat.rank ?? 99, 10) || 99,
    _fromMedusa: isTormenSectionMeta(meta),
  };
}

function normalizeSectionHandle(handle, known){
  if(!handle) return null;
  if(known.has(handle)) return handle;
  if(LEGACY_SECTION_MAP[handle]) return LEGACY_SECTION_MAP[handle];
  return null;
}
const VARIANT_OPTION_TITLES = [
  'Количество', 'количество', 'Quantity', 'Persons', 'Фасовка', 'фасовка', 'Size', 'Размер',
];

function shopSectionForCat(cat){
  return cat || 'sets';
}

function normalizeOptionTitle(t){
  return String(t || '').trim().toLowerCase();
}

function isVariantOptionTitle(title){
  const n = normalizeOptionTitle(title);
  return VARIANT_OPTION_TITLES.some(t=> normalizeOptionTitle(t) === n);
}

function parsePersonsFromChoice(value){
  const m = String(value).match(/(\d+)\s*(?:персон|persons|чел|человек|адам|п\.?)/i);
  return m ? parseInt(m[1], 10) : 0;
}

function parseVariantChoice(v){
  const vm = v.metadata || {};
  if(vm.choice) return String(vm.choice).trim();

  const opts = v.options || [];
  const hit = opts.find(o=> isVariantOptionTitle(o.option?.title) && o.value);
  if(hit) return String(hit.value).trim();

  const any = opts.find(o=> o.value && !/^default/i.test(String(o.value)));
  if(any) return String(any.value).trim();

  const lbl = (v.title || '').trim();
  if(lbl && !/^default\s+(variant|option)/i.test(lbl)) return lbl;
  return '';
}

function variantSortKey(v){
  if(v.persons > 0) return v.persons;
  const n = parseFloat(String(v.choice).replace(',', '.').replace(/[^\d.]/g, ''));
  return Number.isFinite(n) ? n : 9999;
}

function medusaCatalogEnv(){
  return window.TORMEN_ENV?.medusa || {};
}

function medusaAssetBase(){
  return (medusaCatalogEnv().backendUrl || 'http://localhost:9000').replace(/\/$/, '');
}

/** Medusa хранит абсолютные URL; после смены порта (9000→9002) картинки ломаются без переписывания. */
function normalizeMedusaAssetUrl(url){
  if(!url || typeof url !== 'string') return url;
  const path = url.match(/^https?:\/\/[^/]+(\/(?:static|uploads)\/.+)$/i);
  if(path) return medusaAssetBase() + path[1];
  return url;
}

async function catalogFetch(path){
  const { backendUrl, publishableKey } = medusaCatalogEnv();
  const ctrl = new AbortController();
  const timer = setTimeout(()=> ctrl.abort(), 12000);
  let res;
  try{
    res = await fetch(`${backendUrl}${path}`, {
      headers: {
        'Content-Type': 'application/json',
        'x-publishable-api-key': publishableKey,
      },
      signal: ctrl.signal,
    });
  }finally{ clearTimeout(timer); }
  let data = {};
  try{ data = await res.json(); }catch(_){}
  if(!res.ok) throw new Error(data.message || res.statusText || 'catalog_fetch_failed');
  return data;
}

function parseJsonArray(raw, fallback=[]){
  if(Array.isArray(raw)) return raw;
  try{ return JSON.parse(raw || '[]'); }catch(_){ return fallback; }
}

function productCatHandles(product, knownHandles){
  const known = knownHandles || new Set(DEFAULT_SHOP_SECTIONS.map(s=> s.handle));
  const handles = new Set();
  for(const c of (product.categories || [])){
    const raw = c?.handle;
    if(!raw || DEPRECATED_CATEGORY_HANDLES.has(raw)) continue;
    const h = normalizeSectionHandle(raw, known) || (known.has(raw) ? raw : raw);
    if(h) handles.add(h);
  }
  const m = product.metadata || {};
  if(m.shop_section){
    const h = normalizeSectionHandle(m.shop_section, known);
    if(h) handles.add(h);
  }
  if(m.cat){
    const h = normalizeSectionHandle(m.cat, known);
    if(h) handles.add(h);
  }
  return [...handles];
}

function productCatHandle(product, knownHandles){
  return productCatHandles(product, knownHandles)[0] || null;
}

function diagnoseProductSkip(product, knownHandles){
  const cat = productCatHandle(product, knownHandles);
  const priced = (product.variants || []).map(v=>{
    const price = Math.round(v.calculated_price?.calculated_amount ?? 0);
    const choice = parseVariantChoice(v);
    return { price, choice, ok: price > 0 && !!choice };
  });
  const okVariants = priced.filter(v=> v.ok);
  if(!cat && !okVariants.length) return 'no_category_and_no_price';
  if(!cat) return 'no_category';
  if(!okVariants.length) return priced.some(v=> v.price <= 0) ? 'no_kzt_price' : 'no_valid_variant';
  return null;
}

function mapMedusaProduct(product, knownHandles){
  const sectionHandles = productCatHandles(product, knownHandles);
  let cat = sectionHandles[0] || null;

  const m = product.metadata || {};
  const title = product.title || product.handle || '';
  const desc = product.description || '';

  let variants = (product.variants || []).map(v=>{
    const vm = v.metadata || {};
    const choice = parseVariantChoice(v);
    const persons = parsePersonsFromChoice(choice) || parseInt(vm.persons, 10) || 0;
    const price = Math.round(v.calculated_price?.calculated_amount ?? 0);
    return {
      choice,
      persons,
      label: choice || v.title || '',
      price,
      weight: vm.weight || (v.weight ? `${v.weight} г` : ''),
      medusaVariantId: v.id,
    };
  }).filter(v=> v.price > 0)
    .sort((a,b)=> variantSortKey(a) - variantSortKey(b));

  if(variants.length === 1 && !variants[0].choice) {
    variants = [{ ...variants[0], choice: '1' }];
  }
  variants = variants.filter(v=> v.choice);

  if(!variants.length) return null;
  if(!cat) cat = 'sets';
  const shopSections = sectionHandles.length ? sectionHandles : [cat];
  const shopSection = shopSectionForCat(cat);

  return {
    id: product.handle,
    medusaProductId: product.id,
    cat,
    shopSection,
    shopSections,
    badge: m.badge || null,
    best: m.best === 'true' || m.best === true,
    ph: m.ph || (cat === 'grill' ? 'grill' : cat === 'kazan' ? 'kazan' : 'cut'),
    name: { ru: m.name_ru || title, kz: m.name_kz || title },
    tagline: { ru: m.tagline_ru || '', kz: m.tagline_kz || '' },
    desc: { ru: m.desc_ru || desc, kz: m.desc_kz || desc },
    items: {
      ru: parseJsonArray(m.items_ru),
      kz: parseJsonArray(m.items_kz),
    },
    storage: {
      ru: String(m.storage_ru || '').trim(),
      kz: String(m.storage_kz || '').trim(),
    },
    variants,
    thumbnail: normalizeMedusaAssetUrl(product.thumbnail) || null,
    images: (product.images || []).map(i=> normalizeMedusaAssetUrl(i.url)).filter(Boolean),
  };
}

function setImageList(set){
  if(!set) return [];
  const imgs = (set.images || []).map(normalizeMedusaAssetUrl).filter(Boolean);
  if(imgs.length) return imgs;
  if(set.thumbnail) return [normalizeMedusaAssetUrl(set.thumbnail)];
  return [];
}

function setHasMedusaPhotos(set){
  return setImageList(set).length > 0;
}

function setImg(set, idx=0){
  const list = setImageList(set);
  if(list.length) return list[((idx % list.length) + list.length) % list.length];
  return window.imgFor?.(set?.id, idx) || null;
}

/** @deprecated alias */
function mapMedusaSet(product){ return mapMedusaProduct(product); }

function variantChip(v){
  return v.choice || v.label || '—';
}

function variantChoiceLabel(v, t){
  return v.choice || v.label || t('variant_standard');
}

function itemShopSections(item){
  const rawList = item?.shopSections?.length
    ? item.shopSections
    : [item?.shopSection || item?.cat || 'sets'];
  return rawList.map(raw=> LEGACY_SECTION_MAP[raw] || raw);
}

function medusaForSection(sets, section){
  return (sets || []).filter(s=> itemShopSections(s).includes(section));
}

function decodeRouteId(id){
  if(!id) return '';
  try{ return decodeURIComponent(id); }catch(_){ return id; }
}

function findSetById(sets, id){
  const raw = decodeRouteId(id);
  if(!raw) return null;
  return (sets || []).find(s=>
    s.id === raw || s.id === id
    || s.medusaProductId === raw || s.medusaProductId === id
  ) || null;
}

const CatalogContext = createCtxCG(null);

function CatalogProvider({ children }){
  const [sets, setSets] = useStateCG(()=> window.SETS || []);
  const [sections, setSections] = useStateCG(()=> window.TORMEN_SECTIONS || DEFAULT_SHOP_SECTIONS);
  const [loading, setLoading] = useStateCG(true);
  const [source, setSource] = useStateCG('static');
  const [regionId, setRegionId] = useStateCG(null);
  const configured = !!window.isMedusaConfigured?.();

  useEffectCG(()=>{
    if(!configured){
      setLoading(false);
      setSource('static');
      return;
    }

    let cancelled = false;
    (async ()=>{
      try{
        const { regions } = await catalogFetch('/store/regions?limit=50');
        const kz = (regions || []).find(r=> r.currency_code === 'kzt')
          || (regions || []).find(r=> (r.countries || []).some(c=> c.iso_2 === 'kz'))
          || regions?.[0];
        if(!kz) throw new Error('no_region');

        const { product_categories: storeCats } = await catalogFetch('/store/product-categories?limit=100');
        let shopSections = (storeCats || []).map(mapStoreSection).filter(Boolean);
        shopSections.sort((a,b)=> a.sort_order - b.sort_order || a.name.localeCompare(b.name, 'ru'));
        if(!shopSections.length) shopSections = DEFAULT_SHOP_SECTIONS;
        let knownHandles = new Set(shopSections.map(s=> s.handle));

        const fields = encodeURIComponent(
          '*variants,*variants.calculated_price,*variants.options,*variants.options.option,*categories,*images,+metadata,+thumbnail'
        );
        const { products } = await catalogFetch(
          `/store/products?limit=100&region_id=${kz.id}&fields=${fields}`
        );

        const mapped = [];
        const hidden = [];
        for(const p of (products || [])){
          const m = mapMedusaProduct(p, knownHandles);
          if(m){
            if(!productCatHandles(p, knownHandles).length) m._needsCategory = true;
            mapped.push(m);
          }else{
            const why = diagnoseProductSkip(p, knownHandles);
            if(why) hidden.push({ handle: p.handle, title: p.title, why });
          }
        }
        if(hidden.length) console.warn('[catalog] Товары не на витрине:', hidden);

        for(const p of (products || [])){
          for(const c of (p.categories || [])){
            const raw = c?.handle;
            if(!raw || knownHandles.has(raw) || DEPRECATED_CATEGORY_HANDLES.has(raw)) continue;
            shopSections.push({
              id: c.id || raw,
              handle: raw,
              name: c.name || raw,
              name_kz: parseMeta(c.metadata).name_kz || c.name || raw,
              icon: parseMeta(c.metadata).icon || 'package',
              sort_order: parseInt(parseMeta(c.metadata).sort_order ?? 99, 10) || 99,
            });
            knownHandles.add(raw);
          }
        }
        shopSections.sort((a,b)=> a.sort_order - b.sort_order || a.name.localeCompare(b.name, 'ru'));

        // Medusa is source of truth when configured — no static demo SETS/PRODUCTS
        const list = mapped;

        if(cancelled) return;
        setSets(list);
        setSections(shopSections);
        setRegionId(kz.id);
        setSource('medusa');
        window.SETS = list;
        window.TORMEN_SECTIONS = shopSections;
      }catch(e){
        console.warn('[catalog] Medusa error (empty catalog, no static fallback):', e.message);
        if(!cancelled){
          setSets([]);
          setSource('medusa-error');
        }
      }finally{
        if(!cancelled) setLoading(false);
      }
    })();

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

  const value = { sets, sections, loading, source, regionId, configured };
  return <CatalogContext.Provider value={value}>{children}</CatalogContext.Provider>;
}

function useCatalog(){ return useCtxCG(CatalogContext); }

Object.assign(window, {
  CatalogProvider, useCatalog, mapMedusaProduct, mapMedusaSet,
  variantChip, variantChoiceLabel, setImageList, setImg, setHasMedusaPhotos,
  normalizeMedusaAssetUrl, decodeRouteId, findSetById,
  medusaForSection, itemShopSections, productCatHandles, parseVariantChoice, DEFAULT_SHOP_SECTIONS,
});