<template>
  <q-page class="q-pa-md full-width order-prod-page">
  <div class="row items-center justify-between page-header">
    <div>
      <div class="text-h6 text-weight-bold">Uretime Verilen Urunleri Guncelle</div>
    </div>
    <q-btn
      color="primary"
      icon="refresh"
      label="Yenile"
      :loading="store.loading"
      @click="refreshAll"
    />
    <q-btn
      class="q-ml-sm"
      color="secondary"
      icon="save"
      label="Secili Degisiklikleri Kaydet"
      :loading="store.saving"
      @click="onBulkSubmit"
    />
  </div>

    <div class="filter-bar row q-col-gutter-md">
      <div class="col-5">
        <q-input
          :model-value="cariLabel"
          label="Cari Secimi"
          filled
          dense
          readonly
        />
      </div>
      <div class="col-3">
        <q-input
          v-model="descFilter"
          label="Aciklama Ara"
          filled
          dense
          clearable
        />
      </div>
      <div class="col-2">
        <q-input
          :model-value="header?.OrderNumber || ''"
          label="Siparis No"
          filled
          dense
          readonly
        />
      </div>
      <div class="col-2">
        <q-input
          :model-value="formatDate(header?.OrderDate)"
          label="Olusturulma Tarihi"
          filled
          dense
          readonly
        />
      </div>
      <div class="col-2">
        <q-input
          :model-value="formatDate(header?.AverageDueDate)"
          label="Tahmini Termin Tarihi"
          filled
          dense
          readonly
        />
      </div>
    </div>

  <div class="table-wrap">
    <q-table
        class="q-mt-md prod-table"
        flat
        bordered
        dense
        separator="cell"
        row-key="RowKey"
        :rows="filteredRows"
        :columns="columns"
        :loading="store.loading"
        no-data-label="Uretime verilecek urun bulunamadi"
        :rows-per-page-options="[0]"
        :table-style="{ tableLayout: 'fixed', width: '100%' }"
        hide-bottom
      >
      <template #header-cell-select="props">
        <q-th :props="props" class="text-center" style="width: 44px">
          <q-checkbox
            size="sm"
            :model-value="allSelectedVisible"
            :indeterminate="someSelectedVisible && !allSelectedVisible"
            @update:model-value="toggleSelectAllVisible"
          />
        </q-th>
      </template>

      <template #body-cell-select="props">
        <q-td :props="props" class="text-center" style="width: 44px">
          <q-checkbox
            size="sm"
            :model-value="!!selectedMap[props.row.RowKey]"
            @update:model-value="(val) => toggleRowSelection(props.row.RowKey, val)"
          />
        </q-td>
      </template>

      <template #body-cell-NewItemCode="props">
        <q-td :props="props">
          <q-input
            v-model="props.row.NewItemCode"
            dense
            filled
            maxlength="13"
            label="Yeni Urun"
            @update:model-value="val => onNewItemChange(props.row, val)"
          >
            <template #append>
              <q-icon name="arrow_drop_down" class="cursor-pointer" />
            </template>
            <q-menu
              anchor="bottom left"
              self="top left"
              fit
            >
              <div class="q-pa-sm" style="min-width:260px">
                <q-input
                  v-model="productSearch"
                  dense
                  filled
                  debounce="200"
                  placeholder="Urun ara..."
                />
                <q-list class="q-mt-xs" bordered separator>
                  <q-item
                    v-for="opt in filteredProducts"
                    :key="opt.ProductCode"
                    clickable
                    @click="onSelectProduct(props.row, opt.ProductCode)"
                  >
                    <q-item-section>{{ opt.ProductCode }}</q-item-section>
                  </q-item>
                </q-list>
              </div>
            </q-menu>
          </q-input>
        </q-td>
      </template>

      <template #body-cell-NewColor="props">
        <q-td :props="props">
          <q-select
            v-model="props.row.NewColor"
            :options="getColorOptions(props.row)"
            option-label="colorLabel"
            option-value="color_code"
            emit-value
            map-options
            use-input
            new-value-mode="add-unique"
            dense
            filled
            label="Yeni Renk"
            @update:model-value="() => onNewColorChange(props.row)"
            @new-value="(val, done) => onCreateColorValue(props.row, val, done)"
          />
        </q-td>
      </template>

      <template #body-cell-NewDim2="props">
        <q-td :props="props">
          <q-select
            v-model="props.row.NewDim2"
            :options="getSecondColorOptions(props.row)"
            option-label="item_dim2_code"
            option-value="item_dim2_code"
            emit-value
            map-options
            use-input
            new-value-mode="add-unique"
            dense
            filled
            label="Yeni 2. Renk"
            @new-value="(val, done) => onCreateSecondColorValue(props.row, val, done)"
          />
        </q-td>
      </template>

      <template #body-cell-NewDesc="props">
        <q-td :props="props" class="cell-new">
          <q-input
            v-model="props.row.NewDesc"
            dense
            filled
            type="textarea"
            autogrow
            label="Yeni Aciklama"
          />
        </q-td>
      </template>
    </q-table>
  </div>

    <q-banner v-if="store.error" class="bg-red text-white q-mt-sm">
      Hata: {{ store.error }}
    </q-banner>
  </q-page>
</template>

<script setup>
import { computed, onMounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useQuasar } from 'quasar'
import { useOrderProductionItemStore } from 'src/stores/OrderProductionItemStore'
import { normalizeSearchText } from 'src/utils/searchText'

const route = useRoute()
const $q = useQuasar()
const store = useOrderProductionItemStore()

const orderHeaderID = computed(() => String(route.params.orderHeaderID || '').trim())
const header = computed(() => store.header || {})
const cariLabel = computed(() => {
  const code = header.value?.CurrAccCode || ''
  const name = header.value?.CurrAccDescription || ''
  if (!code && !name) return ''
  if (!name) return code
  return `${code} - ${name}`
})

const rows = ref([])
const descFilter = ref('')
const productOptions = ref([])
const productSearch = ref('')
const selectedMap = ref({})

const columns = [
  { name: 'select', label: '', field: 'select', align: 'center', sortable: false, style: 'width:44px;', headerStyle: 'width:44px;' },
  { name: 'OldItemCode', label: 'Eski Urun Kodu', field: 'OldItemCode', align: 'left', sortable: true, style: 'min-width:90px;white-space:normal', headerStyle: 'min-width:90px;white-space:normal', headerClasses: 'col-old', classes: 'col-old' },
  { name: 'OldColor', label: 'Eski Urun Rengi', field: 'OldColor', align: 'left', sortable: true, style: 'min-width:80px;white-space:normal', headerStyle: 'min-width:80px;white-space:normal', headerClasses: 'col-old', classes: 'col-old' },
  { name: 'OldDim2', label: 'Eski 2. Renk', field: 'OldDim2', align: 'left', sortable: true, style: 'min-width:80px;white-space:normal', headerStyle: 'min-width:80px;white-space:normal', headerClasses: 'col-old', classes: 'col-old' },
  { name: 'OldDesc', label: 'Eski Aciklama', field: 'OldDesc', align: 'left', sortable: false, style: 'min-width:130px;', headerStyle: 'min-width:130px;', headerClasses: 'col-old col-desc', classes: 'col-old col-desc' },
  { name: 'OldSizes', label: 'Bedenler', field: 'OldSizesLabel', align: 'left', sortable: false, style: 'min-width:90px;', headerStyle: 'min-width:90px;', headerClasses: 'col-old col-wrap', classes: 'col-old col-wrap' },
  { name: 'NewItemCode', label: 'Yeni Urun Kodu', field: 'NewItemCode', align: 'left', sortable: false, style: 'min-width:130px;', headerStyle: 'min-width:130px;', headerClasses: 'col-new col-new-first', classes: 'col-new col-new-first' },
  { name: 'NewColor', label: 'Yeni Urun Rengi', field: 'NewColor', align: 'left', sortable: false, style: 'min-width:100px;', headerStyle: 'min-width:100px;', headerClasses: 'col-new', classes: 'col-new' },
  { name: 'NewDim2', label: 'Yeni 2. Renk', field: 'NewDim2', align: 'left', sortable: false, style: 'min-width:100px;', headerStyle: 'min-width:100px;', headerClasses: 'col-new', classes: 'col-new' },
  { name: 'NewDesc', label: 'Yeni Aciklama', field: 'NewDesc', align: 'left', sortable: false, style: 'min-width:140px;', headerStyle: 'min-width:140px;', headerClasses: 'col-new col-desc', classes: 'col-new col-desc' }
]

onMounted(async () => {
  await refreshAll()
})

watch(orderHeaderID, async (id) => {
  await refreshAll()
})

watch(
  () => store.items,
  (items) => {
    rows.value = groupItems(items || [], rows.value)
  },
  { immediate: true }
)

watch(
  () => store.products,
  (products) => {
    productOptions.value = products || []
  },
  { immediate: true }
)

function formatDate (val) {
  if (!val) return ''
  const text = String(val)
  return text.length >= 10 ? text.slice(0, 10) : text
}

const filteredProducts = computed(() => {
  const needle = normalizeSearchText(productSearch.value)
  if (!needle) return productOptions.value.slice(0, 50)
  return productOptions.value.filter(p =>
    normalizeSearchText(p?.ProductCode).includes(needle)
  ).slice(0, 50)
})

const filteredRows = computed(() => {
  const needle = normalizeSearchText(descFilter.value)
  if (!needle) return rows.value
  return rows.value.filter(r =>
    normalizeSearchText(r?.OldDesc).includes(needle)
  )
})

const visibleRowKeys = computed(() => filteredRows.value.map(r => r.RowKey))
const selectedVisibleCount = computed(() => visibleRowKeys.value.filter(k => !!selectedMap.value[k]).length)
const allSelectedVisible = computed(() => visibleRowKeys.value.length > 0 && selectedVisibleCount.value === visibleRowKeys.value.length)
const someSelectedVisible = computed(() => selectedVisibleCount.value > 0)

function onSelectProduct (row, code) {
  productSearch.value = ''
  onNewItemChange(row, code)
}

function onNewItemChange (row, val) {
  const next = String(val || '').trim().toUpperCase()
  if (next.length > 13) {
    $q.notify({ type: 'negative', message: 'Model kodu en fazla 13 karakter olabilir.' })
    row.NewItemCode = next.slice(0, 13)
    return
  }
  row.NewItemCode = next ? next.toUpperCase() : ''
  row.NewColor = ''
  row.NewDim2 = ''
  if (row.NewItemCode) {
    store.fetchColors(row.NewItemCode)
  }
}

function onNewColorChange (row) {
  row.NewColor = normalizeShortCode(row.NewColor, 3)
  row.NewDim2 = ''
  if (row.NewItemCode && row.NewColor) {
    store.fetchSecondColors(row.NewItemCode, row.NewColor)
  }
}

function getColorOptions (row) {
  const code = row?.NewItemCode || ''
  const list = store.colorOptionsByCode[code] || []
  return list.map(c => ({
    ...c,
    colorLabel: `${c.color_code} - ${c.color_description || ''}`.trim()
  }))
}

function getSecondColorOptions (row) {
  const code = row?.NewItemCode || ''
  const color = row?.NewColor || ''
  const key = `${code}::${color}`
  return store.secondColorOptionsByKey[key] || []
}

function toggleRowSelection (rowKey, checked) {
  const next = { ...selectedMap.value }
  if (checked) next[rowKey] = true
  else delete next[rowKey]
  selectedMap.value = next
}

function toggleSelectAllVisible (checked) {
  const next = { ...selectedMap.value }
  for (const key of visibleRowKeys.value) {
    if (checked) next[key] = true
    else delete next[key]
  }
  selectedMap.value = next
}

function onCreateColorValue (row, val, done) {
  const code = normalizeShortCode(val, 3)
  if (!code) {
    done(null)
    return
  }
  row.NewColor = code
  onNewColorChange(row)
  done(code, 'add-unique')
}

function onCreateSecondColorValue (row, val, done) {
  const code = normalizeShortCode(val, 3)
  if (!code) {
    done(null)
    return
  }
  row.NewDim2 = code
  done(code, 'add-unique')
}

function normalizeShortCode (value, maxLen) {
  return String(value || '').trim().toUpperCase().slice(0, maxLen)
}

function isValidBaggiModelCode (code) {
  return /^[A-Z][0-9]{3}-[A-Z]{3}[0-9]{5}$/.test(code)
}

function validateRowInput (row) {
  const newItemCode = String(row.NewItemCode || '').trim().toUpperCase()
  const newColor = normalizeShortCode(row.NewColor, 3)
  const newDim2 = normalizeShortCode(row.NewDim2, 3)
  const oldColor = String(row.OldColor || '').trim()
  const oldDim2 = String(row.OldDim2 || '').trim()

  if (!newItemCode) return 'Yeni model kodu zorunludur.'
  if (!isValidBaggiModelCode(newItemCode)) {
    return 'Girdiginiz yapi BAGGI kod yapisina uygun degildir. Format: X999-XXX99999'
  }
  if (oldColor && !newColor) return 'Eski kayitta 1. renk oldugu icin yeni 1. renk zorunludur.'
  if (newColor && newColor.length !== 3) return 'Yeni 1. renk kodu 3 karakter olmalidir.'
  if (oldDim2 && !newDim2) return 'Eski kayitta 2. renk oldugu icin yeni 2. renk zorunludur.'
  if (newDim2 && newDim2.length !== 3) return 'Yeni 2. renk kodu 3 karakter olmalidir.'
  if (newDim2 && !newColor) return '2. renk girmek icin 1. renk zorunludur.'

  row.NewItemCode = newItemCode
  row.NewColor = newColor
  row.NewDim2 = newDim2
  return ''
}

function collectLinesFromRows (selectedRows) {
  const lines = []
  for (const row of selectedRows) {
    const errMsg = validateRowInput(row)
    if (errMsg) {
      return { errMsg, lines: [] }
    }

    const baseLine = {
      NewItemCode: String(row.NewItemCode || '').trim().toUpperCase(),
      NewColor: normalizeShortCode(row.NewColor, 3),
      NewDim2: normalizeShortCode(row.NewDim2, 3),
      NewDesc: String((row.NewDesc || row.OldDesc) || '').trim()
    }

    for (const id of (row.OrderLineIDs || [])) {
      lines.push({
        OrderLineID: id,
        ...baseLine
      })
    }
  }
  return { errMsg: '', lines }
}

function buildGroupKey (item) {
  const parts = [
    String(item?.OldItemCode || '').trim(),
    String(item?.OldColor || '').trim(),
    String(item?.OldDim2 || '').trim(),
    String(item?.OldDesc || '').trim(),
    String(item?.OldDim3 || '').trim()
  ]
  return parts.join('||')
}

function formatSizes (sizeMap) {
  const entries = Object.entries(sizeMap || {})
  if (!entries.length) return { list: [], label: '-' }
  entries.sort((a, b) => String(a[0]).localeCompare(String(b[0])))
  const label = entries.map(([k, v]) => (v > 1 ? `${k}(${v})` : k)).join(', ')
  return { list: entries.map(([k]) => k), label }
}

function groupItems (items, prevRows = []) {
  const prevMap = new Map()
  for (const r of prevRows || []) {
    if (r?.RowKey) prevMap.set(r.RowKey, String(r.NewDesc || '').trim())
  }
  const map = new Map()

  for (const it of items) {
    const key = buildGroupKey(it)
    if (!map.has(key)) {
      const prevDesc = prevMap.get(key) || ''
      const fallbackDesc = String((it?.NewDesc || it?.OldDesc) || '').trim()
      map.set(key, {
        RowKey: key,
        OrderHeaderID: it.OrderHeaderID,
        OldItemCode: it.OldItemCode,
        OldColor: it.OldColor,
        OldDim2: it.OldDim2,
        OldDim3: it.OldDim3,
        OldDesc: it.OldDesc,
        OrderLineIDs: [],
        OldSizes: [],
        OldSizesLabel: '',
        NewItemCode: '',
        NewColor: '',
        NewDim2: '',
        NewDesc: prevDesc || fallbackDesc,
        IsVariantMissing: !!it.IsVariantMissing
      })
    }

    const g = map.get(key)
    if (it?.OrderLineID) g.OrderLineIDs.push(it.OrderLineID)

    const size = String(it?.OldDim1 || '').trim()
    if (size !== '') {
      g.__sizeMap = g.__sizeMap || {}
      g.__sizeMap[size] = (g.__sizeMap[size] || 0) + 1
    }
    if (it?.IsVariantMissing) g.IsVariantMissing = true
  }

  const out = []
  for (const g of map.values()) {
    const sizes = formatSizes(g.__sizeMap || {})
    g.OldSizes = sizes.list
    g.OldSizesLabel = sizes.label
    delete g.__sizeMap
    out.push(g)
  }

  return out
}

async function refreshAll () {
  await store.fetchHeader(orderHeaderID.value)
  await store.fetchItems(orderHeaderID.value)
  await store.fetchProducts()
}

async function onBulkSubmit () {
  const selectedRows = rows.value.filter(r => !!selectedMap.value[r.RowKey])
  if (!selectedRows.length) {
    $q.notify({ type: 'warning', message: 'Lutfen en az bir satir seciniz.' })
    return
  }

  const { errMsg, lines } = collectLinesFromRows(selectedRows)
  if (errMsg) {
    $q.notify({ type: 'negative', message: errMsg })
    return
  }
  if (!lines.length) {
    $q.notify({ type: 'negative', message: 'Secili satirlarda guncellenecek kayit bulunamadi.' })
    return
  }

  try {
    const validate = await store.validateUpdates(orderHeaderID.value, lines)
    const missingCount = validate?.missingCount || 0
    if (missingCount > 0) {
      const missingList = (validate?.missing || []).map(v => (
        `${v.ItemCode} / ${v.ColorCode} / ${v.ItemDim1Code} / ${v.ItemDim2Code}`
      ))
      $q.dialog({
        title: 'Eksik Varyantlar',
        message: `Eksik varyant bulundu: ${missingCount}<br><br>${missingList.join('<br>')}`,
        html: true,
        ok: { label: 'Ekle ve Guncelle', color: 'primary' },
        cancel: { label: 'Vazgec', flat: true }
      }).onOk(async () => {
        await store.applyUpdates(orderHeaderID.value, lines, true)
        await store.fetchItems(orderHeaderID.value)
        selectedMap.value = {}
      })
      return
    }

    await store.applyUpdates(orderHeaderID.value, lines, false)
    await store.fetchItems(orderHeaderID.value)
    selectedMap.value = {}
  } catch (err) {
    console.error('[OrderProductionUpdate] onBulkSubmit failed', {
      orderHeaderID: orderHeaderID.value,
      selectedRowCount: selectedRows.length,
      lineCount: lines.length,
      apiError: err?.response?.data,
      message: err?.message
    })
    $q.notify({ type: 'negative', message: store.error || 'Toplu kayit islemi basarisiz.' })
  }
}
</script>

<style scoped>
.prod-table :deep(th) {
  font-weight: 700;
  letter-spacing: 0.2px;
}

.prod-table :deep(td) {
  vertical-align: middle;
}

.prod-table :deep(.q-table__container) {
  width: 100%;
}

.prod-table :deep(.q-table) {
  font-size: 11px;
}

.order-prod-page {
  --header-height: 56px;
  --filter-bar-height: 72px;
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: auto;
}

.page-header {
  position: sticky;
  top: 0;
  z-index: 8;
  background: #fff;
  margin-top: -8px;
  margin-bottom: 8px;
  padding-top: 4px;
  padding-bottom: 6px;
}

.filter-bar {
  position: sticky;
  top: var(--header-height);
  z-index: 7;
  background: #fff;
  padding-top: 4px;
  padding-bottom: 8px;
}

.table-wrap {
  flex: 1;
  min-height: 0;
  min-width: 0;
  display: flex;
  width: 100%;
  overflow: auto;
}

.prod-table :deep(.q-table__middle) {
  max-height: calc(100vh - var(--header-height) - var(--filter-bar-height) - 140px);
  overflow: auto;
}

.prod-table :deep(.q-table__container) {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.prod-table :deep(.q-table thead tr th) {
  position: sticky;
  top: 0;
  z-index: 6;
  background: #fff;
}

.prod-table :deep(th.col-old),
.prod-table :deep(td.col-old) {
  background: #fff0d9;
}

.prod-table :deep(th.col-new),
.prod-table :deep(td.col-new) {
  background: #e3f3ff;
}

.prod-table :deep(th.col-old) {
  color: #8a5a00;
}

.prod-table :deep(th.col-new) {
  color: #0d4f7a;
}

.prod-table :deep(td.col-old) {
  border-left: 4px solid #f0a500;
}

.prod-table :deep(td.col-new) {
  border-left: 4px solid #2d9cdb;
}

.prod-table :deep(th.col-new-first),
.prod-table :deep(td.col-new-first) {
  border-left: 6px solid #1b7cc8;
}

.prod-table :deep(td.cell-new) {
  background: #e3f3ff;
}

.prod-table :deep(td.col-desc),
.prod-table :deep(th.col-desc),
.prod-table :deep(td.col-wrap),
.prod-table :deep(th.col-wrap) {
  white-space: normal;
  word-break: break-word;
  line-height: 1.2;
}

.prod-table :deep(.q-field),
.prod-table :deep(.q-field__control),
.prod-table :deep(.q-select),
.prod-table :deep(.q-input) {
  width: 100%;
  min-width: 0;
}
</style>
