<template>
  <!-- ===========================================================
       🧾 ORDER ENTRY PAGE (BSSApp)
       v22 — Model + Renk + 2. Renk + Beden/Stok Otomatik Eşleme
  ============================================================ -->
                <q-page class="q-pa-md order-page">
                  <div class="order-scroll-x">
                    <div class="order-width">
                    <div class="row items-center q-mb-xs">
                <q-chip
                  :color="isEditMode ? 'blue-7' : 'green-7'"
                  text-color="white"
                  icon="edit"
                  v-if="isEditMode"
                >
                  Düzenleme Modu
                </q-chip>
                <q-chip
                  text-color="white"
                  icon="add_circle"
                  v-else
                >
                  Yeni Sipariş
                </q-chip>
              </div>

       <!-- =======================================================
     🔹 FILTER BAR — OrderHeader Bilgileri
     SQL eşleşmeli alanlar
======================================================= -->
          <div class="filter-bar row q-col-gutter-md q-mb-sm">

  <!-- 🧾 Cari Seçimi -->
  <div class="col-5">
    <q-select
      v-model="form.CurrAccCode"
      :options="filteredCariOptions"
      label="Cari Seçimi"
      filled
      use-input
      input-debounce="300"
      emit-value
      map-options
      option-value="Cari_Kod"
      :option-label="opt => `${opt.Cari_Kod} - ${opt.Cari_Ad}`"
      @filter="filterCari"
      @update:model-value="onCariChange"
      :loading="loadingCari"
      behavior="menu"
      clearable
    >
      <template #option="scope">
        <q-item v-bind="scope.itemProps">
          <q-item-section>
            <q-item-label>{{ scope.opt.Cari_Ad }}</q-item-label>
            <q-item-label caption>{{ scope.opt.Cari_Kod }}</q-item-label>
          </q-item-section>
        </q-item>
      </template>
    </q-select>
  </div>

  <!-- 🔢 Sipariş No -->
  <div class="col-2">
    <q-input
      v-model="form.OrderNumber"
      label="Sipariş No"
      filled
      dense
      :readonly="isEditMode"
    />
  </div>

  <!-- 📅 Oluşturulma Tarihi -->
  <div class="col-2">
    <q-input
      v-model="form.OrderDate"
      label="Oluşturulma Tarihi"
      type="date"
      filled
      dense
    />
  </div>

  <!-- 📅 Tahmini Termin Tarihi -->
  <div class="col-2">
    <q-input
      v-model="form.AverageDueDate"
      label="Tahmini Termin Tarihi"
      type="date"
      filled
      dense
    />
  </div>

  <!-- 💰 TOPLAM TUTAR + KDV -->
  <div class="col-12 row items-center q-gutter-sm q-mt-sm">

    <div class="col-3">
      <q-input
        dense
        filled
        v-model.number="toplamTutar"
        label="Toplam Tutar"
        readonly
        :suffix="form.pb"
      />
    </div>

    <div class="col-auto">
      <q-checkbox
        v-model="includeKDV"
        label="KDV Dahil"
      />
    </div>

    <div class="col-2">
      <q-input
        dense
        filled
        v-model.number="manualKDV"
        label="KDV"
        readonly
        suffix="%"
      />
    </div>

    <div class="col-3">
      <q-input
        dense
        filled
        :model-value="toplamKDVli.toFixed(2)"
        label="KDV Dahil Toplam"
        readonly
        :suffix="form.pb"
      />
    </div>
  </div>
</div>

          <!-- 🔸 Cari Bilgi Kutuları -->
          <q-slide-transition>
            <div v-if="cariInfo" class="row q-col-gutter-md q-mt-xs cari-info-bar">
              <div class="col-3"><q-input :model-value="cariInfo.Musteri_Temsilcisi || '-'" label="Müşteri Temsilcisi" filled dense readonly /></div>
              <div class="col-3"><q-input :model-value="cariInfo.Musteri_Ana_Grubu || '-'" label="Ana Grup" filled dense readonly /></div>
              <div class="col-3"><q-input :model-value="cariInfo.Piyasa || '-'" label="Piyasa" filled dense readonly /></div>
              <div class="col-3"><q-input :model-value="cariInfo.Ulke || '-'" label="Ülke" filled dense readonly /></div>
            </div>
          </q-slide-transition>

          <!-- 🔹 SAVE TOOLBAR -->
          <div class="save-toolbar">
            <div class="text-subtitle2 text-weight-bold">Sipariş Formu</div>
            <!-- =======================================================
     🔹 KAYDET / GÜNCELLE BUTONU
======================================================= -->
<q-btn
  :label="isEditMode ? 'TÜMÜNÜ GÜNCELLE' : 'TÜMÜNÜ KAYDET'"
  color="primary"
  icon="save"
  class="q-ml-sm"
  :loading="orderStore.loading"
  @click="submitAll"
/>

<!-- =======================================================
     🔹 YENİ SİPARİŞ / FORM SIFIRLA BUTONU
======================================================= -->
<q-btn
  label="YENİ SİPARİŞ"
  color="secondary"
  icon="add_circle"
  class="q-ml-sm"
  @click="resetForm"
/>

          </div>

          <!-- 🔹 GRID HEADER -->
          <div class="order-grid-header">
            <div class="col-fixed model">MODEL</div>
            <div class="col-fixed renk">RENK</div>
            <div class="col-fixed ana">ÜRÜN ANA<br />GRUBU</div>
            <div class="col-fixed alt">ÜRÜN ALT<br />GRUBU</div>
            <div class="col-fixed aciklama-col">AÇIKLAMA</div>

            <div class="beden-block">
              <div v-for="grp in schema" :key="grp.key" class="grp-row" :class="{ 'hl-pan': grp.key === 'pan' && highlightPantolon }">
                <div class="grp-title">{{ grp.title }}</div>
                <div class="grp-body">
                  <div v-for="v in grp.values" :key="'b-' + grp.key + '-' + v" class="grp-cell hdr">
                    {{ v }}
                  </div>
                </div>
              </div>
            </div>

            <div class="total-row">
              <div class="total-cell">ADET</div>
              <div class="total-cell">FİYAT</div>
              <div class="total-cell">PB</div>
              <div class="total-cell">TUTAR</div>
              <div class="total-cell">Tahmini Gönderim Tarihi</div>
            </div>
          </div>
        </div>
        <!-- =======================================================
             🔹 GRID BODY
        ======================================================== -->
        <div class="order-grid-body">
          <template v-for="grp in groupedRows" :key="grp.name">
            <div :class="['summary-group', grp.open ? 'open' : 'closed']">

              <!-- 🟡 Sub-header -->
              <div class="order-sub-header" @click="toggleGroup(grp.name)">
                <div class="sub-left">{{ grp.name }}</div>
                <div class="sub-center">
                  <div
                    v-for="v in (grp.bedenValues || [])"
                    :key="'hdr-' + v"
                    class="beden-cell"
                  >
                    {{ v }}
                  </div>
                </div>
                <div class="sub-right">
                  <div class="text-caption">
                    Toplam {{ grp.name }} Adet: {{ grp.toplamAdet }}
                  </div>
                  <div class="text-caption">
                    Toplam {{ grp.name }} Tutar:
                    {{ Number(grp.toplamTutar||0).toLocaleString('tr-TR',{minimumFractionDigits:2}) }} {{ form.pb || aktifPB }}
                  </div>
                  <q-icon :name="grp.open ? 'expand_less' : 'expand_more'" size="20px" class="cursor-pointer text-grey-8 q-ml-sm" />
                </div>
              </div>

              <!-- 🧩 Grup satırları -->
              <template v-if="grp.open">
                <div
                  v-for="({ row }, i) in grp.rows"
                  :key="i"
                  class="summary-row"
                  :class="{
                    active: editingIndex === summaryRows.findIndex(r => r === row),
                    'is-editing': editingIndex === summaryRows.findIndex(r => r === row)
                  }"
                  @click="editRow(row, i)"
                >
                  <!-- Sol kolonlar -->
                  <div class="cell model">{{ row.model }}</div>
                  <div class="cell renk">{{ row.renk }}{{ row.renk2 ? '-' + row.renk2 : '' }}</div>
                  <div class="cell ana">{{ row.urunAnaGrubu }}</div>
                  <div class="cell alt">{{ row.urunAltGrubu }}</div>
                  <div class="cell aciklama">{{ row.aciklama }}</div>

                  <!-- Beden kolonları -->
                  <div class="grp-area">
                    <div class="grp-row">
                      <div v-for="v in (schemaByKey[row.grpKey]?.values || [])" :key="'val-' + v" class="cell beden">
                        {{ row.bedenMap?.[row.grpKey]?.[v] ?? '' }}
                      </div>
                      <div v-for="i in (16 - (schemaByKey[row.grpKey]?.values?.length || 0))" :key="'empty-' + i" class="cell beden ghost"></div>
                    </div>
                  </div>

                  <!-- Sağ kolonlar -->
                  <div class="cell adet">{{ row.adet }}</div>
                  <div class="cell fiyat">{{ row.fiyat }}</div>
                  <div class="cell pb">{{ row.pb }}</div>
                  <div class="cell tutar">
                    {{ Number(row.tutar || 0).toLocaleString('tr-TR', { minimumFractionDigits: 2 }) }}
                  </div>
                  <!-- ESKİ (inline düzenlenebilir) -->
                <!-- 🔹 Termin Tarihi — sadece gösterge -->
                    <!-- 🔹 Termin Tarihi — sadece gösterge -->
                    <div class="cell termin">
                      <div class="termin-label text-center">
                        {{ formatDate(row.terminTarihi)  }}
                      </div>
                    </div>



                </div>
              </template>
            </div>
          </template>
        </div>
        <!-- =======================================================
             🔹 SATIR DÜZENLEYİCİ FORM (EDITOR)
        ======================================================== -->
        <div class="editor q-mt-lg q-pa-sm">

          <!-- 🔸 1. Satır: Model ve Ürün Bilgileri -->
          <div class="row q-col-gutter-sm q-mb-sm">
            <div class="col-3">
              <!-- 🔹 Model Seçimi -->
              <q-select
                v-model="form.model"
                :options="filteredModelOptions"
                label="Model"
                filled dense
                use-input input-debounce="250"
                emit-value map-options
                option-value="value"
                option-label="label"
                clearable behavior="menu"
                hint="Model kodu ile arayabilirsiniz"
                :loading="loadingModels"
                :disable="isEditing"
                @filter="filterModel"
                @update:model-value="(val) => useComboWatcher('model', onModelChange)(val)"
              />

              <!-- 🔹 1. Renk Seçimi -->
              <div class="q-mt-sm">
                <q-select
                  ref="renkSelect"
                  v-model="form.renk"
                  :options="renkOptions"
                  label="Renk"
                  filled dense clearable
                  emit-value map-options
                  option-value="value"
                  option-label="label"
                  :disable="isEditing"
                  @update:model-value="(val) => useComboWatcher('renk', onColorChange)(val)"
                />
              </div>

              <!-- 🔹 2. Renk Seçimi -->
              <div class="q-mt-sm">
                <q-select
                  ref="renk2Select"
                  v-model="form.renk2"
                  :options="renkOptions2"
                  label="2. Renk"
                  filled dense clearable
                  emit-value map-options
                  option-value="value"
                  option-label="label"
                  :disable="!renkOptions2.length || isEditing"
                  @update:model-value="(val) => useComboWatcher('renk2', onColor2Change)(val)"
                />
              </div>
            </div>

            <!-- Ürün teknik alanları -->
            <div class="col-2">
              <q-input v-model="form.urunAnaGrubu" label="Ürün Ana Grubu" filled dense readonly />
            </div>
            <div class="col-1">
              <q-input v-model="form.urunAltGrubu" label="Alt Grup" filled dense readonly />
            </div>
            <div class="col-1">
              <q-input v-model="form.fit" label="Fit" filled dense readonly />
            </div>
            <div class="col-2">
              <q-input v-model="form.urunIcerik" label="İçerik" filled dense readonly />
            </div>
            <div class="col-1">
              <q-input v-model="form.drop" label="Drop" filled dense readonly />
            </div>
            <div class="col-1">
              <q-input v-model="form.askiliyan" label="ASKILI/YAN" filled dense readonly />
            </div>
            <div class="col-1">
              <q-input v-model="form.kategori" label="Kategori" filled dense readonly />
            </div>
          </div>

          <!-- 🔸 2. Satır: Seri Seçimi -->
          <div class="row q-col-gutter-sm q-mt-xs">
            <div class="col-3">
              <q-select
                v-if="activeSeriesOptions && activeSeriesOptions.length"
                v-model="selectedSeriSet"
                :options="activeSeriesOptions"
                label="Beden Seti Seç"
                filled dense
                emit-value map-options
                option-value="value"
                option-label="label"
              />
            </div>

            <div class="col-2 q-mt-sm">
              <q-input
                v-if="selectedSeriSet"
                v-model.number="seriMultiplier"
                type="number"
                label="Çarpan"
                min="1"
                filled dense
              />
            </div>

            <div class="col-2 q-mt-sm">
              <q-btn
                v-if="selectedSeriSet"
                color="primary"
                icon="add"
                label="Seri Ekle"
                @click="applySeriSet"
              />
            </div>
          </div>

          <!-- =======================================================
               🔹 BEDEN GİRİŞ ALANI + STOK ETİKETİ GÖRÜNÜMÜ
          ======================================================== -->
          <div class="row q-mt-sm q-col-gutter-xs beden-grid">
            <div
              v-for="(lbl, i) in form.bedenLabels || []"
              :key="'beden-'+i"
              class="col-auto beden-wrap"
            >
              <div class="beden-label">{{ lbl }}</div>

              <q-input
                v-model.number="form.bedenler[i]"
                dense outlined type="number" min="0"
                style="width:60px"
                @focus="activeBeden = i"
                @blur="activeBeden = null"
                @update:model-value="updateTotals(form)"
                :class="{ 'beden-active': activeBeden === i }"
              />

              <div
                v-if="getStockFor(lbl) !== null"
                class="stok-label text-caption text-center q-mt-xs"
                :class="stockColorClass(getStockFor(lbl))"
              >
                Stok: {{ getStockFor(lbl) }}
              </div>
            </div>
          </div>

          <!-- 🔹 Aktif beden için küçük stok etiketi -->
          <div
            v-if="form.model && activeBeden !== null && getStockFor(form.bedenLabels[activeBeden]) !== null"
            class="stok-label-sm"
            :class="stockColorClass(getStockFor(form.bedenLabels[activeBeden]))"
          >
            Stok: {{ getStockFor(form.bedenLabels[activeBeden]) }}
          </div>

          <!-- =======================================================
               🔹 ADET / FİYAT / PB / TUTAR
          ======================================================== -->
          <div class="row q-mt-sm q-col-gutter-sm">
            <div class="col-2">
              <q-input v-model.number="form.adet" label="Adet" dense filled readonly />
            </div>
            <div class="col-2">
              <q-input
                v-model.number="form.fiyat"
                label="Fiyat"
                dense filled type="number" min="0"
                @update:model-value="() => updateTotals(form)"
              />
            </div>
            <div class="col-2">
              <q-select v-model="form.pb" :options="paraBirimOptions" label="PB" dense filled />
            </div>
            <div class="col-3">
              <q-input v-model="form.tutar" label="Tutar" dense filled readonly />
            </div>
          </div>

          <!-- =======================================================
               🔹 SATIR BAZINDA TAHMİNİ TERMİN TARİHİ
          ======================================================== -->
          <div class="row q-mt-sm">
            <div class="col-4">
              <q-input
                v-model="form.terminTarihi"
                type="date"
                label="Tahmini Termin Tarihi"
                filled dense
              />
            </div>
          </div>

          <!-- =======================================================
               🔹 AÇIKLAMA ALANI
          ======================================================== -->
          <div class="row q-mt-sm">
            <div class="col-12">
              <q-input
                v-model="form.aciklama"
                label="Açıklama"
                type="textarea"
                filled dense autogrow
                maxlength="1500" counter
              />
            </div>
          </div>

          <!-- =======================================================
               🔹 BUTONLAR (Kaydet / Güncelle / Sil / Temizle)
          ======================================================== -->
          <div class="row justify-between items-center q-mt-md">
            <div class="row q-gutter-sm">
              <q-btn
                :color="editingIndex === -1 ? 'primary' : 'positive'"
                :label="editingIndex === -1 ? 'Kaydet' : 'Güncelle'"
                @click="saveOrUpdate"
              />
              <q-btn
                v-if="editingIndex !== -1"
                color="negative" flat label="Satırı Sil"
                @click="removeSelected"
              />
              <q-btn
                flat color="grey-8"
                label="Formu Temizle"
                @click="resetForm"
              />
            </div>
          </div>

          <!-- =======================================================
               🔹 ALT BİLGİLENDİRME ALANI
          ======================================================== -->
          <div class="q-mt-md text-caption text-grey-7 text-center">
            <q-icon name="info" size="16px" class="q-mr-xs" />
            Bu sayfada yapılan siparişler henüz gönderilmemiştir.
            <br />
            <span class="text-negative">"Tümünü Kaydet (Toplu Gönder)"</span>
            butonuna basarak işlemleri kaydedebilirsiniz.
          </div>

          <!-- =======================================================
               🔹 SİPARİŞ GENEL AÇIKLAMASI
          ======================================================== -->
          <div class="row q-mt-md">
            <div class="col-12">
              <q-input
                v-model="form.Description"
                type="textarea"
                label="Sipariş Genel Açıklaması"
                filled dense autogrow
                maxlength="1500"
                counter
                placeholder="Siparişe genel açıklama giriniz (örn. teslimat, üretim notu, müşteri isteği...)"
              />
            </div>
          </div>

        </div> <!-- editor -->
      </div> <!-- order-width -->
    </div> <!-- order-scroll-x -->
  </q-page>
</template>

<script setup>
/* ===========================================================
   🧩 ORDER ENTRY (v22-final)
   Tüm fonksiyonları kapsayan gelişmiş setup bloğu.
   Bu dosya backend ile sıkı entegredir, axios ve Pinia store
   ile veri alışverişi yapar.
=========================================================== */

// Vue çekirdek importları
import { ref, reactive, computed, onMounted, watch, onBeforeUnmount, nextTick } from 'vue'
import { api } from 'boot/axios'
import { useRoute, useRouter } from 'vue-router'  // ✅ Buradan olmalı
import { useQuasar } from 'quasar'
import axios from 'axios'
import { useOrderentryStore } from 'src/stores/orderentryStore'
import dayjs from 'dayjs'

const route = useRoute()
const router = useRouter()
const $q = useQuasar()
const orderId =
  route.params.id ||
  route.query.id ||
  route.query.orderId ||
  null

console.log('🧩 Route parametresi alındı (setup başında):', orderId)
const isEditMode = ref(false)
// ===========================================================
// 🔹 Mode & Transaction State
// Yeni sipariş mi, düzenleme mi kontrolü için
// ===========================================================
const mode = ref('new') // 'new' | 'edit'
const txId = ref('')
const headerId = ref('')                  // Quasar bileşenleri ve $q.notify kullanımı için
const orderStore = useOrderentryStore()    // Pinia store: siparişler, localStorage, API çağrıları

// 🔹 Genel reaktif değişkenler
const aktifPB = ref('USD')                 // Varsayılan para birimi (Cari seçimiyle değişebilir)
const siparisNo = ref('SP-2025-001')       // Geçici sipariş numarası örneği
const allSeriesSets = ref([])              // Seri listeleri (seriMatrix'ten dinamik doldurulur)
/* ===========================================================
   🗓️ SİPARİŞ TARİHLERİ — Varsayılan Değerler
   Oluşturulma tarihi = bugünün tarihi
   Tahmini termin tarihi = bugünden + 5 hafta (35 gün)
=========================================================== */
const today = new Date()
const terminDate = new Date(today)
terminDate.setDate(today.getDate() + 35) // 5 hafta sonrası

const defaultOlusturmaTarihi = today.toISOString().substring(0, 10)
const defaultTerminTarihi = terminDate.toISOString().substring(0, 10)
// 💰 KDV Hesaplama Alanları
const includeKDV = ref(false)     // KDV kutusu işaretli mi?
const manualKDV = ref(0)          // Kullanıcının elle girdiği KDV tutarı
const kdvOrani = 0.10             // Varsayılan %10 oran

/* ===========================================================
   🔹 FORM TANIMI (reactive form)
   Tüm giriş alanları ve hesaplanan değerler tek reactive obje içinde.
=========================================================== */

const form = reactive({
  /* =========================================================
     🔹 TEMEL ALANLAR
  ========================================================= */
  OrderHeaderID: '',                     // string (GUID)
  OrderTypeCode: 1,                      // int8
  ProcessCode: 'WS',                     // string
  OrderNumber: '',                       // string
  OrderTime: dayjs().format('HH:mm:ss'), // saat formatı (örn. "14:35:22")
  IsCancelOrder: false,

  /* =========================================================
     🔹 ADRES / REFERANS ALANLARI
  ========================================================= */
  BillingPostalAddressID: '',
  GuarantorContactID: '',
  ApplicationCode: '',
  ApplicationID: '',

  /* =========================================================
     🔹 TARİH / AÇIKLAMA
  ========================================================= */
  OrderDate: dayjs().format('YYYY-MM-DD'),
  AverageDueDate: dayjs().add(30, 'day').format('YYYY-MM-DD'),
  Description: '',
  InternalDescription: '',

  /* =========================================================
     🔹 CARİ BİLGİLERİ
  ========================================================= */
  CurrAccTypeCode: 0,
  CurrAccCode: '',
  CurrAccDescription: '',

  /* =========================================================
     🔹 PARA BİRİMİ
  ========================================================= */
  DocCurrencyCode: 'USD',
  LocalCurrencyCode: 'TRY',
  ExchangeRate: 1,

  /* =========================================================
     🔹 DURUM ALANLARI
  ========================================================= */
  IsCreditSale: true,
  IsCreditableConfirmed: false,
  IsSalesViaInternet: false,
  IsSuspended: false,
  IsCompleted: false,
  IsPrinted: false,
  IsLocked: false,
  IsClosed: false,

  /* =========================================================
     🔹 KULLANICI VE TARİH
  ========================================================= */
  CreatedUserName: '',                   // backend dolduracak (auth user)
  CreatedDate: dayjs().toISOString(),
  LastUpdatedUserName: '',
  LastUpdatedDate: dayjs().toISOString(),
  CreditableConfirmedUser: '',
  CreditableConfirmedDate: '',

  /* =========================================================
     🔹 SABİT / EK ALANLAR
  ========================================================= */
  DocumentNumber: '',
  PaymentTerm: '',
  SubCurrAccID: '',
  ShipmentMethodCode: '',
  ContactID: '',
  ShippingPostalAddressID: '',
  GuarantorContactID2: '',
  RoundsmanCode: '',
  DeliveryCompanyCode: '',
  TaxTypeCode: '',
  WithHoldingTaxTypeCode: '',
  DOVCode: '',
  TaxExemptionCode: 0,
  CompanyCode: 1,
  OfficeCode: 101,
  StoreTypeCode: 5,
  StoreCode: 0,
  POSTerminalID: 0,
  WarehouseCode: '1-0-12',
  ToWarehouseCode: '',
  OrdererCompanyCode: 1,
  OrdererOfficeCode: 101,
  OrdererStoreCode: '',
  GLTypeCode: '',
  TDisRate1: 0,
  TDisRate2: 0,
  TDisRate3: 0,
  TDisRate4: 0,
  TDisRate5: 0,
  DiscountReasonCode: 0,
  SurplusOrderQtyToleranceRate: 0,
  ImportFileNumber: '',
  ExportFileNumber: '',
  IncotermCode1: '',
  IncotermCode2: '',
  LettersOfCreditNumber: '',
  PaymentMethodCode: '',
  IsIncludedVat: 0,
  UserLocked: 0,
  IsProposalBased: 0,
  model: '',           // Ürün kodu
  renk: '',
  renk2: '',
  urunAnaGrubu: '',
  urunAltGrubu: '',
  fit: '',
  urunIcerik: '',
  drop: '',
  kategori: '',
  askiliyan: '',
  seri: '',
  bedenLabels: [],
  bedenler: [],
  adet: 0,
  fiyat: 0,
  pb: aktifPB.value,
  tutar: 0,
  aciklama: '',
  minFiyat: 0,
  kur: 1,
  minFiyatTRY: 0,

  // 🗓️ Tarihler
  olusturmaTarihi: defaultOlusturmaTarihi,
  tahminiTerminTarihi: defaultTerminTarihi,
  terminTarihi: defaultTerminTarihi
})
const orderLine = reactive({
  // 🔹 Temel Bilgiler
  OrderLineID: '',              // GUID
  OrderHeaderID: '',            // foreign key
  SortOrder: 1,
  ItemTypeCode: 0,
  ItemCode: '',
  ColorCode: '',
  ItemDim1Code: '',
  ItemDim2Code: '',
  ItemDim3Code: '',

  // 🔹 Miktarlar
  Qty1: 0,
  Qty2: 0,
  CancelQty1: 0,
  CancelQty2: 0,

  // 🔹 Tarihler
  CancelDate: null,                           // null ya da ISO string
  ClosedDate: null,
  DeliveryDate: null,
  PlannedDateOfLading: '',

  // 🔹 Durum & Neden
  OrderCancelReasonCode: '',
  IsClosed: false,

  // 🔹 Satış Planı
  SalespersonCode: '',
  PaymentPlanCode: '',
  PurchasePlanCode: '',

  // 🔹 Ürün Bilgisi
  LineDescription: '',
  UsedBarcode: '',
  CostCenterCode: '',
  VatCode: '',
  VatRate: 0,
  PCTCode: '',
  PCTRate: 0,

  // 🔹 Satır Bazlı İndirimler
  LDisRate1: 0,
  LDisRate2: 0,
  LDisRate3: 0,
  LDisRate4: 0,
  LDisRate5: 0,

  // 🔹 Para / Fiyat Bilgileri
  DocCurrencyCode: 'USD',
  PriceCurrencyCode: 'USD',
  PriceExchangeRate: 1,
  Price: 0,

  // 🔹 Referans Bilgiler
  PriceListLineID: '',
  BaseProcessCode: '',
  BaseOrderNumber: '',
  BaseCustomerTypeCode: 0,
  BaseCustomerCode: '',
  BaseSubCurrAccID: '',
  BaseStoreCode: '',
  SupportRequestHeaderID: '',

  // 🔹 Takip / Sistem Bilgileri
  OrderLineSumID: 0,
  OrderLineBOMID: 0,

  // 🔹 Kullanıcı / Tarih
  CreatedUserName: '',
  CreatedDate: dayjs().toISOString(),
  LastUpdatedUserName: '',
  LastUpdatedDate: dayjs().toISOString(),

  // 🔹 Vergi & Ek Kodlar
  SurplusOrderQtyToleranceRate: 0,
  PurchaseRequisitionLineID: '',
  WithHoldingTaxTypeCode: '',
  DOVCode: '',
  OrderLineLinkedProductID: '',

  // 🔹 Frontend’e özel ek alanlar (UI binding için)
  selectedModel: '',           // model (ürün kodu)
  selectedColor: '',           // renk
  selectedColor2: '',          // ikinci renk
  bedenLabels: [],             // beden başlıkları
  bedenValues: {},             // {38:2, 40:1, 42:0} gibi
  unitPrice: 0,
  totalAmount: 0,
  note: '',
})
const editingIndex = ref(-1)  // aktif düzenlenen satırın index’i
const summaryRows = ref([])   // tüm satırların listesi (grid kaynağı)
// 🔹 Düzenleme durumunu hesaplayan computed
const isEditing = computed(() => editingIndex.value >= 0)
/* ===========================================================
   🔹 1. ve 2. Renk Select Referansları
   QSelect bileşenlerine erişmek için template ref’leri tutulur.
=========================================================== */
const renkSelect = ref(null)
const renk2Select = ref(null)

const renkOptions = ref([])   // 1. renk seçenekleri
const renkOptions2 = ref([])  // 2. renk seçenekleri

/* ===========================================================
   🔹 Kombinasyon Anahtarı Fonksiyonları
   Aynı model + renk + 2. renk kombinasyonunun gridde olup olmadığını bulmak için
   bu yardımcı fonksiyonlar kullanılır.
=========================================================== */
const getComboKey = (o) => [o.model || '', o.renk || '', o.renk2 || ''].join('||')

// 99999 veya boş renkleri toleranslı eşleştirme
const isSameCombo = (row, form) => {
  const sameModel = row.model === form.model
  const renkOk =
    (row.renk || '') === (form.renk || '') ||
    (row.renk || '') === '99999' ||
    (form.renk || '') === '99999'
  const renk2Ok =
    (row.renk2 || '') === (form.renk2 || '') ||
    (row.renk2 || '') === '99999' ||
    (form.renk2 || '') === '99999'
  return sameModel && renkOk && renk2Ok
}

// Grid içinde aynı kombinasyonun index’ini bulur
const findExistingIndexByForm = () =>
  summaryRows.value.findIndex(r => isSameCombo(r, form))

/* ===========================================================
   🔹 Ürün Ana Grubu Bazında Gruplanmış Satırlar
   groupedRows computed fonksiyonu, satırları urunAnaGrubu’na göre gruplar.
   Her grup alt toplamları, açık/kapalı durumu ve beden setlerini içerir.
=========================================================== */
const groupOpen = reactive({})  // {"TAKIM ELBİSE": true, "GÖMLEK": false, ...}

const groupedRows = computed(() => {
  const buckets = {}
  const order = []

  // Null veya hatalı satırları filtrele
  const safeRows = (summaryRows.value || []).filter(r => r && r.urunAnaGrubu)

  for (const [idx, row] of safeRows.entries()) {
    const anaGrup = row.urunAnaGrubu.trim().toUpperCase()
    if (!anaGrup) continue

    // 🔹 Beden grubu anahtarını tespit et (schemaByKey üzerinden)
    const bedenList = Object.keys(row.bedenMap?.[row.grpKey] || {})
    const grpKey = detectBedenGroup(bedenList, row.urunAnaGrubu, row.kategori)
    const grpSchema = schemaByKey.value[grpKey]
    const bedenValues = grpSchema ? grpSchema.values : []

    // 🔹 Eğer grup ilk kez görülüyorsa, yeni obje oluştur
    if (!buckets[anaGrup]) {
      buckets[anaGrup] = {
        name: anaGrup,
        key: grpKey,
        rows: [],
        toplamAdet: 0,
        toplamTutar: 0,
        bedenValues
      }
      order.push(anaGrup)
      // ilk kez eklendiğinde default açık bırak
      if (groupOpen[anaGrup] === undefined) groupOpen[anaGrup] = true
    }

    // 🔹 Satırları grup altına ekle
    const adet = Number(row.adet || 0)
    const tutar = Number(row.tutar || 0)
    buckets[anaGrup].rows.push({ row, idx })
    buckets[anaGrup].toplamAdet += adet
    buckets[anaGrup].toplamTutar += tutar

    // 🔹 Daha geniş beden seti varsa grup seviyesinde güncelle
    if (buckets[anaGrup].bedenValues.length < bedenValues.length)
      buckets[anaGrup].bedenValues = bedenValues
  }

  // 🔹 Sonuç sıralı dizi olarak döner (UI grid için)
  return order.map(name => ({
    ...buckets[name],
    open: groupOpen[name]
  }))
})
/* ===========================================================
   🔹 Grup Aç/Kapa Fonksiyonu
   groupedRows içindeki grupOpen reactive objesini günceller.
   Kullanıcı bir ürün grubunu kapattığında alt satırlar gizlenir.
=========================================================== */
function toggleGroup(groupName) {
  if (!groupName) return
  groupOpen[groupName] = !groupOpen[groupName]
  console.log(`📂 Grup "${groupName}" artık ${groupOpen[groupName] ? 'açık' : 'kapalı'}`)
}
// ===========================================================
// 🔹 Grup Açık/Kapalı Durumunu summaryRows’a göre otomatik güncelle
// Eski sipariş çağrıldığında tüm gruplar açık gelsin
// ===========================================================
watch(summaryRows, rows => {
  if (!Array.isArray(rows)) return
  rows.forEach(r => {
    if (r.urunAnaGrubu && groupOpen[r.urunAnaGrubu] === undefined) {
      groupOpen[r.urunAnaGrubu] = true
    }
  })
})


// 🔹 Sipariş genel açıklaması (ör. “Yaz sezonu toplu sipariş”)
const siparisGenelAciklama = ref('')
const DRAFT_KEY = computed(() =>
  mode.value === 'edit'
    ? `bssapp:order:draft:edit:${headerId.value}`
    : `bssapp:order:draft:new:${txId.value || 'noguid'}`
)

// ===========================================================
// ✅ AXIOS INSTANCE TANIMI
// Tüm backend çağrıları bu instance üzerinden geçer.
// Token otomatik eklenir, 401 durumunda login sayfasına yönlendirir.
// ===========================================================
const API_BASE = 'http://localhost:8080'


// İstek öncesi interceptor — token ekleme
api.interceptors.request.use(cfg => {
  const token = localStorage.getItem('token')
  if (token) cfg.headers.Authorization = `Bearer ${token}`
  return cfg
})

// Yanıt interceptor — 401 durumunda login'e yönlendir
api.interceptors.response.use(
  r => r,
  err => {
    if (err?.response?.status === 401) {
      localStorage.removeItem('token')
      if (typeof window !== 'undefined') window.location.href = '/login'
    }
    return Promise.reject(err)
  }
)

/* ===========================================================
   🔹 detectBedenGroup — Beden Grubunu Otomatik Tespit Et
   Bu fonksiyon, ürünün "ana grup" ve "kategori" bilgilerine
   göre hangi beden setine (takım, gömlek, pantolon, ayakkabı vs.)
   ait olduğunu belirler. Bu bilgi grid yapısını belirler.
=========================================================== */
function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = '') {
  // Beden listesi normalize edilir (trim, uppercase, boşsa default ' ')
  const list = Array.isArray(bedenList) && bedenList.length > 0
    ? bedenList.map(v => (v || '').toString().trim().toUpperCase())
    : [' ']

  // Ana grup temizleme: parantez içlerini ve özel karakterleri kaldırır
  const ana = (urunAnaGrubu || '')
    .toUpperCase()
    .trim()
    .replace(/\(.*?\)/g, '')                  // (Regular Fit) gibi notları siler
    .replace(/[^A-ZÇĞİÖŞÜ0-9\s]/g, '')        // özel karakterleri temizler
    .replace(/\s+/g, ' ')                     // fazla boşlukları tek boşluk yapar

  // Kategori de temizlenir
  const kat = (urunKategori || '').toUpperCase().trim()

  // ✅ Aksesuar gruplarının listesi
  const aksesuarGruplari = [
    'AKSESUAR', 'KRAVAT', 'PAPYON', 'KEMER',
    'CORAP', 'ÇORAP', 'FULAR', 'MENDIL', 'MENDİL',
    'KASKOL', 'ASKI', 'YAKA', 'KOL DUGMESI', 'KOL DÜĞMESİ'
  ]

  // ✅ Giyim grupları
  const giyimGruplari = ['GÖMLEK', 'CEKET', 'PANTOLON', 'MONT', 'YELEK', 'TAKIM', 'TSHIRT', 'TİŞÖRT']

  // ✅ Harfli beden tespiti: XS, S, M, L, XL, XXL gibi
  const harfliBedenler = ['XS', 'S', 'M', 'L', 'XL', 'XXL', '3XL', '4XL']
  if (list.some(b => harfliBedenler.includes(b))) {
    return 'gom' // gömlek / tişört tarzı gruplar
  }

  // ⚙️ Eğer aksesuar kelimesi geçiyor ama giyim grubu değilse
  if (
    aksesuarGruplari.some(g => ana.includes(g) || kat.includes(g)) &&
    !giyimGruplari.some(g => ana.includes(g))
  ) {
    return 'aksbir'
  }

  // 🔢 Pantolon + Garson (yaş grubu) özel kuralları
  if (ana.includes('PANTOLON') && kat.includes('YETİŞKİN')) return 'pan'
  if (kat.includes('GARSON')) return 'yas'

  // 🔢 Tamamen sayısal bedenler (örneğin 39–44)
  const allNumeric = list.every(v => /^\d+$/.test(v))
  if (allNumeric) {
    const nums = list.map(v => parseInt(v, 10)).filter(Boolean)
    const diffs = nums.slice(1).map((v, i) => v - nums[i])
    if (diffs.every(d => d === 1) && nums[0] >= 35 && nums[0] <= 46) return 'ayk'
  }

  // 🧩 Eğer hiçbiri değilse:
  // Harf içeriyorsa 'gom', değilse 'tak' (takım elbise)
  const sample = list[0]
  if (/[A-Z]/.test(sample)) return 'gom'
  return 'tak'
}

/* ===========================================================
   🔹 Seri Matrix — Excel benzeri çarpan tabloları
   Her ürün tipi için (takım, gömlek, pantolon vs.)
   önceden tanımlanmış seri setlerini tutar.
   Örneğin “46–58 seri” seçilirse 46=1, 48=1, … şeklinde çarpanlar oluşur.
=========================================================== */
const seriMatrix = {
  tak: {
    '46-58 seri':     { 46:1, 48:1, 50:1, 52:1, 54:1, 56:1, 58:1 },
    '46-58 ara çift': { 46:1, 48:2, 50:2, 52:2, 54:1, 56:1, 58:1 },
    '44-58 seri':     { 44:1, 46:1, 48:1, 50:1, 52:1, 54:1, 56:1, 58:1 },
    '44-58 ara çift': { 44:1, 46:1, 48:2, 50:2, 52:2, 54:1, 56:1, 58:1 },
    '60-64 seri':     { 60:1, 62:1, 64:1 },
    '66-70 seri':     { 66:1, 68:1, 70:1 },
    '48-58 seri':     { 48:1, 50:1, 52:1, 54:1, 56:1, 58:1 }
  },
  gom: {
    'XS-XXL':          { XS:1, S:1, M:1, L:1, XL:1, XXL:1 },
    'XS-XXL ara çift': { XS:1, S:1, M:2, L:2, XL:2, XXL:1 },
    '3XL-5XL':         { '3XL':1, '4XL':1, '5XL':1 }
  },
  ayk: {
    '10\'lu seri': { 39:1, 40:2, 41:2, 42:2, 43:2, 44:1 },
    '39-44':        { 39:1, 40:1, 41:1, 42:1, 43:1, 44:1 },
    '45-47':        { 45:1, 46:1, 47:1 }
  },
  yas: {
    '2-14Y': { 2:1, 4:1, 6:1, 8:1, 10:1, 12:1, 14:1 }
  },
  pan: {
    '38-50 seri':     { 38:1, 40:1, 42:1, 44:1, 46:1, 48:1, 50:1 },
    '38-50 ara çift': { 38:1, 40:1, 42:2, 44:2, 46:2, 48:1, 50:1 },
    '52-56 seri':     { 52:1, 54:1, 56:1 },
    '58-62 seri':     { 58:1, 60:1, 62:1 }
  }
}


// 🔹 Aktif ürün grubuna göre uygun seri setlerini dinamik hesaplar
const activeSeriesOptions = computed(() => {
  const grpKey = detectBedenGroup(form.bedenLabels, form.urunAnaGrubu, form.kategori)
  const sets = seriMatrix[grpKey] || {}
  return Object.keys(sets).map(k => ({ label: k, value: k, isActive: true }))
})

/* ===========================================================
   🔹 Para Birimi ve Toplam Tutar Hesaplaması
   Sipariş toplamları ve para birimi seçimi burada yönetilir.
=========================================================== */
const paraBirimOptions = ['USD', 'EUR', 'TRY']   // Kullanıcıya sunulacak döviz seçenekleri

// Grid altındaki “Toplam Tutar” alanı dinamik hesaplanır.
const toplamTutar = computed(() => {
  const sum = orderStore.totalAmount ? Number(orderStore.totalAmount) : 0
  return isNaN(sum) ? 0 : sum
})

/* ===========================================================
   🔹 Cari Bilgileri
   Cari (müşteri) listesi, arama filtresi ve seçim sonrası
   para birimi kontrolü burada yapılır.
=========================================================== */
const selectedCari = ref(null)             // Kullanıcının seçtiği cari kodu
const cariOptions = ref([])                // Tüm cari listesi (backend'den gelir)
const filteredCariOptions = ref([])        // Arama filtrelenmiş hali
const loadingCari = ref(false)             // Yükleniyor göstergesi
const cariInfo = ref(null)                 // Seçilen carinin tüm bilgisi

/* ===========================================================
   🔹 Cari Listesini Yükleme Fonksiyonu
   Uygulama açıldığında veya cari seçimi değiştiğinde çağrılır.
   Backend'den /api/customer-list endpoint'ini çağırır.
=========================================================== */
async function loadCariList() {
  loadingCari.value = true
  try {
    ensureAuthOrRedirect() // Token kontrolü, gerekirse login yönlendirmesi
    const res = await api.get('/customer-list')
    const data = res?.data

    // Gelen data farklı formatlarda olabilir, esnek parse yapılır
    if (!data) {
      cariOptions.value = []
    } else if (Array.isArray(data)) {
      cariOptions.value = data
    } else if (Array.isArray(data?.data)) {
      cariOptions.value = data.data
    } else {
      cariOptions.value = []
    }

    // Filtre listesi de aynı anda güncellenir
    filteredCariOptions.value = cariOptions.value
    console.log('🧾 Cari listesi yüklendi:', cariOptions.value.length)
  } catch (err) {
    console.error('❌ Cari listesi alınamadı:', err)
    $q.notify({ type: 'negative', message: 'Cari listesi yüklenemedi ❌' })
  } finally {
    loadingCari.value = false
  }
}
// ===========================================================
// 🔹 Local Draft Yönetimi
// ===========================================================
function saveDraft() {
  const draft = {
    header: {
      OrderDate: form.olusturmaTarihi,
      AverageDueDate: form.tahminiTerminTarihi,
      CurrAccCode: selectedCari.value,
      DocCurrencyCode: form.pb,
      Description: siparisGenelAciklama.value
    },
    lines: summaryRows.value
  }
  localStorage.setItem(DRAFT_KEY.value, JSON.stringify(draft))
}

function loadDraft() {
  const raw = localStorage.getItem(DRAFT_KEY.value)
  if (!raw) return false
  try {
    const { header, lines } = JSON.parse(raw)
    if (header) {
      form.olusturmaTarihi = header.OrderDate || form.olusturmaTarihi
      form.tahminiTerminTarihi = header.AverageDueDate || form.tahminiTerminTarihi
      form.pb = header.DocCurrencyCode || form.pb
      selectedCari.value = header.CurrAccCode || ''
      siparisGenelAciklama.value = header.Description || ''
    }
    if (Array.isArray(lines)) summaryRows.value = [...lines]
    return true
  } catch {
    return false
  }
}

function clearDraft() {
  localStorage.removeItem(DRAFT_KEY.value)
}

/* ===========================================================
   🔹 onMounted — İlk Yüklemeler
   Uygulama ilk açıldığında auth kontrolü, store restore,
   cari ve model listesi yükleme işlemleri yapılır.
=========================================================== */
/* ===========================================================
   🔹 onMounted — İlk Yüklemeler
   Uygulama ilk açıldığında auth kontrolü, store restore,
   cari ve model listesi yükleme işlemleri yapılır.
=========================================================== */
onMounted(async () => {
  ensureAuthOrRedirect()

  if (orderId) {
    console.log('✏️ Düzenleme modu başlatılıyor:', orderId)
    mode.value = 'edit'
    isEditMode.value = true
    headerId.value = orderId
    await loadOrderById(orderId)
  } else {
    console.log('🆕 Yeni sipariş modu başlatılıyor')
    mode.value = 'new'
    isEditMode.value = false
    form.OrderHeaderID = crypto.randomUUID()
    txId.value = form.OrderHeaderID
    resetForm()
  }

  await Promise.all([loadCariList(), loadModels()])
  console.log('✅ OrderEntry ekranı hazır — mode:', mode.value)
})


/* ===========================================================
   🔹 Cari Filtreleme (Arama Kutusu)
   QSelect bileşeninde “use-input” aktif olduğunda çalışır.
   Kullanıcının yazdığı değeri cari listesinde arar (kod + ad bazlı).
=========================================================== */
function filterCari(val, update) {
  if (val === '') {
    // Boş arama → tüm cari listesi geri yüklenir
    update(() => (filteredCariOptions.value = cariOptions.value))
    return
  }

  // Küçük harfe çevirip hem ad hem kod üzerinden arama yap
  update(() => {
    const needle = val.toLowerCase()
    filteredCariOptions.value = cariOptions.value.filter(v =>
      (v.Cari_Ad || '').toLowerCase().includes(needle) ||
      (v.Cari_Kod || '').toLowerCase().includes(needle)
    )
  })
}
onMounted(() => {
  // ♻️ Daha önce kaydedilmiş siparişler varsa geri yükle
  orderStore.loadFromStorage()

  // 💾 Order değişikliklerini izleyip her değişiklikte kaydet
  orderStore.watchOrders()

  // 💾 LocalStorage geri yüklendikten sonra grid senkronizasyonu
  onMounted(async () => {
    await nextTick()
    if (orderStore.orders && orderStore.orders.length > 0) {
      summaryRows.value = [...orderStore.orders]
      console.log('💾 Grid satırları LocalStorage’dan yüklendi:', summaryRows.value.length)
    } else {
      console.log('ℹ️ LocalStorage boş, grid başlatılmadı.')
    }
  })

  // 🔄 Store değişiklikleri anlık olarak grid’e yansıt
  watch(
    () => orderStore.orders,
    newOrders => {
      summaryRows.value = [...newOrders]
    },
    { deep: true, immediate: true }
  )

  console.log(
    '♻️ LocalStorage geri yükleme tamamlandı. Aktif transaction:',
    orderStore.activeTransactionId || '—'
  )
})

// 🧹 Sayfa kapanmadan önce tekrar yedekle (fail-safe)
onBeforeUnmount(() => {
  orderStore.saveToStorage()
  console.log('💾 Sayfa kapatılırken veriler son kez kaydedildi.')
})

// 🔄 Reaktif izleme: orderStore.orders değiştiğinde kalıcı yaz
watch(
  () => orderStore.orders,
  () => orderStore.saveToStorage(),
  { deep: true }
)
/* ===========================================================
   🔹 onMounted: Header Gap Güncelleme
   order-grid-header yüksekliğini ölçüp CSS değişkeni olarak kaydeder.
   Böylece sticky header ile grid gövdesi arasında tam hizalama sağlanır.
=========================================================== */
onMounted(() => {
  nextTick(() => { // DOM tamamen yüklensin
    const hdr = document.querySelector('.order-grid-header')
    if (!hdr) {
      console.warn('⚠️ .order-grid-header bulunamadı, ölçüm atlandı.')
      return
    }

    const updateHeaderGap = () => {
      if (!hdr || !hdr.parentNode) return  // ⚠️ güvenlik kontrolü eklendi
      const rect = hdr.getBoundingClientRect()
      const height = rect.height || 0
      const fineAdjust = -height
      document.documentElement.style.setProperty('--header-body-gap', `${fineAdjust}px`)
      console.log('📏 Header yüksekliği ölçüldü:', height, 'gap:', fineAdjust)
    }

    updateHeaderGap()

    const resizeObs = new ResizeObserver(() => {
      if (hdr?.parentNode) updateHeaderGap()
    })
    resizeObs.observe(hdr)

    const onResize = () => {
      if (hdr?.parentNode) updateHeaderGap()
    }
    window.addEventListener('resize', onResize)

    onBeforeUnmount(() => {
      resizeObs.disconnect()
      window.removeEventListener('resize', onResize)
    })
  })
})

/* ===========================================================
   🔹 Cari Seçimi (onCariChange)
   Kullanıcı cari seçtiğinde hem cari bilgisi yüklenir,
   hem de ilgili para birimi (PB) otomatik olarak set edilir.
=========================================================== */
async function onCariChange(kod) {
  // 1️⃣ Cari bilgiyi lokal listeden bul
  cariInfo.value = cariOptions.value.find(c => c.Cari_Kod === kod) || null

  // 2️⃣ Varsayılan PB USD (fallback)
  let pb = cariInfo.value?.Doviz_Cinsi || 'USD'

  try {
    // 3️⃣ Eğer local veride Doviz_Cinsi yoksa backend'den çağır
    if (!cariInfo.value?.Doviz_Cinsi && kod) {
      const res = await api.get('/customer-detail', { params: { code: kod } })
      const data = res?.data || {}

      // Backend farklı property isimleri döndürebileceği için esnek kontrol
      if (data.Doviz_Cinsi || data.ParaBirimi || data.currency) {
        pb = data.Doviz_Cinsi || data.ParaBirimi || data.currency
        console.log(`💱 Cari (${kod}) para birimi backend'den alındı: ${pb}`)
      } else {
        console.log(`💵 Cari (${kod}) için PB bulunamadı, USD olarak atanıyor.`)
        pb = 'USD'
      }
    }
  } catch (err) {
    console.warn('⚠️ Cari detay alınamadı, USD olarak devam ediliyor.', err)
    pb = 'USD'
  }

  // 4️⃣ Global ve form seviyesinde PB'yi güncelle
  aktifPB.value = pb
  form.pb = pb

  // 5️⃣ Eğer model seçiliyse, PB değiştiği için min fiyatı yeniden çek
  if (form.model) {
    try {
      await fetchMinPrice()
    } catch (e) {
      console.warn('⚠️ Min fiyat yenilenemedi:', e)
    }
  }

  // 6️⃣ Bilgi logu
  console.log(`💱 Aktif PB setlendi: ${pb}`)
}

/* ===========================================================
   🔹 Model Listesi (Ürün Seçimi)
   Backend'den /api/products endpoint’inden tüm ürün kodları çekilir.
=========================================================== */
const modelOptions = ref([])          // Model seçenekleri
const filteredModelOptions = ref([])  // Arama ile filtrelenmiş hali
const loadingModels = ref(false)      // Spinner için flag

async function loadModels() {
  loadingModels.value = true
  try {
    ensureAuthOrRedirect()
    const res = await api.get('/products')
    const arr = res?.data || []

    // Backend'den ProductCode alanı çekilir
    modelOptions.value = arr.map(x => ({
      label: x.ProductCode,
      value: x.ProductCode
    }))

    filteredModelOptions.value = modelOptions.value
    console.log('✅ Model listesi yüklendi:', modelOptions.value.length)
  } catch (err) {
    console.error('❌ Model listesi alınamadı:', err)
    $q.notify({ type: 'negative', message: 'Model listesi alınamadı ❌' })
  } finally {
    loadingModels.value = false
  }
}

/* ===========================================================
   🔹 Model Arama (QSelect içinde)
   Kullanıcının yazdığı harflerle model kodlarını filtreler.
=========================================================== */
function filterModel(val, update) {
  if (val === '') {
    update(() => (filteredModelOptions.value = modelOptions.value))
    return
  }
  update(() => {
    const needle = val.toLowerCase()
    filteredModelOptions.value = modelOptions.value.filter(v =>
      (v.label || '').toLowerCase().includes(needle)
    )
  })
}

/* ===========================================================
   🔹 MODEL SEÇİMİ (onModelChangeV2)
   Yeni model seçildiğinde renkler, ürün bilgileri, min fiyat,
   stok ve beden grubu eksiksiz yenilenir; açıklama ve adet korunur.
=========================================================== */
/* ===========================================================
   🔹 MODEL SEÇİMİ (onModelChange)
   Yeni model seçildiğinde renkler, ürün bilgileri, min fiyat,
   stok ve beden grubu eksiksiz yenilenir; açıklama ve adet korunur.
=========================================================== */
async function onModelChange(modelCode) {
  if (!modelCode) {
    console.warn('⚠️ Model kodu boş, sorgu yapılmadı.')
    return
  }

  // 🧩 Önceki değerleri yedekle (korunacak alanlar)
  const keep = {
    aciklama: form.aciklama,
    bedenler: [...form.bedenler],
    bedenLabels: [...form.bedenLabels],
    fiyat: form.fiyat,
    adet: form.adet,
    tutar: form.tutar
  }

  try {
    ensureAuthOrRedirect()

    // 🎨 1️⃣ Renk listesi
    const resColors = await api.get('/product-colors', { params: { code: modelCode } })
    renkOptions.value = (resColors?.data || []).map(x => ({
      label: `${x.color_code || x.ColorCode} – ${x.color_description || x.ColorDesc || ''}`,
      value: x.color_code || x.ColorCode
    }))

    // 🧱 2️⃣ Ürün detayları
    const resDetail = await api.get('/product-detail', { params: { code: modelCode } })
    const d = resDetail?.data || {}

    Object.assign(form, {
      model: modelCode,
      urunAnaGrubu: d.UrunAnaGrubu || d.ProductGroup || '',
      urunAltGrubu: d.UrunAltGrubu || d.ProductSubGroup || '',
      fit: d.Fit1 || d.Fit || '',
      urunIcerik: d.UrunIcerik || d.Fabric || '',
      drop: d.Drop || '',
      kategori: d.Kategori || '',
      askiliyan: d.AskiliYan || '',
      aciklama: keep.aciklama,
      fiyat: keep.fiyat,
      adet: keep.adet,
      tutar: keep.tutar,
      bedenLabels: keep.bedenLabels,
      bedenler: keep.bedenler
    })

    console.log('📦 Model detayları yüklendi:', d.UrunAnaGrubu, d.Fit1)

    // 💰 3️⃣ Min fiyatı yükle
    await fetchMinPrice()

    // ⚙️ 4️⃣ Renk bulunmazsa doğrudan bedenleri yükle
    if (!renkOptions.value.length) {
      await loadProductSizes(true)
    }

    // 🧮 5️⃣ Gridde mevcut kombinasyon varsa düzenleme moduna al
    await openExistingCombination()

    // ✅ 6️⃣ Yeni model sonrası otomatik stok/beden yükle (forceRefresh)
    await handleNewCombination()

    $q.notify({
      type: 'info',
      message: `Model "${modelCode}" yüklendi ✅`,
      position: 'top-right'
    })
  } catch (err) {
    console.error('❌ Model verileri alınamadı:', err)
    $q.notify({
      type: 'negative',
      message: 'Model bilgileri alınamadı ❌',
      position: 'top-right'
    })
  }
}


/* ===========================================================
   🔹 RENK SEÇİMİ (1. Renk Değişimi)
   Kullanıcı model seçtikten sonra 1. rengi seçtiğinde:
   - 2. renk seçenekleri sıfırlanır
   - 2. renk listesi backend'den yüklenir
   - Eğer 2. renk tanımı yoksa doğrudan bedenler yüklenir
=========================================================== */
async function onColorChange(colorCode) {
  form.renk = colorCode || ''
  renkOptions2.value = []
  form.renk2 = ''

  // 2. renk QSelect bileşenini sıfırla
  if (renk2Select.value) renk2Select.value.reset()

  // ⚠️ Renk seçilmediyse işlemi iptal et
  if (!form.renk) {
    console.warn('⚠️ Renk seçilmedi, işlemler durduruldu.')
    return
  }

  try {
    ensureAuthOrRedirect()

    // 🎨 2️⃣ İkinci renk listesini yükle
    const res = await api.get('/product-secondcolor', {
      params: { code: form.model, color: colorCode }
    })

    const data = res?.data || []
    if (Array.isArray(data) && data.length > 0) {
      renkOptions2.value = data.map(x => ({
        label: x.item_dim2_code,
        value: x.item_dim2_code
      }))
      console.log('🎨 2. renk listesi yüklendi:', renkOptions2.value.length)
    } else {
      // 2. renk yoksa doğrudan beden/stok yükle
      console.log('⚪ 2. renk yok, doğrudan beden/stok yükleniyor...')
      await loadProductSizes(true)
    }

    await handleNewCombination()
  } catch (err) {
    console.error('❌ 1. renk sonrası hata:', err)
  }
}

/* ===========================================================
   🔹 2. RENK SEÇİMİ (onColor2Change)
   Kullanıcı 2. renk seçtiğinde beden/stok sorgusu yeniden yapılır.
   Ayrıca kombinasyon gridde varsa form otomatik doldurulur.
=========================================================== */
async function onColor2Change(colorCode2) {
  if (typeof colorCode2 === 'object' && colorCode2?.value) {
    colorCode2 = colorCode2.value
  }

  form.renk2 = colorCode2 || ''

  try {
    ensureAuthOrRedirect()

    // 2. renk seçildikten sonra stok/beden yükle
    await loadProductSizes(true)

    // Aynı kombinasyon varsa düzenleme moduna al
    await openExistingCombination()

    await handleNewCombination()
  } catch (err) {
    console.error('❌ 2. renk sonrası hata:', err)
  }
}


/* ===========================================================
   🔹 MODEL + PB Bazlı Minimum Fiyat
   Backend’de her model + para birimi kombinasyonu için
   minimum satış fiyatı tutulur. Kullanıcı fiyat girdiğinde
   bu alt limitin altına inmemesi sağlanır.
=========================================================== */
async function fetchMinPrice() {
  if (!form.model || !form.pb) {
    console.warn('⚠️ Fiyat sorgusu için model veya PB eksik.')
    return
  }

  try {
    // Store’daki fetchMinPrice fonksiyonu backend’den veri çeker
    const priceData = await orderStore.fetchMinPrice(form.model, form.pb)
    if (priceData) {
      // Döviz bazlı fiyatlar + TL karşılığı (rateToTRY) setlenir
      form.minFiyat = Number(priceData.price || 0)
      form.kur = Number(priceData.rateToTRY || 1)
      form.minFiyatTRY = Number(priceData.priceTRY || 0)
      console.log(
        `💰 Fiyatlar yüklendi: ${form.minFiyat} ${form.pb} (${form.minFiyatTRY.toFixed(2)} TRY)`
      )
    } else {
      // Backend boş döndüyse default sıfırla
      form.minFiyat = 0
      form.kur = 1
      form.minFiyatTRY = 0
    }
  } catch (err) {
    console.error('❌ Min fiyat alınamadı:', err)
    form.minFiyat = 0
  }
}

/* ===========================================================
   🔹 Beden / Stok Yükleyici (loadProductSizes)
   Bu fonksiyon ERP’den renk+model bazlı beden ve stok bilgisini çeker.
   Ayrıca MSSQL stoklarıyla merge eder ve cache’ler.
=========================================================== */
const sizeCache = ref({})     // Tekrar sorguları engellemek için cache
const bedenStock = ref([])    // Görsel tablo için stok listesi
const stockMap = ref({})      // { "48": 12, "50": 7, ... } şeklinde key-value map

/* ===========================================================
   🔹 Beden / Stok Yükleme Fonksiyonu
   forceRefresh = true → cache'i yok say, API'den güncel çek
=========================================================== */
async function loadProductSizes(forceRefresh = false) {
  if (!form.model) {
    console.warn('⚠️ Beden yüklenemedi: model seçilmemiş.')
    return
  }

  const colorKey  = (form.renk && form.renk.trim() !== '') ? form.renk.trim() : 'nocolor'
  const color2Key = (form.renk2 && form.renk2.trim() !== '') ? form.renk2.trim() : 'no2color'
  const key = `${form.model}_${colorKey}_${color2Key}`

  console.log('🧩 loadProductSizes → key:', key, '| forceRefresh:', forceRefresh)

  // 💾 Cache’den veri varsa ve forceRefresh=false ise cache kullan
  if (!forceRefresh && sizeCache.value[key]) {
    console.log(`💾 Cache’den yüklendi: ${key}`)
    const cached = sizeCache.value[key]

    // ✅ Mevcut adetleri koru
    const previousMap = {}
    form.bedenLabels?.forEach((lbl, i) => {
      previousMap[lbl] = Number(form.bedenler?.[i] || 0)
    })

    form.bedenLabels = cached.labels
    form.bedenler = form.bedenLabels.map(lbl => Number(previousMap[lbl] || 0))
    bedenStock.value = cached.stockArray
    stockMap.value = { ...cached.stockMap }

    // ⚡ Cache yüklenmiş olsa bile MSSQL stoklarını güncelle (edit mode için)
    console.log('🔄 Cache sonrası MSSQL stokları tazeleniyor...')
    await loadOrderInventory(true)

    return
  }

  try {
    ensureAuthOrRedirect()

    const params = { code: form.model }
    if (form.renk?.trim()) params.color = form.renk.trim()
    if (form.renk2?.trim()) params.color2 = form.renk2.trim()

    console.log('📦 Beden/stok sorgusu gönderiliyor:', params)
    const res = await api.get('/product-colorsize', { params })
    const data = res?.data || []

    console.log(`📦 Gelen beden/stok kayıt sayısı: ${data.length}`)
    if (!Array.isArray(data) || data.length === 0) {
      console.warn('⚪ Bu kombinasyon için tanımlı beden bulunamadı.')
      form.bedenLabels = []
      form.bedenler = []
      bedenStock.value = []
      stockMap.value = {}
      return
    }

    // 🔹 Gelen beden kodlarını normalize et
    const bedenList = Array.from(
      new Set(
        data.map(x => x.item_dim1_code?.trim() || x.ItemDim1Code?.trim()).filter(Boolean)
      )
    )

    // 🔹 Önceki adetleri koru
    const previousMap = {}
    form.bedenLabels?.forEach((lbl, i) => {
      previousMap[lbl] = Number(form.bedenler?.[i] || 0)
    })

    // 🔹 Aktif beden grubu belirle
    const grpKey = detectBedenGroup(bedenList, form.urunAnaGrubu, form.kategori)
    const grp = schemaByKey.value[grpKey] || schemaByKey.value.tak
    form.bedenLabels = grp.values
    form.bedenler = form.bedenLabels.map(lbl => Number(previousMap[lbl] || 0))

    console.log(`✅ Aktif beden grubu: ${grp.title} (${grpKey})`)

    // 🔹 ERP stoklarını işle
    const stockArray = data.map(x => ({
      beden: x.item_dim1_code?.trim() || x.ItemDim1Code?.trim(),
      stok: Number(
        x.kullanilabilir_envanter ||
        x.Kullanilabilir_Envanter ||
        x.stock ||
        0
      )
    }))
    const stockMapLocal = {}
    for (const s of stockArray) stockMapLocal[s.beden] = s.stok
    stockMap.value = { ...stockMapLocal }
    bedenStock.value = [...stockArray]

    console.log(`🧮 İlk stok verisi işlendi (${stockArray.length} beden)`)

    // 🔹 MSSQL stoklarını merge et
    await loadOrderInventory(true)

    // 💾 Cache güncelle
    sizeCache.value[key] = {
      labels: [...form.bedenLabels],
      stockArray: [...bedenStock.value],
      stockMap: { ...stockMap.value }
    }

    console.log(`✅ Cache güncellendi: ${key}`)
  } catch (err) {
    console.error('❌ Beden/stok verisi yüklenirken hata oluştu:', err)
    $q.notify({ type: 'negative', message: 'Beden/stok verisi alınamadı ❌' })
  }
}


/* ===========================================================
   🔹 loadOrderInventory (GÜNCELLENMİŞ)
   MSSQL stok sorgusu — artık boş değerleri 0 yapmıyor.
   merge=true ise sadece dolu değerleri günceller.
=========================================================== */
async function loadOrderInventory(merge = false) {
  if (!form.model) {
    console.warn('⚠️ Stok yüklenemedi: model seçilmemiş.')
    return
  }

  try {
    ensureAuthOrRedirect()

    const params = { code: form.model }
    if (form.renk?.trim()) params.color = form.renk.trim()
    if (form.renk2?.trim()) params.color2 = form.renk2.trim()

    console.log('📦 MSSQL stok sorgusu gönderiliyor:', params)
    const res = await api.get('/order-inventory', { params })
    const data = res?.data || []

    console.log('📦 MSSQL stok verisi geldi:', data.length)

    // 1️⃣ Normalize et
    const invMap = {}
    for (const x of data) {
      let beden = (x.Beden || x.beden || '').trim()
      if (beden === '') beden = ' '
      const stokDeger =
        x.KullanilabilirEnvanter ??
        x.kullanilabilir_envanter ??
        x.Kullanilabilir_Envanter ??
        null
      if (stokDeger != null) invMap[beden] = Number(stokDeger)
    }

    // 2️⃣ Form bedenlerine göre map oluştur
    const newMap = {}
    for (const lbl of form.bedenLabels || []) {
      const key = lbl?.trim() === '' ? ' ' : lbl.trim()
      if (invMap[key] != null) newMap[lbl] = invMap[key]
    }

    // 3️⃣ Merge veya replace
    if (merge && stockMap.value) {
      for (const lbl of Object.keys(newMap)) {
        // sadece yeni stok bilgisi varsa güncelle
        if (newMap[lbl] != null && !isNaN(newMap[lbl])) {
          stockMap.value[lbl] = newMap[lbl]
        }
      }
    } else {
      stockMap.value = { ...newMap }
    }

    // 4️⃣ bedenStock listesini senkronize et
    bedenStock.value = Object.keys(stockMap.value).map(k => ({
      beden: k,
      stok: stockMap.value[k]
    }))

    console.log('✅ Stok haritası güncellendi:', stockMap.value)
  } catch (err) {
    console.error('❌ Order inventory yüklenemedi:', err)
    $q.notify({
      type: 'negative',
      message: 'Stok verisi alınamadı ❌',
      position: 'top-right'
    })
  }
}
function formatDate(v) {
  if (!v) return '—'
  try {
    // ISO tarih ise parçala
    if (/^\d{4}-\d{2}-\d{2}$/.test(v)) {
      const [y, m, d] = v.split('-')
      return `${d}.${m}.${y}`
    }
    // diğer olası formatlar
    const date = new Date(v)
    if (isNaN(date.getTime())) return '—'
    const dd = String(date.getDate()).padStart(2, '0')
    const mm = String(date.getMonth() + 1).padStart(2, '0')
    const yyyy = date.getFullYear()
    return `${dd}.${mm}.${yyyy}`
  } catch {
    return '—'
  }
}





/* ===========================================================
   🔹 applyTerminToRows — Tahmini Termin Tarihini Grid Satırlarına Aktar
   Formdaki tahmini termin tarihi değiştiğinde,
   griddeki tüm satırlara aynı tarih işlenir (boş olanlara veya yeni eklenenlere)
=========================================================== */
function applyTerminToRows(dateStr) {
  if (!dateStr || !Array.isArray(summaryRows.value)) return
  summaryRows.value = summaryRows.value.map(r => {
    if (!r.terminTarihi || r.terminTarihi === '') {
      return { ...r, terminTarihi: dateStr }
    }
    return r
  })
}

// 🔹 Watcher: Formdaki tahmini termin tarihi değiştiğinde tüm satırlara uygula
// ÜST formdaki tahmini termin değişince:
watch(
  () => form.tahminiTerminTarihi,
  (yeni, eski) => {
    // 1) Önce editördeki tarih alanını güncelle
    // Eğer kullanıcı editörde manuel farklı bir tarih tutmuyorsa, senkronla.
    if (!form.terminTarihi || form.terminTarihi === eski) {
      form.terminTarihi = yeni || ''
    }

    // 2) İstersen griddeki BOŞ termin alanlarına da uygula
    // (dolu satırlara dokunmaz)
    applyTerminToRows(yeni)
  }
)


/*=========================================================== */
const selectedSeriSet = ref(null)   // Seçili seri seti (ör: “46-58 seri”)
const seriMultiplier = ref(1)       // Çarpan (ör: 2 → her bedene 2 ekler)

/* ===========================================================
   🔹 Seri Uygulama (Tüm bedenlere aynı değeri atar)
   Kullanıcı “ALL1” veya “ALL2” gibi genel seri modunu seçerse
   tüm bedenlere aynı miktar yazılır.
=========================================================== */
function applySeri(f) {
  f.bedenler = (f.bedenLabels || []).map(() =>
    f.seri === 'ALL2' ? 2 : f.seri === 'ALL1' ? 1 : 0
  )
  updateTotals(f)
}

/* ===========================================================
   🔹 Toplam Güncelleme Fonksiyonu
   Beden girişlerinde adet veya fiyat değiştiğinde toplam tutarı hesaplar.
=========================================================== */
function updateTotals(f) {
  f.adet = (f.bedenler || []).reduce((a, b) => a + Number(b || 0), 0)
  const fiyat = Number(f.fiyat) || 0
  f.tutar = (f.adet * fiyat).toFixed(2)
}

// dışarıya alınmalı:
watch([includeKDV, toplamTutar], ([aktif, toplam]) => {
  manualKDV.value = aktif ? Number(toplam || 0) * kdvOrani : 0
})

const toplamKDVli = computed(() => {
  return Number(toplamTutar.value || 0) + (includeKDV.value ? Number(manualKDV.value || 0) : 0)
})


/* ===========================================================
   🔹 Seri Seti Uygulama (applySeriSet)
   Kullanıcı bir seri seti seçtiğinde, o setin beden-adet oranlarını
   ilgili gruptan alır ve formdaki bedenlere ekler.
=========================================================== */
function applySeriSet() {
  if (!selectedSeriSet.value) return

  // 🔹 Aktif beden grubu anahtarını tespit et
  const grpKey = detectBedenGroup(form.bedenLabels, form.urunAnaGrubu, form.kategori)

  // 🔹 Seçilen seri setinin anahtarını al (object veya string olabilir)
  const setKey =
    typeof selectedSeriSet.value === 'object'
      ? (selectedSeriSet.value.value || selectedSeriSet.value.label)
      : selectedSeriSet.value

  // 🔹 Seri pattern’ini bul
  const pattern = seriMatrix[grpKey]?.[setKey] || {}
  const mult = Number(seriMultiplier.value) || 1

  // 🔸 EKLEYEREK uygula — mevcut değerlere çarpanlı ekleme yapar
  form.bedenler = form.bedenLabels.map((lbl, idx) => {
    const current = Number(form.bedenler[idx] || 0)
    const inc = Number(pattern[lbl] || 0) * mult
    return current + inc
  })

  // 🔹 Toplam adet ve tutarı güncelle
  updateTotals(form)

  // 🔔 Kullanıcıya bilgi bildirimi
  $q.notify({
    type: 'positive',
    message: `Seri seti "${setKey}" başarıyla eklendi ✅`
  })
}

/* ===========================================================
   🔹 Editing ve Satır İşlemleri
   summaryRows, ekranda gridde görülen satırların tam listesidir.
   editingIndex aktif olarak düzenlenen satırı tutar.
=========================================================== */

/* ===========================================================
   🔹 Form → Grid Satırı Dönüştürücü (v2)
   Kullanıcının formda yaptığı girişleri griddeki summaryRows
   formatına dönüştürür. Ayrıca formdaki tahmini termin tarihini
   grid satırına "terminTarihi" olarak işler.
=========================================================== */
function toSummaryRowFromForm() {
  // 🔸 Beden grubu anahtarını tespit et
  const grpKey = detectBedenGroup(form.bedenLabels, form.urunAnaGrubu, form.kategori)

  // 🔸 Beden map oluştur
  const bedenMap = {}
  for (const lbl of form.bedenLabels) {
    const index = form.bedenLabels.indexOf(lbl)
    bedenMap[lbl] = Number(form.bedenler[index] || 0)
  }

  // 🔸 Grid satır objesi
  const row = {
    id: Date.now(),                           // geçici ID
    model: form.model,
    renk: form.renk,
    renk2: form.renk2,
    urunAnaGrubu: form.urunAnaGrubu,
    urunAltGrubu: form.urunAltGrubu,
    aciklama: form.aciklama,
    fiyat: Number(form.fiyat || 0),
    pb: form.pb || aktifPB.value || 'USD',
    adet: Number(form.adet || 0),
    tutar: Number(form.tutar || 0),

    // 🔹 Grup yapısı
    grpKey,
    bedenMap: { [grpKey]: { ...bedenMap } },

    // 🔹 Yeni: Tahmini termin tarihi formdan alınır
       terminTarihi: form.terminTarihi || form.tahminiTerminTarihi || ''

  }

  console.log('📄 Grid satırı oluşturuldu:', row)
  return row
}

/* ===========================================================
   🔹 updateRow (Grid satırını güncelle veya ekle)
   - Edit mode aktifse mevcut satırı günceller
   - Yeni kayıt ise summaryRows’a ekler
   - Adet, fiyat, tutar, aciklama, pb, bedenMap alanlarını senkronize eder
=========================================================== */
async function updateRow() {
  try {
    ensureAuthOrRedirect()

    // 1️⃣ Temel doğrulama
    if (!form.model) {
      $q.notify({ type: 'warning', message: 'Lütfen model seçin ⚠️' })
      return
    }

    // 2️⃣ Toplamları güncelle
    updateTotals(form)

    // 3️⃣ Formu summaryRow formatına çevir
    const row = toSummaryRowFromForm()

    // 4️⃣ Edit mode aktifse → mevcut satırı güncelle
    if (editingIndex.value !== -1 && summaryRows.value[editingIndex.value]) {
      const idx = editingIndex.value
      const existing = summaryRows.value[idx]

      console.log(`✏️ updateRow çalıştı → ID: ${existing.id || '(geçici)'}`)

      // 🔹 Mevcut satır verilerini koruyarak güncelle
      summaryRows.value[idx] = {
        ...existing,
        ...row, // form’daki yeni değerleri uygula
        id: existing.id || row.id, // ID aynı kalmalı
        grpKey: existing.grpKey || row.grpKey,
        bedenMap: row.bedenMap, // beden adetleri
        fiyat: form.fiyat,
        pb: form.pb,
        tutar: form.tutar,
        aciklama: form.aciklama,
        adet: form.adet
      }

      // 🧮 Grup ve toplamlar yeniden hesaplanır (recomputed)
      updateTotals(form)

      $q.notify({
        type: 'positive',
        message: 'Satır başarıyla güncellendi ✅',
        position: 'top-right'
      })

      console.log('✅ Satır güncellendi:', summaryRows.value[idx])
    }
    else {
      // 5️⃣ Yeni satır ekleme
      summaryRows.value.push(row)
      console.log('🆕 Yeni satır eklendi:', row)

      $q.notify({
        type: 'positive',
        message: 'Yeni kombinasyon eklendi 🧩',
        position: 'top-right'
      })
    }

    // 6️⃣ Formu temizle (sadece yeni ekleme sonrası)
    if (editingIndex.value === -1) {
      resetForm(true)
    } else {
      // Edit sonrası formu bırak ama editing’i kapat
      editingIndex.value = -1
      orderStore.selected = null
    }

    console.log('🧾 Toplam satır sayısı:', summaryRows.value.length)
  } catch (err) {
    console.error('❌ Satır güncellenirken hata oluştu:', err)
    $q.notify({ type: 'negative', message: 'Satır güncellenemedi ❌' })
  }
}

/* ===========================================================
   🔹 openExistingCombination
   Formda seçilen model + renk + renk2 kombinasyonu zaten gridde varsa,
   o satırı düzenleme moduna alır ve formu otomatik doldurur.
   Yoksa formu temizleyip yeni girişe hazırlar.
=========================================================== */
/* ===========================================================
   🔹 openExistingCombination (Zero-Stock Safe v3)
   Edit modunda stokların 0 görünme hatası çözülmüş versiyon.
   Reactive flush + parametre doğrulaması içerir.
=========================================================== */
async function openExistingCombination() {
  if (!form.model) return

  // 🔍 1️⃣ Aynı kombinasyon gridde var mı?
  const idx = findExistingIndexByForm()
  if (idx === -1) {
    // 🆕 Yeni kombinasyon
    editingIndex.value = -1
    orderStore.selected = null

    Object.assign(form, {
      adet: 0,
      fiyat: 0,
      tutar: 0,
      pb: aktifPB.value || 'USD'
    })
    console.log('🆕 Yeni kombinasyon → Form temizlendi')
    return
  }

  // 🔹 2️⃣ Mevcut satırı bul
  const r = summaryRows.value[idx]
  editingIndex.value = idx
  orderStore.selected = { ...r }

  // 🔒 Edit modda aktif model ve renk seçeneklerini sabitle
  renkOptions.value = [{ label: r.renk, value: r.renk }]
  renkOptions2.value = r.renk2
    ? [{ label: r.renk2, value: r.renk2 }]
    : []

  // 🔹 3️⃣ Formu doldur
  Object.assign(form, {
    model: r.model,
    renk: r.renk,
    renk2: r.renk2,
    urunAnaGrubu: r.urunAnaGrubu,
    urunAltGrubu: r.urunAltGrubu,
    aciklama: r.aciklama,
    fiyat: Number(r.fiyat || 0),
    pb: r.pb || aktifPB.value || 'USD',
    adet: Number(r.adet || 0),
    tutar: Number(r.tutar || 0)
  })

  // ✅ 3B️⃣ GRIDDEKİ TERMİN → EDİTÖR
  form.terminTarihi = r.terminTarihi || form.terminTarihi || form.tahminiTerminTarihi || ''

  // 🔹 4️⃣ Beden grubunu geri yükle
  const key = r.grpKey || activeGroupKeyForRow(r)
  const grp = schemaByKey.value[key]
  form.bedenLabels = grp?.values || []

  const savedMap = r.bedenMap?.[key] || {}
  form.bedenler = form.bedenLabels.map(lbl => Number(savedMap[lbl] || 0))

  // ✅ 5️⃣ Stokları yeniden getir (forceRefresh = true)
  try {
    console.log('🔄 Stoklar tazeleniyor (edit mode)...')
    await nextTick()
    await new Promise(resolve => setTimeout(resolve, 250))
    await nextTick()

    console.log('🧩 loadProductSizes çağrısı öncesi:', {
      model: form.model,
      renk: form.renk,
      renk2: form.renk2
    })

    if (!form.model || !form.renk) {
      console.warn('⚠️ Model veya renk eksik, stok çağrısı atlanıyor.', form)
    } else {
      await loadProductSizes(true)
      const stoklar = Object.values(stockMap.value || {})
      console.log(`📦 Güncel stoklar: ${stoklar.join(', ')}`)
      if (stoklar.length && stoklar.every(v => Number(v) === 0)) {
        console.warn('⚠️ Backend 0 stok döndürdü → form:', form)
        $q.notify({
          type: 'warning',
          message: '⚠️ Bu kombinasyon için stok bulunamadı (0).',
          position: 'top-right'
        })
      } else {
        console.log('✅ Stoklar başarıyla yüklendi.')
      }
    }
  } catch (err) {
    console.warn('❌ Stok bilgisi yenilenemedi:', err)
  }

  // 💱 Para birimi doğrulaması
  if (!form.pb || form.pb === '') {
    form.pb = aktifPB.value || 'USD'
    console.log('💱 Para birimi formda eksikti, otomatik setlendi:', form.pb)
  }

  // 💰 Minimum fiyat kontrolü
  try {
    if (form.model && form.pb) {
      console.log('💰 Min fiyat kontrolü başlatılıyor...')
      const priceData = await orderStore.fetchMinPrice(form.model, form.pb)
      const minFiyat = Number(priceData?.price || 0)
      if (minFiyat > 0 && form.fiyat < minFiyat) {
        form.fiyat = minFiyat
        form.tutar = (form.adet || 0) * (form.fiyat || 0)
        $q.notify({
          type: 'warning',
          message: `Fiyat min. seviyeye güncellendi (${minFiyat.toLocaleString('tr-TR')} ${form.pb})`,
          position: 'top-right'
        })
      }
    }
  } catch (e) {
    console.warn('⚠️ Fiyat bilgisi yenilenemedi:', e)
  }

  // 🔢 Toplam güncelle
  updateTotals(form)

  // 💬 Kullanıcıya bilgi ver
  $q.notify({
    type: 'info',
    message: 'Mevcut kombinasyon düzenleme moduna alındı ✏️',
    position: 'top-right'
  })

  console.log(
    `✏️ Editör aktif → model=${r.model}, renk=${r.renk || '-'}, renk2=${r.renk2 || '-'}, pb=${form.pb}, termin=${form.terminTarihi}`
  )
}


/* ===========================================================
   🔹 Yeni Kombinasyon Seçimi (Model / Renk / 2. Renk)
   Kullanıcı yeni model veya renk seçtiğinde stokların 0 görünmesini önler.
   Vue flush tamamlandıktan sonra loadProductSizes(true) çağrılır.
=========================================================== */
async function handleNewCombination() {
  if (!form.model) {
    console.warn('⚠️ Model seçilmeden stok yüklenemez.')
    return
  }

  console.log('🆕 Yeni kombinasyon seçildi:', {
    model: form.model,
    renk: form.renk,
    renk2: form.renk2
  })

  try {
    // 🧠 Reaktivite flush bitene kadar bekle
    await nextTick()
    await new Promise(resolve => setTimeout(resolve, 250))
    await nextTick()

    // ⚙️ Gereksiz çağrıları önle
    if (!form.model || !form.renk) {
      console.warn('⚠️ Model veya renk eksik, loadProductSizes atlandı.')
      return
    }

    console.log('🧩 loadProductSizes çağrılıyor (handleNewCombination)...')
    await loadProductSizes(true)

    const stoklar = Object.values(stockMap.value || {})
    if (stoklar.length && stoklar.every(v => Number(v) === 0)) {
      $q.notify({
        type: 'warning',
        message: '⚠️ Bu kombinasyon için stok bulunamadı (0)',
        position: 'top-right'
      })
    } else {
      console.log('✅ Stoklar başarıyla yüklendi (yeni kombinasyon).')
    }

    // 🔹 Gridde varsa düzenleme moduna al
    await openExistingCombination()
  } catch (err) {
    console.error('❌ handleNewCombination hatası:', err)
    $q.notify({
      type: 'negative',
      message: 'Stok bilgisi alınamadı ❌',
      position: 'top-right'
    })
  }
}
/* ===========================================================
   🔹 useComboWatcher — Model / Renk / Renk2 değişimlerini izler
   Tek bir yardımcı fonksiyonla handleNewCombination çağrısını yönetir.
   Parametre: hangi alan değişti (model, renk, renk2)
=========================================================== */
/* ===========================================================
   🔹 useComboWatcher v3 (Yeni Satır Güvenli)
   Model / Renk / Renk2 değişimlerinde reaktif flush sonrası
   otomatik stok yükleme + mevcut satır koruma.
=========================================================== */
function useComboWatcher(type, handler) {
  return async (val) => {
    try {
      console.log(`🎯 useComboWatcher tetiklendi → ${type}:`, val)
      const isNewRow = editingIndex.value === -1
      const prevModel = form.model

      // 1️⃣ İlgili handler'ı (ör. onModelChange) çalıştır
      if (typeof handler === 'function') {
        await handler(val)
      }

      // 2️⃣ Vue flush tamamlanmasını bekle
      await nextTick()
      await new Promise(resolve => setTimeout(resolve, 200))
      await nextTick()

      // 3️⃣ Türüne göre zinciri yürüt
      if (type === 'model') {
        if (isNewRow || form.model !== prevModel) {
          // 🗓️ Yeni satır açılıyorsa, editörde termin boşsa default terminle doldur
          if (!form.terminTarihi || form.terminTarihi === '') {
            form.terminTarihi = form.tahminiTerminTarihi || ''
          }
          console.log('🆕 Yeni satır veya model değişimi → stok yükleniyor...')
          await handleNewCombination()
        }
      } else if (type === 'renk' || type === 'renk2') {
        // 🗓️ Editörde termin boşsa default terminle doldur
        if (!form.terminTarihi || form.terminTarihi === '') {
          form.terminTarihi = form.tahminiTerminTarihi || ''
        }
        await handleNewCombination()
      }

      console.log(`✅ useComboWatcher(${type}) tamamlandı.`)
    } catch (err) {
      console.error(`❌ useComboWatcher(${type}) hatası:`, err)
    }
  }
}

/* ===========================================================
   🔹 Satır Düzenleme (Manuel Edit – stok güncelleme dahil)
   Grid’deki bir satırı tıklayınca formu o satırla doldurur.
   Termin: GRID → EDİTÖR senkronu eklendi.
=========================================================== */
const editRow = async (row, localIndex) => {
  const globalIndex = summaryRows.value.findIndex(r =>
    r.model === row.model &&
    r.renk === row.renk &&
    r.renk2 === row.renk2 &&
    r.aciklama === row.aciklama
  )

  if (globalIndex === -1) {
    console.warn('⚠️ Editlenecek satır bulunamadı.')
    return
  }

  editingIndex.value = globalIndex
  orderStore.selected = { ...row }

  // 🔒 Edit modda seçili renkleri kilitle (seçenek olarak satırdaki değerleri koy)
  renkOptions.value = row.renk ? [{ label: row.renk, value: row.renk }] : []
  renkOptions2.value = row.renk2 ? [{ label: row.renk2, value: row.renk2 }] : []

  // 🔄 Formu satır bilgileriyle doldur
  Object.assign(form, {
    model: row.model,
    renk: row.renk,
    renk2: row.renk2,
    urunAnaGrubu: row.urunAnaGrubu,
    urunAltGrubu: row.urunAltGrubu,
    aciklama: row.aciklama,
    fiyat: Number(row.fiyat || 0),
    pb: row.pb,
    adet: Number(row.adet || 0),
    tutar: Number(row.tutar || 0)
  })

  // 🗓️ GRID → EDİTÖR termin senkronu
  form.terminTarihi = row.terminTarihi || form.terminTarihi || form.tahminiTerminTarihi || ''

  // 🔹 Beden şemasını geri yükle
  const key = row.grpKey || activeGroupKeyForRow(row)
  const grp = schemaByKey.value[key]
  form.bedenLabels = grp?.values || []
  const savedMap = row.bedenMap?.[key] || {}
  form.bedenler = form.bedenLabels.map(lbl => Number(savedMap[lbl] || 0))

  // 🔢 Toplamları yeniden hesapla
  updateTotals(form)
  form.tutar = (form.adet || 0) * (form.fiyat || 0)

  // 🧩 Stokları forceRefresh ile yükle
  if (form.model && form.renk) {
    try {
      await nextTick()
      await loadProductSizes(true)     // 💾 forceRefresh
      console.log('📦 Edit mode stoklar yenilendi:', stockMap.value)
    } catch (err) {
      console.warn('⚠️ Edit modda stok yenileme başarısız:', err)
      $q.notify({
        type: 'warning',
        message: 'Stok verisi yenilenemedi ⚠️',
        position: 'top-right'
      })
    }
  } else {
    console.log('⚪ Model veya renk eksik, stok çağrısı atlandı.')
  }

  console.log(`✏️ Edit mode aktif → index: ${globalIndex}, model: ${row.model}, termin: ${form.terminTarihi}`)
}

// Bu fonksiyonu parent bileşenlerden çağırabilmek için export et
defineExpose({ editRow })


/* ===========================================================
   🔹 Kaydet / Güncelle (saveOrUpdate)
   - Aynı kombinasyon varsa güncelleme moduna geçer,
     yoksa yeni satır ekler.
   - Kaydetmeden hemen önce stokları forceRefresh ile tazeler.
   - Stok ve Min Fiyat validasyonları içerir.
=========================================================== */
async function saveOrUpdate() {
  // 0️⃣ Kombinasyon kontrolü (99999 toleranslı)
  const existingIndex = summaryRows.value.findIndex(r =>
    r.model === form.model &&
    ((r.renk || '') === (form.renk || '') || (r.renk || '') === '99999' || (form.renk || '') === '99999') &&
    ((r.renk2 || '') === (form.renk2 || '') || (r.renk2 || '') === '99999' || (form.renk2 || '') === '99999')
  )

  if (existingIndex !== -1 && editingIndex.value === -1) {
    console.log(`⚙️ Kombinasyon zaten var → index ${existingIndex} güncellenecek`)
    editingIndex.value = existingIndex
  }

  // 1️⃣ Model zorunlu alan
  if (!form.model) {
    $q.notify({ type: 'warning', message: '⚠️ Model seçimi gerekli!' })
    return
  }

  // 2️⃣ Para birimi doğrulaması (cari yoksa USD)
  if (!form.pb || form.pb === '') {
    form.pb = aktifPB.value || 'USD'
    console.log('💱 Para birimi otomatik setlendi:', form.pb)
  }

  // 3️⃣ Kaydetmeden önce stok verisini tazele (forceRefresh)
  try {
    await loadProductSizes(true)
    console.log('📦 Stok bilgisi kaydetmeden önce yenilendi (forceRefresh).')
  } catch (err) {
    console.warn('⚠️ Stok bilgisi kaydetmeden önce yenilenemedi:', err)
  }

  // 4️⃣ Stok kontrolü (beden bazında)
  let stokOK = true
  const overLimit = []
  for (let i = 0; i < form.bedenLabels.length; i++) {
    const lbl = form.bedenLabels[i]
    const stok = Number(stockMap.value?.[lbl] || 0)
    const girilen = Number(form.bedenler[i] || 0)
    if (stok > 0 && girilen > stok) {
      overLimit.push({ beden: lbl, stok, girilen })
    }
  }

  if (overLimit.length > 0) {
    const msgLines = overLimit
      .map(x => `🟡 ${x.beden}: ${x.girilen} (Stok: ${x.stok})`)
      .join('<br>')

    stokOK = await new Promise(resolve => {
      $q.dialog({
        title: 'Stok Uyarısı',
        message: `Bazı bedenlerde stoktan fazla giriş yaptınız:<br><br>${msgLines}`,
        html: true,
        ok: { label: 'Devam Et', color: 'primary' },
        cancel: { label: 'İptal', color: 'negative' }
      })
        .onOk(() => resolve(true))
        .onCancel(() => resolve(false))
    })
  }
  if (!stokOK) return

  // 5️⃣ Min fiyat kontrolü (stok OK sonrası)
  let fiyatOK = true
  try {
    const priceData = await orderStore.fetchMinPrice(form.model, form.pb)
    const minFiyat = Number(priceData?.price || 0)
    if (priceData && form.fiyat < minFiyat) {
      fiyatOK = await new Promise(resolve => {
        $q.dialog({
          title: 'Fiyat Uyarısı',
          message: `
            <b>Min. Fiyat:</b> ${minFiyat.toLocaleString('tr-TR')} ${form.pb}<br>
            <b>Girdiğin:</b> ${form.fiyat.toLocaleString('tr-TR')} ${form.pb}`,
          html: true,
          ok: { label: 'Devam Et', color: 'primary' },
          cancel: { label: 'İptal', color: 'negative' }
        })
          .onOk(() => resolve(true))
          .onCancel(() => resolve(false))
      })
    }
  } catch (err) {
    console.warn('⚠️ Fiyat kontrolü yapılamadı:', err)
  }
  if (!fiyatOK) return
  // 6️⃣ Satır objesi oluştur (form → grid row)
  const row = toSummaryRowFromForm()
  if (!row || !row.model) return

  // 7️⃣ Tutarlılık kontrolleri
  row.adet = Number(row.adet || form.adet || 0)
  row.fiyat = Number(row.fiyat || form.fiyat || 0)
  row.tutar = Number(row.tutar || (row.adet * row.fiyat) || 0)
  row.pb = form.pb || aktifPB.value || 'USD'

  // 8️⃣ Güncelle veya yeni satır ekle
  if (editingIndex.value !== -1) {
    const currentRow = summaryRows.value[editingIndex.value]
    if (currentRow?.id) {
      // 🔹 ID varsa doğrudan güncelle
      row.id = currentRow.id
      summaryRows.value.splice(editingIndex.value, 1, row)
      orderStore.updateRow(currentRow.id, { ...row })
    } else {
      // 🔹 ID yoksa index bazlı güncelle
      summaryRows.value.splice(editingIndex.value, 1, row)
      if (orderStore.orders[editingIndex.value])
        orderStore.orders[editingIndex.value] = { ...row }
    }

    orderStore.saveToStorage?.()
    $q.notify({
      type: 'positive',
      message: 'Mevcut kombinasyon güncellendi ✏️',
      position: 'top-right'
    })
  } else {
    // 🆕 Yeni satır ekleme akışı
    orderStore.addRow({ ...row })
    summaryRows.value = [...orderStore.orders]
    orderStore.saveToStorage?.()
    $q.notify({
      type: 'positive',
      message: 'Yeni kombinasyon eklendi ✅',
      position: 'top-right'
    })
  }

  // 9️⃣ Düzenleme durumunu sıfırla
  editingIndex.value = -1
  orderStore.selected = null
  resetForm()
}

/* ===========================================================
   🔹 Form Sıfırlama (Tam Temizleme)
   Tüm form alanlarını, renk seçeneklerini, stok map’lerini
   ve select bileşenlerini sıfırlar.
=========================================================== */
/* ===========================================================
   🔹 resetForm (Güvenli Sıfırlama)
   Yeni sipariş başlatılırken formu temizler.
   Edit modunda ise aktif satırı korur.
=========================================================== */
/* ===========================================================
   🔹 Reset Form (Yeni Sipariş Başlatma)
=========================================================== */
function resetForm() {
  form.olusturmaTarihi = dayjs().format('YYYY-MM-DD')
  form.tahminiTerminTarihi = dayjs().add(30, 'day').format('YYYY-MM-DD')
  form.pb = 'USD'
  aktifPB.value = 'USD'
  selectedCari.value = ''
  siparisGenelAciklama.value = ''
  summaryRows.value = []
  orderStore.newOrderTemplate()
  isEditMode.value = false
  console.log('🧹 Form sıfırlandı.')
}

/* ===========================================================
   🔹 Satır Silme (removeSelected)
   Kullanıcı bir satırı düzenleme modundayken silmek isterse
   güvenlik diyaloğu açılır. Onay verilirse hem gridden hem
   store’dan kaldırılır.
=========================================================== */
function removeSelected() {
  if (editingIndex.value === -1) {
    $q.notify({
      type: 'info',
      message: 'Silinecek satır seçili değil ⚠️'
    })
    return
  }

  const idx = editingIndex.value
  const selectedRow = summaryRows.value[idx]
  if (!selectedRow) {
    $q.notify({
      type: 'warning',
      message: 'Geçersiz satır, silinemedi ⚠️'
    })
    return
  }

  // 🔹 Onay penceresi
  $q.dialog({
    title: 'Satırı Sil',
    message: `
      Bu satırı silmek istediğinizden emin misiniz?<br><br>
      <b>Model:</b> ${selectedRow.model || '-'}<br>
      <b>Renk:</b> ${selectedRow.renk || '-'}<br>
      <b>PB:</b> ${selectedRow.pb || '-'}<br>
      <b>Tutar:</b> ${Number(selectedRow.tutar || 0).toLocaleString(
        'tr-TR',
        { minimumFractionDigits: 2 }
      )}`,
    html: true,
    ok: { label: 'Evet, Sil', color: 'negative' },
    cancel: { label: 'Vazgeç', flat: true }
  }).onOk(() => {
    // 🔹 Grid'den kaldır
    summaryRows.value.splice(idx, 1)

    // 🔹 Store'dan kaldır (id varsa id’ye göre, yoksa index’e göre)
    if (selectedRow.id != null) {
      orderStore.removeRow(selectedRow.id)
    } else {
      orderStore.orders.splice(idx, 1)
      orderStore.saveToStorage?.()
    }

    // 🔹 Formu sıfırla
    editingIndex.value = -1
    orderStore.selected = null
    resetForm()

    // 🔹 Kullanıcıya bilgi
    $q.notify({
      type: 'positive',
      message: 'Satır silindi ✅',
      position: 'top-right'
    })
  })
}

/* ===========================================================
   🔹 Grid Şeması (Beden Haritası)
   Uygulamada hangi ürün grubunda hangi beden seti kullanılacak
   burada tanımlanır. Key → kod, title → görünür ad, values → bedenler.
=========================================================== */
const schema = ref([
  {
    key: 'ayk',
    title: 'AYAKKABI',
    values: ['39','40','41','42','43','44','45']
  },
  {
    key: 'yas',
    title: 'YAŞ',
    values: ['2','4','6','8','10','12','14']
  },
  {
    key: 'pan',
    title: 'PANTOLON',
    values: ['38','40','42','44','46','48','50','52','54','56','58','60','62','64','66','68']
  },
  {
    key: 'gom',
    title: 'GÖMLEK',
    values: ['XS','S','M','L','XL','2XL','3XL','4XL','5XL','6XL','7XL']
  },
  {
    key: 'tak',
    title: 'TAKIM ELBİSE',
    values: ['44','46','48','50','52','54','56','58','60','62','64','66','68','70','72','74']
  },
  {
    key: 'aksbir',
    title: 'AKSESUAR',
    values: [' ', '44', 'STD', '110CM', '115CM', '120CM', '125CM', '130CM', '135CM']
  }
])

/* ===========================================================
   🔹 Aktif Grup Anahtarı Tespiti
   Ürün grubunun adından (ör. “TAKIM”, “PANTOLON”) hareketle
   uygun schema.key değerini döndürür. Default: 'tak'
=========================================================== */
function activeGroupKeyForRow(row) {
  const g = row.urunAnaGrubu?.toUpperCase() || ''
  if (g.includes('TAKIM')) return 'tak'
  if (g.includes('PANTOLON')) return 'pan'
  if (g.includes('GÖMLEK')) return 'gom'
  if (g.includes('AYAKKABI')) return 'ayk'
  if (g.includes('YAŞ')) return 'yas'
  return 'tak' // default fallback
}

/* ===========================================================
   🔹 schemaByKey (Computed)
   Reaktif olarak schema listesinden key → object map üretir.
   Böylece örn. schemaByKey.value['pan'] diyerek doğrudan erişim sağlanır.
=========================================================== */
const schemaByKey = computed(() => {
  const m = {}
  schema.value.forEach(grp => (m[grp.key] = grp))
  return m
})

/* ===========================================================
   🔹 highlightPantolon (Computed)
   Eğer form’un aktif ürünü PANTOLON ise,
   grid veya formda özel vurgu yapılabilir.
=========================================================== */
const highlightPantolon = computed(() =>
  form.urunAnaGrubu?.toUpperCase()?.includes('PANTOLON')
)


/* ===========================================================
   🔹 Sayfa Kapanırken Verileri Kaydet
   onBeforeUnmount: sayfa kapatıldığında sipariş verileri
   LocalStorage’a otomatik yazılır.
=========================================================== */
onBeforeUnmount(() => {
  orderStore.saveToStorage()
  console.log('💾 Sayfa kapatılırken veriler kaydedildi.')
})




/* ===========================================================
   🔹 Tümünü Kaydet (Toplu Gönder) — Store Entegrasyonlu Versiyon
=========================================================== */
async function submitAll() {
  try {
    ensureAuthOrRedirect()

    const headerPayload = {
      OrderDate: form.olusturmaTarihi,
      AverageDueDate: form.tahminiTerminTarihi,
      CurrAccCode: selectedCari.value,
      DocCurrencyCode: form.pb,
      Description: siparisGenelAciklama.value
    }
    const linesPayload = summaryRows.value

    let res
    if (mode.value === 'new') {
      res = await api.post('/api/orders', { header: headerPayload, lines: linesPayload })
      $q.notify({ type: 'positive', message: 'Yeni sipariş oluşturuldu ✅' })
      mode.value = 'edit'
      headerId.value = res?.data?.OrderHeaderID || headerId.value
      form.OrderHeaderID = headerId.value
    } else {
      res = await api.put(`/api/orders/${form.OrderHeaderID}`, { header: headerPayload, lines: linesPayload })
      $q.notify({ type: 'positive', message: 'Sipariş güncellendi ✅' })
    }

    saveDraft()
  } catch (err) {
    console.error('❌ submitAll hata:', err)
    $q.notify({ type: 'negative', message: 'Kaydedilemedi ❌' })
  }
}


// ===========================================================
// 🔹 Sipariş Yükleme Fonksiyonu (Güvenli Sürüm)
// ===========================================================
async function loadOrderById(orderId) {
  console.log('📦 loadOrderById çağrıldı →', orderId)

  const hasLoading = !!$q.loading
  const hasNotify = !!$q.notify

  try {
    // 🔹 Loading başlat
    if (hasLoading) {
      $q.loading.show({
        message: 'Sipariş yükleniyor...',
        spinnerSize: 50,
        spinnerColor: 'gold',
        backgroundColor: 'rgba(255,255,255,0.6)',
      })
    } else {
      console.warn('⚠️ $q.loading tanımlı değil (plugin aktif mi?).')
    }

    // 🔹 API çağrısı
    const { data } = await api.get(`/order/get/${orderId}`)
    console.log('📡 API yanıtı:', data)

    if (!data || Object.keys(data).length === 0) {
      if (hasNotify) {
        $q.notify({
          type: 'negative',
          message: 'Sipariş verisi bulunamadı.',
          position: 'top',
        })
      }
      console.error('❌ Boş yanıt geldi.')
      return
    }

    // 🔹 Header → form’a aktar
    if (data.header) {
      Object.assign(form, data.header)
      console.log('✅ Header yüklendi:', form.OrderNumber || '(numara yok)')
    }

    // 🔹 Detay satırlarını frontend modeline çevir
    if (Array.isArray(data.lines)) {
      summaryRows.value = data.lines.map(l => {
        const grpKey = detectBedenGroup([l.ItemDim1Code], l.ProductGroup, '')
        return {
          model: l.ItemCode || '',
          renk: l.ColorCode || '',
          renk2: l.ItemDim2Code || '',
          urunAnaGrubu: l.ProductGroup || l.UrunAnaGrubu || '',
          urunAltGrubu: l.ProductSubGroup || l.UrunAltGrubu || '',
          aciklama: l.LineDescription || l.Aciklama || '',
          fiyat: Number(l.Price || 0),
          pb: l.PriceCurrencyCode || l.DocCurrencyCode || 'USD',
          adet: Number(l.Qty1 || 0),
          tutar: Number((l.Qty1 || 0) * (l.Price || 0)),
          grpKey,
          bedenMap: {
            [grpKey]: { [l.ItemDim1Code]: Number(l.Qty1 || 0) },
          },
          terminTarihi: l.DeliveryDate
            ? dayjs(l.DeliveryDate).format('YYYY-MM-DD')
            : form.tahminiTerminTarihi,
        }
      })
      console.log('📋 Grid satırları hazır:', summaryRows.value.length)
    } else {
      summaryRows.value = []
    }
  } catch (err) {
    console.error('❌ loadOrderById hata:', err)
    if (hasNotify) {
      $q.notify({
        type: 'negative',
        message: 'Sipariş yüklenirken hata oluştu.',
        position: 'top',
      })
    }
  } finally {
    // 🔹 Loading gizle
    if (hasLoading) {
      try {
        $q.loading.hide()
      } catch (hideErr) {
        console.warn('⚠️ Loading kapatılamadı:', hideErr)
      }
    }
  }
}




/* ===========================================================
   🔹 Stok Bilgisi Görüntüleme Fonksiyonları
   Her beden veya satır için stok bilgisini UI’da göstermek için kullanılır.
=========================================================== */
function getStockFor(lbl) {
  if (!lbl || !stockMap.value) return 0
  const val = stockMap.value[lbl]
  const num = Number(val)
  return isNaN(num) ? 0 : num   // 🎯 string "433" bile olsa 433 olarak döner
}

function getStockForRow(row, beden) {
  if (!row || !beden) return 0

  // 🔹 Eğer formda seçili model ve renk bu satıra aitse, bedenStock'tan getir
  if (row.model === form.model && row.renk === form.renk) {
    const f = bedenStock.value.find(x => x.beden === beden)
    if (f) return Number(f.stok) || 0   // 🎯 string → number dönüşümü eklendi
  }

  // 🔹 Satırın kendi stokMap’inde varsa oradan getir
  if (row.stokMap && row.stokMap[beden] != null) {
    const num = Number(row.stokMap[beden])
    return isNaN(num) ? 0 : num
  }

  return 0
}

/* ===========================================================
   🔹 Watchers — Model & Renk Değişimlerinde Otomatik Temizlik
   Kullanıcı model veya renk değiştirdiğinde önceki form verileri
   sıfırlanır, gereksiz stok veya beden bilgileri temizlenir.
=========================================================== */
watch(
  () => form.model,
  async (newVal, oldVal) => {
    // MODEL TEMİZLENDİYSE: her şey sıfırlanır
    if (!newVal) {
      console.log('🧹 Model kaldırıldı, beden seti sıfırlanıyor...')
      resetForm()
      selectedSeriSet.value = null
      seriMultiplier.value = 1
      return
    }

    // MODEL DEĞİŞTİYSE: form yeniden başlatılır ve yeni model yüklenir
    if (oldVal && newVal !== oldVal) {
      console.log('🌀 Model değişti, form temizleniyor...')
      resetForm()
      await nextTick()
      form.model = newVal
      onModelChange(newVal)
    }
  }
)

watch(
  () => form.renk,
  (newVal, oldVal) => {
    // Renk değiştiğinde ikinci renk ve ilgili stok bilgileri temizlenir
    if (oldVal && newVal && newVal !== oldVal) {
      console.log('🎨 Renk değişti, alt veriler sıfırlanıyor...')
      form.renk2 = ''
      renkOptions2.value = []
      if (renk2Select.value) renk2Select.value.reset()
    }
  }
)

/* ===========================================================
   🔹 Beden + Stok Etiketli Görünüm (Frontend Haritalama)
   Grid veya tablo üzerinde bedenlerin yanında stok göstermek için
   kullanılacak computed alan.
=========================================================== */
const bedenWithStock = computed(() => {
  if (!form.bedenLabels.length) return []
  return form.bedenLabels.map(lbl => ({
    label: lbl,
    stok: stockMap.value[lbl] ?? null,
    value: form.bedenler[form.bedenLabels.indexOf(lbl)]
  }))
})

/* ===========================================================
   🔹 PB (Para Birimi) değişiminde min fiyat yenileme
   Eğer kullanıcı para birimini değiştirirse, backend’den yeniden
   min fiyat sorgusu yapılır (örneğin USD → EUR dönüşüm).
=========================================================== */
watch(
  () => form.pb,
  async (newVal, oldVal) => {
    if (newVal && newVal !== oldVal) {
      console.log('💱 PB değişti:', newVal)
      await fetchMinPrice()
    }
  }
)
/* ===========================================================
   🔹 Aktif Beden Alanı ve Renkli Stok Etiketleri
   Stok miktarına göre hücre arka planı veya yazı rengini belirler.
   Kullanıcı stok durumunu görsel olarak hemen fark eder.
=========================================================== */
const activeBeden = ref(null)

function stockColorClass(qty) {
  const n = Number(qty)
  if (isNaN(n)) return ''
  if (n === 0) return 'stok-red'         // 🔴 Stok yok
  if (n > 0 && n <= 2) return 'stok-yellow' // 🟡 Kritik stok (1–2)
  return 'stok-green'                    // 🟢 Yeterli stok (3+)
}

/* ===========================================================
   🔹 Yardımcı Fonksiyonlar — Auth ve Token Kontrolü
   Kullanıcının token’ı yoksa login sayfasına yönlendirir.
   Tüm backend çağrıları öncesi güvenlik katmanı sağlar.
=========================================================== */
function getToken() {
  return localStorage.getItem('token')
}

function ensureAuthOrRedirect() {
  const token = getToken()
  if (!token) {
    if (typeof window !== 'undefined') window.location.href = '/login'
    throw new Error('🚫 Yetkilendirme gerekli.')
  }
}

/* ===========================================================
   🔹 Son Bilgilendirme ve Debug Log
   Geliştirme aşamasında konsolda bileşenin başarıyla
   yüklendiği bilgisini verir.
=========================================================== */
console.log('🧩 OrderEntry (v22-final) bileşeni başarıyla yüklendi.')
</script>
