import { defineStore } from 'pinia'
import api from 'src/services/api'

const GROUPED_TTL_MS = 2 * 60 * 1000
const IMAGE_TTL_MS = 15 * 60 * 1000

function resolveProductImageUrl (item) {
  return resolveProductImageUrls(item)[0] || ''
}

function resolveProductImageUrls (item) {
  if (!item || typeof item !== 'object') return []
  const urls = []
  const addURL = value => {
    const url = String(value || '').trim()
    if (url && !urls.includes(url)) urls.push(url)
  }

  const thumbURL = String(item.thumb_url || item.thumbUrl || '').trim()
  addURL(thumbURL)

  const fullURL = String(item.full_url || item.fullUrl || '').trim()
  addURL(fullURL)

  const contentURL = String(item.content_url || item.ContentURL || '').trim()
  if (contentURL.startsWith('/api/')) addURL(contentURL)
  else if (contentURL.startsWith('/')) addURL(`/api${contentURL}`)
  return urls
}

function normalizedFilterMap (filters = {}) {
  return Object.fromEntries(Object.entries(filters || {})
    .map(([key, values]) => [
      String(key || '').trim(),
      normalizedList(values, true)
    ])
    .filter(([key, values]) => key && values.length)
    .sort((a, b) => a[0].localeCompare(b[0], 'tr')))
}

function normalizedList (value, sort = false) {
  if (!Array.isArray(value)) return []
  const out = value.map(x => String(x || '').trim()).filter(Boolean)
  return sort ? out.sort() : out
}

export const useProductPerformanceStore = defineStore('product-performance-store', {
  state: () => ({
    groupedRowsByKey: {},
    groupedLoadedAtByKey: {},
    groupedLoadingByKey: {},
    groupedInFlightByKey: {},
    groupedFilterOptionsByKey: {},
    groupedFilterOptionsLoadedAtByKey: {},
    groupedFilterOptionsInFlightByKey: {},
    imageUrlByKey: {},
    imageListByKey: {},
    imageLoadedAtByKey: {}
  }),

  getters: {
    groupedRows: state => key => state.groupedRowsByKey[key] || [],
    hasImageKey: state => key => Object.prototype.hasOwnProperty.call(state.imageListByKey, key),
    imageUrl: state => key => state.imageUrlByKey[key] || '',
    imageList: state => key => state.imageListByKey[key] || []
  },

  actions: {
    groupedCacheKey (params = {}) {
      return JSON.stringify({
        mode: String(params.mode || ''),
        mainGroup: String(params.urunAnaGrubu || params.urun_ana_grubu || ''),
        groupLevels: normalizedList(params.groupLevels),
        expandedKeys: normalizedList(params.expandedKeys, true),
        expandThroughLevel: Number(params.expandThroughLevel ?? params.expand_through_level ?? -1),
        filters: normalizedFilterMap(params.filters),
        sortBy: String(params.sortBy || params.sort_by || ''),
        descending: params.descending !== false,
        limit: Number(params.limit || 0)
      })
    },

    groupedFilterOptionsCacheKey (params = {}) {
      return JSON.stringify({
        mode: String(params.mode || ''),
        mainGroup: String(params.urunAnaGrubu || params.urun_ana_grubu || ''),
        groupLevels: normalizedList(params.groupLevels),
        fields: normalizedList(params.fields, true),
        limit: Number(params.limit || 0)
      })
    },

    async fetchGroupedRows (params = {}, options = {}) {
      const key = this.groupedCacheKey(params)
      const now = Date.now()
      const loadedAt = Number(this.groupedLoadedAtByKey[key] || 0)
      const cached = this.groupedRowsByKey[key]
      const logPrefix = '[ProductPerformance][grouped]'
      if (!options.force && Array.isArray(cached) && now - loadedAt < GROUPED_TTL_MS) {
        console.info(`${logPrefix} cache hit`, {
          mode: params.mode,
          rows: cached.length,
          ageMs: now - loadedAt
        })
        return cached
      }
      if (this.groupedInFlightByKey[key]) {
        console.info(`${logPrefix} in-flight reuse`, {
          mode: params.mode,
          groupLevels: normalizedList(params.groupLevels),
          expandedKeys: normalizedList(params.expandedKeys, true).length,
          expandThroughLevel: Number(params.expandThroughLevel ?? params.expand_through_level ?? -1)
        })
        return this.groupedInFlightByKey[key]
      }

      this.groupedLoadingByKey = { ...this.groupedLoadingByKey, [key]: true }
      const startedAt = performance.now()
      console.info(`${logPrefix} request start`, {
        mode: params.mode,
        groupLevels: normalizedList(params.groupLevels),
        expandedKeys: normalizedList(params.expandedKeys, true).length,
        expandThroughLevel: Number(params.expandThroughLevel ?? params.expand_through_level ?? -1),
        limit: params.limit
      })
      const request = api.post('/pricing/product-performance/grouped', {
        mode: params.mode,
        urun_ana_grubu: params.urunAnaGrubu || params.urun_ana_grubu || '',
        group_levels: Array.isArray(params.groupLevels) ? params.groupLevels : String(params.groupLevels || '').split(',').filter(Boolean),
        expanded_keys: Array.isArray(params.expandedKeys) ? params.expandedKeys : String(params.expandedKeys || '').split(',').filter(Boolean),
        expand_through_level: Number(params.expandThroughLevel ?? params.expand_through_level ?? -1),
        filters: normalizedFilterMap(params.filters),
        sort_by: String(params.sortBy || params.sort_by || ''),
        descending: params.descending !== false,
        limit: params.limit
      }, {
        params: {
          mode: params.mode,
          limit: params.limit,
          urun_ana_grubu: params.urunAnaGrubu || params.urun_ana_grubu || '',
          expand_through_level: Number(params.expandThroughLevel ?? params.expand_through_level ?? -1),
          sort_by: String(params.sortBy || params.sort_by || ''),
          descending: params.descending !== false
        },
        timeout: 90000
      }).then(resp => {
        const rows = Array.isArray(resp?.data) ? resp.data : []
        this.groupedRowsByKey = { ...this.groupedRowsByKey, [key]: rows }
        this.groupedLoadedAtByKey = { ...this.groupedLoadedAtByKey, [key]: Date.now() }
        console.info(`${logPrefix} request done`, {
          mode: params.mode,
          rows: rows.length,
          elapsedSec: Number(((performance.now() - startedAt) / 1000).toFixed(2))
        })
        return rows
      }).catch(err => {
        const message = err?.response?.data || err?.message || String(err || '')
        console.warn(`${logPrefix} request failed: ${message}`, {
          mode: params.mode,
          elapsedSec: Number(((performance.now() - startedAt) / 1000).toFixed(2)),
          message
        })
        throw err
      }).finally(() => {
        const nextLoading = { ...this.groupedLoadingByKey }
        const nextInFlight = { ...this.groupedInFlightByKey }
        delete nextLoading[key]
        delete nextInFlight[key]
        this.groupedLoadingByKey = nextLoading
        this.groupedInFlightByKey = nextInFlight
      })

      this.groupedInFlightByKey = { ...this.groupedInFlightByKey, [key]: request }
      return request
    },

    async fetchGroupedFilterOptions (params = {}, options = {}) {
      const key = this.groupedFilterOptionsCacheKey(params)
      const now = Date.now()
      const loadedAt = Number(this.groupedFilterOptionsLoadedAtByKey[key] || 0)
      const cached = this.groupedFilterOptionsByKey[key]
      if (!options.force && cached && now - loadedAt < GROUPED_TTL_MS) return cached
      if (this.groupedFilterOptionsInFlightByKey[key]) return this.groupedFilterOptionsInFlightByKey[key]

      const request = api.post('/pricing/product-performance/grouped/filter-options', {
        mode: params.mode,
        urun_ana_grubu: params.urunAnaGrubu || params.urun_ana_grubu || '',
        group_levels: Array.isArray(params.groupLevels) ? params.groupLevels : String(params.groupLevels || '').split(',').filter(Boolean),
        fields: Array.isArray(params.fields) ? params.fields : String(params.fields || '').split(',').filter(Boolean),
        limit: params.limit || 50000
      }, { timeout: 60000 }).then(resp => {
        const data = resp?.data && typeof resp.data === 'object' ? resp.data : {}
        this.groupedFilterOptionsByKey = { ...this.groupedFilterOptionsByKey, [key]: data }
        this.groupedFilterOptionsLoadedAtByKey = { ...this.groupedFilterOptionsLoadedAtByKey, [key]: Date.now() }
        return data
      }).finally(() => {
        const nextInFlight = { ...this.groupedFilterOptionsInFlightByKey }
        delete nextInFlight[key]
        this.groupedFilterOptionsInFlightByKey = nextInFlight
      })

      this.groupedFilterOptionsInFlightByKey = { ...this.groupedFilterOptionsInFlightByKey, [key]: request }
      return request
    },

    setImageCache (key, urls = []) {
      const normalizedKey = String(key || '').trim()
      if (!normalizedKey) return
      const list = Array.isArray(urls) ? urls.filter(Boolean) : []
      this.imageListByKey = { ...this.imageListByKey, [normalizedKey]: list }
      this.imageUrlByKey = { ...this.imageUrlByKey, [normalizedKey]: list[0] || '' }
      this.imageLoadedAtByKey = { ...this.imageLoadedAtByKey, [normalizedKey]: Date.now() }
    },

    async fetchImageBatch (items = [], options = {}) {
      const now = Date.now()
      const pending = []
      const seen = new Set()
      for (const item of items) {
        const key = String(item?.key || '').trim()
        if (!key || seen.has(key)) continue
        seen.add(key)
        const loadedAt = Number(this.imageLoadedAtByKey[key] || 0)
        if (!options.force && Object.prototype.hasOwnProperty.call(this.imageListByKey, key) && now - loadedAt < IMAGE_TTL_MS) continue
        pending.push({
          key,
          code: String(item?.code || '').trim(),
          dim1: String(item?.dim1 || '').trim(),
          dim3: String(item?.dim3 || '').trim()
        })
      }

      if (!pending.length) {
        const keys = Array.from(seen.values())
        return {
          lists: Object.fromEntries(keys.map(key => [key, this.imageListByKey[key] || []])),
          urls: Object.fromEntries(keys.map(key => [key, this.imageUrlByKey[key] || '']))
        }
      }

      const resp = await api.post('/product-images/batch', { items: pending }, { timeout: 60000 })
      const returned = new Set()
      const lists = {}
      const urlsByKey = {}
      for (const item of Array.isArray(resp?.data) ? resp.data : []) {
        const key = String(item?.key || '').trim()
        if (!key) continue
        returned.add(key)
        const urls = (Array.isArray(item.images) ? item.images : []).flatMap(resolveProductImageUrls).filter(Boolean)
        this.setImageCache(key, urls)
        lists[key] = urls
        urlsByKey[key] = urls[0] || ''
      }
      for (const item of pending) {
        if (returned.has(item.key)) continue
        this.setImageCache(item.key, [])
        lists[item.key] = []
        urlsByKey[item.key] = ''
      }

      return { lists, urls: urlsByKey }
    }
  }
})
