const { getRedisClient } = require("./client")
const { recordCacheMiss } = require("./cacheMetrics.service")

const SELLERS_KEY = "data:sellers"
const SELLER_DOMAINS_KEY = "data:seller:domains"

function createRedisClient() {
  return getRedisClient()
}

function normalizeIds(ids = []) {
  return Array.from(
    new Set(
      (Array.isArray(ids) ? ids : [])
        .map((id) => Number(id))
        .filter((id) => Number.isInteger(id) && id > 0)
    )
  )
}

async function getSellerById(id) {
  const sellerId = Number(id)
  if (!Number.isInteger(sellerId) || sellerId <= 0) return null
  const redis = createRedisClient()
  try {
    const raw = await redis.hget(SELLERS_KEY, String(sellerId))
    if (!raw) {
      await recordCacheMiss({ key: `${SELLERS_KEY}:${sellerId}`, label: "seller" })
    }
    return raw ? JSON.parse(raw) : null
  } catch {
    return null
  } finally {}
}

async function getSellersByIds(ids = []) {
  const normalized = normalizeIds(ids)
  if (!normalized.length) return new Map()
  const redis = createRedisClient()
  try {
    const raw = await redis.hmget(SELLERS_KEY, normalized.map(String))
    const map = new Map()
    raw.forEach((item, idx) => {
      if (!item) return
      try {
        const seller = JSON.parse(item)
        map.set(normalized[idx], seller)
      } catch {
        return
      }
    })
    return map
  } catch {
    return new Map()
  } finally {}
}

async function getSellerIdByDomain(domain) {
  const normalized = String(domain || "").trim().toLowerCase()
  if (!normalized) return null
  const redis = createRedisClient()
  try {
    const raw = await redis.hget(SELLER_DOMAINS_KEY, normalized)
    if (!raw) {
      await recordCacheMiss({ key: `${SELLER_DOMAINS_KEY}:${normalized}`, label: "seller-domain" })
    }
    const id = raw ? Number(raw) : null
    return Number.isInteger(id) && id > 0 ? id : null
  } catch {
    return null
  } finally {}
}

async function setSellersInRedis(sellers = []) {
  const list = Array.isArray(sellers) ? sellers : []
  if (!list.length) return 0
  const redis = createRedisClient()
  try {
    const pipeline = redis.pipeline()
    list.forEach((seller) => {
      if (!seller?.id) return
      pipeline.hset(SELLERS_KEY, String(seller.id), JSON.stringify(seller))
    })
    await pipeline.exec()
    return list.length
  } finally {}
}

async function setSellerInRedis(seller) {
  if (!seller?.id) return false
  await setSellersInRedis([seller])
  return true
}

async function setSellerDomainInRedis(domain, sellerId) {
  const normalized = String(domain || "").trim().toLowerCase()
  const id = Number(sellerId)
  if (!normalized || !Number.isInteger(id) || id <= 0) return false
  const redis = createRedisClient()
  try {
    await redis.hset(SELLER_DOMAINS_KEY, normalized, String(id))
    return true
  } finally {}
}

async function removeSellerFromRedis(sellerId) {
  const id = Number(sellerId)
  if (!Number.isInteger(id) || id <= 0) return 0
  const redis = createRedisClient()
  try {
    await redis.hdel(SELLERS_KEY, String(id))
    return 1
  } finally {}
}

async function removeSellerDomainFromRedis(domain) {
  const normalized = String(domain || "").trim().toLowerCase()
  if (!normalized) return 0
  const redis = createRedisClient()
  try {
    await redis.hdel(SELLER_DOMAINS_KEY, normalized)
    return 1
  } finally {}
}

async function listSellersFromRedis() {
  const redis = createRedisClient()
  try {
    const raw = await redis.hgetall(SELLERS_KEY)
    const list = []
    for (const value of Object.values(raw || {})) {
      try {
        const parsed = JSON.parse(value)
        if (parsed && parsed.id) list.push(parsed)
      } catch {
        continue
      }
    }
    return list
  } catch {
    return []
  } finally {}
}

module.exports = {
  getSellerById,
  getSellersByIds,
  getSellerIdByDomain,
  setSellerInRedis,
  setSellersInRedis,
  setSellerDomainInRedis,
  removeSellerFromRedis,
  removeSellerDomainFromRedis,
  listSellersFromRedis,
  SELLERS_KEY,
  SELLER_DOMAINS_KEY,
}
