# -*- coding: utf-8 -*-
"""
TRENDYOL TOPLU URUN SABLONUNU DOLDUR

Kullanici 7 Eyl 2026 Trendyol'un urun-olusturma sablonunu verdi ve
"kategori kategori urunleri yaz ve bana gonder" dedi. API'nin urun
ucu 426 verdigi icin toplu Excel yolu kullaniliyor.

VERI: veri_topla.php'nin urettigi ty_veri.json (449 satilabilir varyant)
MARKA ADI: marka_adlari.php (Trendyol'un kendi yazimi)

SABLON BOZULMUYOR: openpyxl sablonu acip yalniz satir ekliyor;
dogrulama listeleri ve Urun_Ozellik sayfalari oldugu gibi kaliyor.
Cikti AYRI bir dosyaya yazilir, kaynak sablon degismez.

    python excel_doldur.py
"""
import json, io, os, re, math, unicodedata
import openpyxl

SABLON = r'C:\Users\Mikro Pc\Desktop\urun-olusturma-1402308.xlsx'
CIKTI  = r'C:\Users\Mikro Pc\Desktop\Trendyol-Urunler-DOLU.xlsx'
# trendyol_fiyat.php'nin urettigi ZENGIN dosya: ty_fiyat / desi / kargo
# iceriyor. Trendyol fiyati AYRI politikadir (taban + Trendyol kargosu,
# %19 komisyon icerecek sekilde), Shopify fiyati kullanilmaz.
VERI   = r'C:\Users\MIKROP~1\AppData\Local\Temp\claude\ty_veri_fiyatli.json'
ADLAR  = r'C:\xampp\htdocs\shopify\trendyol\marka_adlari.php'
# canli_dok.php uretir: barkod -> [modelKodu, marka] (Trendyol'daki hali)
CANLI  = r'C:\Users\MIKROP~1\AppData\Local\Temp\claude\ty_canli_model.json'

MENSEI = 'TR'                 # kullanici: "mensei turkiye"
STOK_TAKIPSIZ = 25            # zarf gibi takibi kapali kalemler icin BEYAN
SEVK_SURESI = 3               # is gunu

# ---------------------------------------------------------------- marka adi
def marka_adlari():
    s = io.open(ADLAR, encoding='utf-8').read()
    d = {}
    for m in re.finditer(r"'((?:[^'\\]|\\.)*)'\s*=>\s*'((?:[^'\\]|\\.)*)'", s):
        d[m.group(1).replace("\\'", "'")] = m.group(2).replace("\\'", "'")
    return d

# ------------------------------------------------------------ yardimcilar
def kisalt(s, n):
    s = re.sub(r'\s+', ' ', (s or '')).strip()
    return s if len(s) <= n else s[:n-1].rstrip() + '.'

def desi(kg):
    """Trendyol desi tam sayi ister; kilodan asagi yuvarlanmaz."""
    try: kg = float(kg)
    except Exception: kg = 0.0
    return max(1, int(math.ceil(kg)))

def gramaj_kovasi(gr, izin):
    """Etiketteki gramaji sablonun izin verdigi degere oturtur.
    Tam karsilik varsa onu, yoksa araligi kullanir. Hicbiri
    tutmuyorsa BOS birakir - opsiyonel alana yanlis deger yazmaktan
    iyidir."""
    tam = '%d gr' % gr
    if tam in izin: return tam
    for aday, alt, ust in (('0-24gr',0,24), ('25 - 49 gr',25,49),
                           ('50 - 99 gr',50,99), ('100 - 149 gr',100,149),
                           ('140 - 199 gr',150,199), ('200 - 249 gr',200,249)):
        if alt <= gr <= ust and aday in izin: return aday
    if gr >= 250 and '250+' in izin: return '250+'
    return ''

# 2797 Kagit Tipi eslemesi. Buyuk ebat tabaka kagitlarin karsiligi
# sablonda "Tabaka Kagitlar" olarak VAR - o yuzden 70x100 kagitlari
# yanlis bir A4 boyutuna zorlamak gerekmiyor (Kagit Boyutu opsiyonel).
KAGIT_TIPI = {
    'Fotokopi Kağıdı':        'Beyaz Fotokopi Kağıdı',
    'Renkli Fotokopi Kağıdı': 'Renkli Fotokopi Kağıdı',
}
KAGIT_TIPI_VARSAYILAN = 'Tabaka Kağıtlar'

def slug(s):
    """Marka adini model koduna eklenecek hale getirir. Turkce harfler
    ASCII'ye katlanir - model kodu ASCII olmali."""
    s = (s or '').strip()
    for a, b in (('İ','i'),('I','i'),('ı','i'),('Ü','u'),('ü','u'),
                 ('Ö','o'),('ö','o'),('Ş','s'),('ş','s'),('Ç','c'),
                 ('ç','c'),('Ğ','g'),('ğ','g')):
        s = s.replace(a, b)
    s = s.lower()
    s = re.sub(r'[^a-z0-9]+', '-', s).strip('-')
    return s or 'genel'

def model_kodu(s, marka, canli):
    """HER BARKODA KENDI MODEL KODU.

    Trendyol hatasi: "Ayni kategori, model kodu, marka bilgisine sahip
    sadece bir barkodunuz bulunmaktadir. Referans Barkod: KGT11ZEUSM
    ... model kodunu farkli olacak sekilde guncelleyiniz."

    OLCULEN SEBEP: model kodu Shopify handle'iydi, yani ayni urunun
    butun varyantlari tek model koduna dusuyordu. Trendyol model
    kodunu VARYANT GRUBU sayiyor ve gruptaki barkodlari bir varyant
    ozelliginden (Renk / Beden / Ebat) ayirt etmek istiyor.
    Bizim kategorilerde bu ozellik ya yok ya bos:
        2013 Ofis Sarf  -> tek ozellik Mensei, ayirt edici YOK
        2797 Kagitlar   -> Kagit Boyutu yalniz A3-C4 kabul ediyor,
                           70x100 tabakada bos birakildi
    Ayirt edilemeyen barkodlar reddediliyor. Kanit: TOYO'nun 26
    satirindan yalniz 7'si yuklenebilmis, ZEUS'un 2'si girmis ve
    ucuncu satir KGT11ZEUSM'e carpmis.

    COZUM: model kodu = barkod. Her urun kendi basina duruyor,
    gruplama olmadigi icin ayirt etme sorunu da yok.
    BEDELI: varyantlar urun sayfasinda tek listede toplanmiyor.
    Kategori ozelliklerini (Renk/Ebat) eksiksiz doldurabildigimizde
    gruplama geri getirilebilir.

    CANLI URUNE DOKUNULMAZ: Trendyol'da zaten olan barkodun model
    kodu ve markasi AYNEN korunur - degistirmek ayni urunu ikinci kez
    olusturur. (Zaten canli satirlar dosyaya hic yazilmiyor.)
    """
    b = s.get('barkod')
    if b and b in canli:
        return canli[b][0], canli[b][1]      # (model kodu, marka)
    return b, marka

def urun_adi(s):
    """Trendyol urun adi 100 karakter. Urun + secenekler, tekrar eden
    kelimeler atilir."""
    parca = [s['urun']]
    for k, v in s['sec'].items():
        v = (v or '').strip()
        if not v or v.lower() in ('diğer', 'diger'): continue
        if v.lower() in ' '.join(parca).lower(): continue
        parca.append(v)
    return kisalt(' '.join(parca), 100)

def urun_aciklamasi(s):
    sec = ' · '.join('%s: %s' % (k, v) for k, v in s['sec'].items()
                     if v and str(v).strip())
    p = []
    p.append('<p><strong>%s</strong> — %s</p>' % (s['urun'], sec))
    if s.get('kg'):
        p.append('<p>Paket ağırlığı yaklaşık <strong>%s kg</strong>.</p>'
                 % ('%.2f' % float(s['kg'])).replace('.', ','))
    p.append('<p>Fiyat KDV dahildir. Kağıtçınız / TBM Kağıt stoklarından '
             'gönderilir. Ürün kodu: %s</p>' % s['sku'])
    p.append('<p>Farklı ebat, gramaj veya miktar için bize ulaşın; '
             'matbaa ve dijital baskı işletmelerine toptan tedarik '
             'yapıyoruz.</p>')
    return ''.join(p)

# ------------------------------------------------------------------- ana
def main():
    veri = json.load(io.open(VERI, encoding='utf-8'))
    ad_h = marka_adlari()
    # Trendyol'da zaten olan barkodlarin model kodu/markasi korunur
    try:
        canli = json.load(io.open(CANLI, encoding='utf-8'))
    except Exception:
        canli = {}
    print('Trendyol\'da mevcut barkod: %d (model kodu korunacak)' % len(canli))
    wb = openpyxl.load_workbook(SABLON)

    # kategori kodu -> sayfa adi
    sayfa = {}
    for ad in wb.sheetnames:
        m = re.search(r'\((\d+)\)\s*$', ad)
        if m and not ad.startswith('Urun_Ozellik'):
            sayfa[int(m.group(1))] = ad

    # sayfa basina izin verilen ozellik degerleri
    izin = {}
    for kod, sad in sayfa.items():
        oz = 'Urun_Ozellik_Bilgileri_%d' % kod
        izin[kod] = {}
        if oz not in wb.sheetnames: continue
        ws = wb[oz]
        for c in range(1, ws.max_column + 1):
            bas = ws.cell(row=1, column=c).value
            if not bas: continue
            vals = set()
            for r in range(2, ws.max_row + 1):
                v = ws.cell(row=r, column=c).value
                if v not in (None, ''): vals.add(str(v).strip())
            izin[kod][str(bas).strip()] = vals

    # sayfa basina baslik -> kolon no
    kol = {}
    for kod, sad in sayfa.items():
        ws = wb[sad]
        kol[kod] = {}
        for c in range(1, ws.max_column + 1):
            v = ws.cell(row=1, column=c).value
            if v: kol[kod][str(v).strip()] = c

    satir = dict((k, 2) for k in sayfa)      # 2. satirdan basla
    say = dict((k, 0) for k in sayfa)
    atlanan, uyari = [], []
    # Satirlar ayrica JSON'a dokuluyor: xlsx_enjekte.py bunlari
    # OZGUN sablonun icine gomuyor. openpyxl ile yeniden kaydetmek
    # Trendyol'un logosunu, sharedStrings ve yazici ayarlarini
    # dusurdugu icin yukleyici "kayit edilecek satir bulunamadi"
    # diyordu.
    dokum = {}

    canliAtlanan = 0
    for s in veri:
        kod = int(s['kat'])
        if kod not in sayfa:
            atlanan.append((s['sku'], 'sablonda %d sayfasi yok' % kod)); continue
        # TRENDYOL'DA ZATEN OLANI DOSYAYA YAZMA. Fiyatlari API'den
        # guncellendi; tekrar yuklemek ya ayni model kodu hatasini
        # tekrar dogurur ya kopya urun olusturur.
        if s.get('barkod') in canli:
            canliAtlanan += 1; continue
        ws = wb[sayfa[kod]]
        K = kol[kod]
        r = satir[kod]

        kayit = {}

        def yaz(bas, deger):
            c = K.get(bas)
            if c and deger not in (None, ''):
                ws.cell(row=r, column=c).value = deger
                kayit[bas] = deger

        mk = s.get('marka_ad')
        marka = ad_h.get(mk, 'Etiketsiz') if mk else 'Etiketsiz'
        model, marka = model_kodu(s, marka, canli)
        stok = s['stok'] if s['izleme'] else STOK_TAKIPSIZ
        # ty_fiyat = (taban + Trendyol kargosu) / (1 - komisyon).
        # Shopify fiyatina DUSMEZ; dusuyorsa hesap yapilmamis demektir.
        fiyat = round(float(s.get('ty_fiyat') or s['fiyat']), 2)

        yaz('Barkod', s['barkod'])
        yaz('Model Kodu', model)
        yaz('Marka', marka)
        yaz('Kategori', kod)
        yaz('Para Birimi', 'TRY')
        yaz('Ürün Adı', urun_adi(s))
        yaz('Ürün Açıklaması', urun_aciklamasi(s))
        # Piyasa fiyati ile satis fiyati AYNI: uydurma bir liste fiyati
        # yazmak musteriyi yaniltir.
        yaz('Piyasa Satış Fiyatı (KDV Dahil)', fiyat)
        for b in K:
            if b.startswith("Trendyol'da Satılacak Fiyat"): yaz(b, fiyat)
        yaz('Ürün Stok Adedi', stok)
        yaz('Stok Kodu', s['sku'])
        yaz('KDV Oranı', int(s['kdv']))
        # Kargo hangi desiye gore fiyatlandiysa Excel'e o yazilir -
        # ikisi ayrisirsa Trendyol farkli bir desiden faturalandirir.
        yaz('Desi', int(s['desi']) if s.get('desi') else desi(s.get('kg')))
        yaz('Sevkiyat Süresi', SEVK_SURESI)
        for i, u in enumerate(s.get('gorsel') or [], start=1):
            if i > 8: break
            yaz('Görsel %d' % i, u)
        yaz('Menşei', MENSEI)

        # ---- kategoriye ozel opsiyonel ozellikler ----
        if kod == 2797:
            tip = KAGIT_TIPI.get(s['urun'], KAGIT_TIPI_VARSAYILAN)
            if tip in izin[kod].get('Kağıt Tipi', set()): yaz('Kağıt Tipi', tip)
            et = ' '.join([s['et']] + list(s['sec'].values()))
            mb = re.search(r'\b(A3|A4|A5|A6|B5|C4)\b', et, re.I)
            if mb:
                v = mb.group(1).upper()
                if v in izin[kod].get('Kağıt Boyutu', set()): yaz('Kağıt Boyutu', v)
            mg = re.search(r'(\d{2,3})\s*gr', et, re.I)
            if mg:
                g = gramaj_kovasi(int(mg.group(1)), izin[kod].get('Gramaj', set()))
                if g: yaz('Gramaj', g)
        elif kod == 2796:
            et = ' '.join([s['et']] + list(s['sec'].values()))
            mp = re.search(r'(\d{1,4})\s*ad', et, re.I)
            if mp:
                for aday in ("%s'li" % mp.group(1), "%s'lu" % mp.group(1),
                             "%s'lü" % mp.group(1), "%s'lı" % mp.group(1)):
                    if aday in izin[kod].get('Paket İçeriği', set()):
                        yaz('Paket İçeriği', aday); break
            for renk in izin[kod].get('Renk', set()):
                if len(renk) < 4: continue
                if re.search(r'\b%s\b' % re.escape(renk), et, re.I):
                    yaz('Renk', renk); break

        dokum.setdefault(sayfa[kod], []).append(kayit)
        satir[kod] += 1
        say[kod] += 1

    if os.path.exists(CIKTI): os.remove(CIKTI)
    wb.save(CIKTI)
    DOKUM = r'C:\Users\MIKROP~1\AppData\Local\Temp\claude\ty_satirlar.json'
    json.dump(dokum, io.open(DOKUM, 'w', encoding='utf-8'), ensure_ascii=False)

    print('=== YAZILAN SATIRLAR ===')
    for kod in sorted(sayfa):
        print('  %-40s %4d satir' % (sayfa[kod][:40], say[kod]))
    print('  TOPLAM %d satir' % sum(say.values()))
    print('  (Trendyol\'da zaten olan %d satir yazilmadi - fiyatlari'
          ' API\'den guncellendi)' % canliAtlanan)
    if atlanan:
        print('\n=== ATLANAN ===')
        for a in atlanan[:10]: print('  %-30s %s' % a)
    print('\nCikti: %s  (%s bayt)' % (CIKTI, format(os.path.getsize(CIKTI), ',')))

if __name__ == '__main__':
    main()
