// src/stores/OrderProductionItemStore.js
import { defineStore } from 'pinia'
import api from 'src/services/api'

function extractApiErrorMessage (err, fallback) {
  const data = err?.response?.data
  if (typeof data === 'string' && data.trim()) return data
  if (data && typeof data === 'object') {
    const validationMessages = Array.isArray(data.barcodeValidations)
      ? data.barcodeValidations.map(v => String(v?.message || '').trim()).filter(Boolean)
      : []
    const msg = String(data.message || '').trim()
    const step = String(data.step || '').trim()
    const detail = String(data.detail || '').trim()
    const parts = [msg]
    if (step) parts.push(`step=${step}`)
    if (detail) parts.push(detail)
    if (validationMessages.length) parts.push(validationMessages.join(' | '))
    const merged = parts.filter(Boolean).join(' | ')
    if (merged) return merged
  }
  return err?.message || fallback
}

function logApiError (action, err, payload = null) {
  const status = err?.response?.status
  const data = err?.response?.data
  console.error(`[OrderProductionItemStore] ${action} failed`, {
    status,
    payload,
    data,
    message: err?.message
  })
}

function nowMs () {
  if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
    return performance.now()
  }
  return Date.now()
}

const applyInFlightByOrder = new Map()

const YAS_NUMERIC_SIZES = new Set(['2', '4', '6', '8', '10', '12', '14'])

function safeStr (value) {
  return value == null ? '' : String(value).trim()
}

function normalizeProductionDim1Label (value) {
  let text = safeStr(value)
  if (!text) return ''

  text = text.toUpperCase()
  const yasMatch = text.match(/^(\d+)\s*(Y|YAS|YAŞ)$/)
  if (yasMatch?.[1] && YAS_NUMERIC_SIZES.has(yasMatch[1])) {
    return yasMatch[1]
  }

  return text
}

function pickPreferredProductionYasPayloadLabel (currentRaw, nextRaw) {
  const current = safeStr(currentRaw).toUpperCase()
  const next = safeStr(nextRaw).toUpperCase()
  if (!next) return current
  if (!current) return next

  const currentHasYas = /YAS$|YAŞ$/.test(current)
  const nextHasYas = /YAS$|YAŞ$/.test(next)
  if (!currentHasYas && nextHasYas) return next
  return current
}

function toProductionPayloadDim1 (row, value) {
  const base = normalizeProductionDim1Label(value)
  if (!base) return ''
  if (!YAS_NUMERIC_SIZES.has(base)) return base

  const map =
    row?.yasPayloadMap && typeof row.yasPayloadMap === 'object'
      ? row.yasPayloadMap
      : {}
  const mapped = safeStr(map[base]).toUpperCase()
  if (mapped) return mapped
  return `${base}Y`
}

export const useOrderProductionItemStore = defineStore('orderproductionitems', {
  state: () => ({
    items: [],
    header: null,
    products: [],
    colorOptionsByCode: {},
    newColorOptionsByCode: {},
    secondColorOptionsByKey: {},
    newSecondColorOptionsByKey: {},
    colorRequestsByCode: {},
    newColorRequestsByCode: {},
    secondColorRequestsByKey: {},
    newSecondColorRequestsByKey: {},
    productAttributesByItemType: {},
    productItemAttributesByKey: {},
    cdItemLookups: null,
    cdItemDraftsByCode: {},
    productAttributeDraftsByCode: {},
    knownExistingItemCodes: {},
    loading: false,
    saving: false,
    error: null
  }),

  getters: {
    productCodeSet (state) {
      const set = new Set()
      for (const p of (state.products || [])) {
        const code = String(p?.ProductCode || '').trim().toUpperCase()
        if (code) set.add(code)
      }
      return set
    }
  },

  actions: {
    normalizeDim1ForUi (value) {
      return normalizeProductionDim1Label(value)
    },
    pickPreferredYasPayloadLabel (currentRaw, nextRaw) {
      return pickPreferredProductionYasPayloadLabel(currentRaw, nextRaw)
    },
    toPayloadDim1Code (row, value) {
      return toProductionPayloadDim1(row, value)
    },
    classifyItemCode (value) {
      const normalized = String(value || '').trim().toUpperCase()
      if (!normalized) {
        return { normalized: '', mode: 'empty', exists: false }
      }
      const exists = this.productCodeSet.has(normalized) || !!this.knownExistingItemCodes[normalized]
      return {
        normalized,
        mode: exists ? 'existing' : 'new',
        exists
      }
    },
    markItemCodeKnownExisting (itemCode, exists = true) {
      const code = String(itemCode || '').trim().toUpperCase()
      if (!code) return
      this.knownExistingItemCodes = {
        ...this.knownExistingItemCodes,
        [code]: !!exists
      }
    },

    async fetchHeader (orderHeaderID) {
      if (!orderHeaderID) {
        this.header = null
        return
      }

      this.loading = true
      this.error = null

      try {
        const res = await api.get(`/order/get/${encodeURIComponent(orderHeaderID)}`)
        this.header = res?.data?.header || null
      } catch (err) {
        this.header = null
        this.error = err?.response?.data || err?.message || 'Siparis bilgisi alinamadi'
      } finally {
        this.loading = false
      }
    },
    async fetchItems (orderHeaderID) {
      if (!orderHeaderID) {
        this.items = []
        return
      }

      this.loading = true
      this.error = null

      try {
        const res = await api.get(`/orders/production-items/${encodeURIComponent(orderHeaderID)}`)
        const data = res?.data
        this.items = Array.isArray(data) ? data : []
      } catch (err) {
        this.items = []
        this.error = err?.response?.data || err?.message || 'Liste alinamadi'
      } finally {
        this.loading = false
      }
    },
    async fetchProducts () {
      this.error = null
      try {
        const res = await api.get('/products')
        const data = res?.data
        this.products = Array.isArray(data) ? data : []
      } catch (err) {
        this.products = []
        this.error = err?.response?.data || err?.message || 'Urun listesi alinamadi'
      }
    },
    async fetchCdItemByCode (code) {
      if (!code) return null
      try {
        const res = await api.get('/product-cditem', { params: { code } })
        const data = res?.data || null
        if (data) {
          this.markItemCodeKnownExisting(code, true)
        }
        return data
      } catch (err) {
        console.error('[OrderProductionItemStore] fetchCdItemByCode failed', err)
        return null
      }
    },
    async fetchColors (productCode) {
      const code = String(productCode || '').trim()
      if (!code) return []

      if (this.colorOptionsByCode[code]) {
        return this.colorOptionsByCode[code]
      }
      if (this.colorRequestsByCode[code]) {
        return this.colorRequestsByCode[code]
      }

      try {
        this.colorRequestsByCode[code] = (async () => {
          const t0 = nowMs()
          console.info('[OrderProductionItemStore] fetchColors start', { code })
          const res = await api.get('/product-colors', { params: { code } })
          const data = res?.data
          const list = Array.isArray(data) ? data : []
          if (list.length) this.markItemCodeKnownExisting(code, true)
          this.colorOptionsByCode[code] = list
          console.info('[OrderProductionItemStore] fetchColors done', { code, count: list.length, durationMs: Math.round(nowMs() - t0) })
          return list
        })()
        return await this.colorRequestsByCode[code]
      } catch (err) {
        this.error = err?.response?.data || err?.message || 'Renk listesi alinamadi'
        return []
      } finally {
        delete this.colorRequestsByCode[code]
      }
    },
    async fetchNewColors (productCode) {
      const code = String(productCode || '').trim()
      if (!code) return []

      if (this.newColorOptionsByCode[code]) {
        return this.newColorOptionsByCode[code]
      }
      if (this.newColorRequestsByCode[code]) {
        return this.newColorRequestsByCode[code]
      }

      try {
        this.newColorRequestsByCode[code] = (async () => {
          const t0 = nowMs()
          console.info('[OrderProductionItemStore] fetchNewColors start', { code })
          const res = await api.get('/product-newcolors', { params: { code } })
          const data = res?.data
          const list = Array.isArray(data) ? data : []
          this.newColorOptionsByCode[code] = list
          console.info('[OrderProductionItemStore] fetchNewColors done', { code, count: list.length, durationMs: Math.round(nowMs() - t0) })
          return list
        })()
        return await this.newColorRequestsByCode[code]
      } catch (err) {
        this.error = err?.response?.data || err?.message || 'Yeni urun renk listesi alinamadi'
        return []
      } finally {
        delete this.newColorRequestsByCode[code]
      }
    },
    async fetchSecondColors (productCode, colorCode) {
      const code = String(productCode || '').trim()
      const color = String(colorCode || '').trim()
      if (!code || !color) return []

      const key = `${code}::${color}`
      if (this.secondColorOptionsByKey[key]) {
        return this.secondColorOptionsByKey[key]
      }
      if (this.secondColorRequestsByKey[key]) {
        return this.secondColorRequestsByKey[key]
      }

      try {
        this.secondColorRequestsByKey[key] = (async () => {
          const t0 = nowMs()
          console.info('[OrderProductionItemStore] fetchSecondColors start', { code, color })
          const res = await api.get('/product-secondcolor', { params: { code, color } })
          const data = res?.data
          const list = Array.isArray(data) ? data : []
          this.secondColorOptionsByKey[key] = list
          console.info('[OrderProductionItemStore] fetchSecondColors done', { code, color, count: list.length, durationMs: Math.round(nowMs() - t0) })
          return list
        })()
        return await this.secondColorRequestsByKey[key]
      } catch (err) {
        this.error = err?.response?.data || err?.message || '2. renk listesi alinamadi'
        return []
      } finally {
        delete this.secondColorRequestsByKey[key]
      }
    },
    async fetchNewSecondColors (productCode, colorCode) {
      const code = String(productCode || '').trim()
      const color = String(colorCode || '').trim()
      if (!code || !color) return []

      const key = `${code}::${color}`
      if (this.newSecondColorOptionsByKey[key]) {
        return this.newSecondColorOptionsByKey[key]
      }
      if (this.newSecondColorRequestsByKey[key]) {
        return this.newSecondColorRequestsByKey[key]
      }

      try {
        this.newSecondColorRequestsByKey[key] = (async () => {
          const t0 = nowMs()
          console.info('[OrderProductionItemStore] fetchNewSecondColors start', { code, color })
          const res = await api.get('/product-newsecondcolor', { params: { code, color } })
          const data = res?.data
          const list = Array.isArray(data) ? data : []
          this.newSecondColorOptionsByKey[key] = list
          console.info('[OrderProductionItemStore] fetchNewSecondColors done', { code, color, count: list.length, durationMs: Math.round(nowMs() - t0) })
          return list
        })()
        return await this.newSecondColorRequestsByKey[key]
      } catch (err) {
        this.error = err?.response?.data || err?.message || 'Yeni urun 2. renk listesi alinamadi'
        return []
      } finally {
        delete this.newSecondColorRequestsByKey[key]
      }
    },
    async fetchProductAttributes (itemTypeCode = 1) {
      const key = String(itemTypeCode || 1)
      if (this.productAttributesByItemType[key]) {
        return this.productAttributesByItemType[key]
      }
      try {
        const res = await api.get('/product-attributes', { params: { itemTypeCode } })
        const list = Array.isArray(res?.data) ? res.data : []
        this.productAttributesByItemType[key] = list
        return list
      } catch (err) {
        this.error = err?.response?.data || err?.message || 'Urun ozellikleri alinamadi'
        return []
      }
    },
    async fetchProductItemAttributes (itemCode, itemTypeCode = 1, force = false) {
      const code = String(itemCode || '').trim().toUpperCase()
      const itc = Number(itemTypeCode || 1)
      if (!code) return []
      const key = `${itc}|${code}`
      if (!force && this.productItemAttributesByKey[key]) {
        return this.productItemAttributesByKey[key]
      }
      try {
        const res = await api.get('/product-item-attributes', { params: { itemTypeCode: itc, itemCode: code } })
        const list = Array.isArray(res?.data) ? res.data : []
        if (list.length) this.markItemCodeKnownExisting(code, true)
        this.productItemAttributesByKey[key] = list
        return list
      } catch (err) {
        this.error = err?.response?.data || err?.message || 'Urunun mevcut ozellikleri alinamadi'
        return []
      }
    },
    async fetchCdItemLookups (force = false) {
      if (this.cdItemLookups && !force) return this.cdItemLookups
      try {
        const res = await api.get('/orders/production-items/cditem-lookups')
        this.cdItemLookups = res?.data || null
        return this.cdItemLookups
      } catch (err) {
        const rid =
          err?.response?.headers?.['x-debug-request-id'] ||
          err?.response?.data?.requestId ||
          ''
        logApiError('fetchCdItemLookups', err, { force, requestId: rid })
        if (rid) {
          console.error(`[OrderProductionItemStore] fetchCdItemLookups requestId=${rid}`)
        }
        this.error = extractApiErrorMessage(err, 'cdItem lookup listesi alinamadi')
        return null
      }
    },
    setCdItemDraft (itemCode, draft) {
      const code = String(itemCode || '').trim().toUpperCase()
      if (!code) return
      this.cdItemDraftsByCode = {
        ...this.cdItemDraftsByCode,
        [code]: {
          ...(draft || {}),
          ItemCode: code,
          ItemTypeCode: Number(draft?.ItemTypeCode || 1)
        }
      }
    },
    getCdItemDraft (itemCode) {
      const code = String(itemCode || '').trim().toUpperCase()
      if (!code) return null
      return this.cdItemDraftsByCode[code] || null
    },
    setProductAttributeDraft (itemCode, rows) {
      const code = String(itemCode || '').trim().toUpperCase()
      if (!code) return
      this.productAttributeDraftsByCode = {
        ...this.productAttributeDraftsByCode,
        [code]: Array.isArray(rows) ? rows : []
      }
    },
    getProductAttributeDraft (itemCode) {
      const code = String(itemCode || '').trim().toUpperCase()
      if (!code) return []
      return this.productAttributeDraftsByCode[code] || []
    },
    async validateUpdates (orderHeaderID, lines, cdItems = []) {
      if (!orderHeaderID) return { missingCount: 0, missing: [] }

      this.saving = true
      this.error = null

      try {
        const t0 = nowMs()
        console.info('[OrderProductionItemStore] validateUpdates start', { orderHeaderID, lineCount: lines?.length || 0 })
        const res = await api.post(
          `/orders/production-items/${encodeURIComponent(orderHeaderID)}/validate`,
          { lines, cdItems }
        )
        const data = res?.data || { missingCount: 0, missing: [] }
        const rid = res?.headers?.['x-debug-request-id'] || ''
        console.info('[OrderProductionItemStore] validateUpdates done', {
          orderHeaderID,
          lineCount: lines?.length || 0,
          missingCount: Number(data?.missingCount || 0),
          barcodeValidationCount: Number(data?.barcodeValidationCount || 0),
          requestId: rid,
          durationMs: Math.round(nowMs() - t0)
        })
        return data
      } catch (err) {
        logApiError('validateUpdates', err, { orderHeaderID, lineCount: lines?.length || 0 })
        this.error = extractApiErrorMessage(err, 'Kontrol basarisiz')
        throw err
      } finally {
        this.saving = false
      }
    },
    async applyUpdates (orderHeaderID, lines, insertMissing, cdItems = [], productAttributes = [], headerAverageDueDate = null) {
      if (!orderHeaderID) return { updated: 0, inserted: 0 }

      const orderKey = String(orderHeaderID).trim().toUpperCase()
      if (applyInFlightByOrder.has(orderKey)) {
        console.warn('[OrderProductionItemStore] applyUpdates deduped (in-flight)', {
          orderHeaderID: orderKey,
          lineCount: lines?.length || 0
        })
        return await applyInFlightByOrder.get(orderKey)
      }

      const applyPromise = (async () => {
        this.saving = true
        this.error = null

        try {
          const t0 = nowMs()
          console.info('[OrderProductionItemStore] applyUpdates start', {
            orderHeaderID,
            lineCount: lines?.length || 0,
            insertMissing: !!insertMissing,
            cdItemCount: cdItems?.length || 0,
            attributeCount: productAttributes?.length || 0,
            headerAverageDueDate
          })
          const res = await api.post(
            `/orders/production-items/${encodeURIComponent(orderHeaderID)}/apply`,
            {
              lines,
              insertMissing,
              cdItems,
              productAttributes,
              HeaderAverageDueDate: headerAverageDueDate
            }
          )
          const data = res?.data || { updated: 0, inserted: 0 }
          const rid = res?.headers?.['x-debug-request-id'] || ''
          console.info('[OrderProductionItemStore] applyUpdates done', {
            orderHeaderID,
            updated: Number(data?.updated || 0),
            inserted: Number(data?.inserted || 0),
            barcodeInserted: Number(data?.barcodeInserted || 0),
            attributeUpserted: Number(data?.attributeUpserted || 0),
            headerUpdated: !!data?.headerUpdated,
            requestId: rid,
            durationMs: Math.round(nowMs() - t0)
          })
          return data
        } catch (err) {
          logApiError('applyUpdates', err, { orderHeaderID, lineCount: lines?.length || 0, insertMissing })
          this.error = extractApiErrorMessage(err, 'Guncelleme basarisiz')
          throw err
        } finally {
          this.saving = false
        }
      })()

      applyInFlightByOrder.set(orderKey, applyPromise)

      try {
        return await applyPromise
      } finally {
        if (applyInFlightByOrder.get(orderKey) === applyPromise) {
          applyInFlightByOrder.delete(orderKey)
        }
      }
    }
  }
})
