const prisma = require("./client")

function getDb(db) {
  return db || prisma
}


const DEAL_CARD_INCLUDE = {
  user: { select: { id: true, username: true, avatarUrl: true } },
  seller: { select: { id: true, name: true, url: true } },
  images: {
    orderBy: { order: "asc" },
    take: 1,
    select: { imageUrl: true },
  },
}

async function getDealCards({ where = {}, skip = 0, take = 10, orderBy = [{ createdAt: "desc" }] }) {
  try {
    // Prisma sorgusunu çalıştırıyoruz ve genelleştirilmiş formatta alıyoruz
    return await prisma.deal.findMany({
      where,
      skip,
      take,
      orderBy,
      include: DEAL_CARD_INCLUDE, // Her zaman bu alanları dahil ediyoruz
    })
  } catch (err) {
    throw new Error(`Fırsatlar alınırken bir hata oluştu: ${err.message}`)
  }
}

/**
 * Sayfalama ve diğer parametrelerle deal'leri çeker
 * 
 * @param {object} params - where, skip, take, orderBy parametreleri
 * @returns {object} - Deal card'leri ve toplam sayıyı döner
 */
async function getPaginatedDealCards({ where = {}, page = 1, limit = 10, orderBy = [{ createdAt: "desc" }] }) {
  const pagination = clampPagination({ page, limit })

  // Deal card verilerini ve toplam sayıyı alıyoruz
  const [deals, total] = await Promise.all([
    getDealCards({
      where,
      skip: pagination.skip,
      take: pagination.limit,
      orderBy,
    }),
    countDeals(where), // Total count almak için
  ])

  return {
    page: pagination.page,
    total,
    totalPages: Math.ceil(total / pagination.limit),
    results: deals, // Burada raw data döndürülüyor, map'lemiyoruz
  }
}


async function findDeals(where = {}, options = {}) {
  return prisma.deal.findMany({
    where,
    include: options.include || undefined,
    select: options.select || undefined,
    orderBy: options.orderBy || { createdAt: "desc" },
    skip: options.skip || 0,
    take: options.take || undefined,
  })
}

async function findSimilarCandidatesByCategory(categoryId, excludeDealId, { take = 80 } = {}) {
  const safeTake = Math.min(Math.max(Number(take) || 80, 1), 200)

  return prisma.deal.findMany({
    where: {
      id: { not: Number(excludeDealId) },
      status: "ACTIVE",
      categoryId: Number(categoryId),
    },
    orderBy: [{ score: "desc" }, { createdAt: "desc" }],
    take: safeTake,
    include: {
      seller: { select: { id: true, name: true, url: true } },
      images: { take: 1, orderBy: { order: "asc" }, select: { imageUrl: true } },
    },
  })
}

async function findSimilarCandidatesBySeller(sellerId, excludeDealId, { take = 30 } = {}) {
  const safeTake = Math.min(Math.max(Number(take) || 30, 1), 200)

  return prisma.deal.findMany({
    where: {
      id: { not: Number(excludeDealId) },
      status: "ACTIVE",
      sellerId: Number(sellerId),
    },
    orderBy: [{ score: "desc" }, { createdAt: "desc" }],
    take: safeTake,
    include: {
      seller: { select: { id: true, name: true, url: true } },
      images: { take: 1, orderBy: { order: "asc" }, select: { imageUrl: true } },
    },
  })
}

async function findDeal(where, options = {}, db) {
  const p = getDb(db)
  return p.deal.findUnique({
    where,
    include: options.include || undefined,
    select: options.select || undefined,
  })
}


async function createDeal(data, options = {}) {
  return prisma.deal.create({
    data,
    include: options.include || undefined,
    select: options.select || undefined,
  })
}

async function updateDeal(where, data, options = {}, db) {
  const p = getDb(db)
  return p.deal.update({
    where,
    data,
    include: options.include || undefined,
    select: options.select || undefined, 
  })
}

async function countDeals(where = {}) {
  return prisma.deal.count({ where })
}

async function findVotes(where = {}, options = {}) {
  return prisma.dealVote.findMany({
    where,
    include: options.include || undefined,
    select: options.select || undefined,
  })
}

async function createVote(data, options = {}) {
  return prisma.dealVote.create({
    data,
    include: options.include || undefined,
    select: options.select || undefined,
  })
}

async function updateVote(where, data, options = {}) {
  return prisma.dealVote.update({
    where,
    data,
    include: options.include || undefined,
    select: options.select || undefined,
  })
}

async function countVotes(where = {}) {
  return prisma.dealVote.count({ where })
}
async function getDealWithImages(dealId) {
  return prisma.deal.findUnique({
    where: { id: dealId },
    include: { images: { orderBy: { order: "asc" } } },
  });
}

async function aggregateDeals(where = {}, db) {
  const p = getDb(db)
  return p.deal.aggregate({
    where,
    _count: { _all: true },
    _sum: { score: true },
  })
}



module.exports = {
  findDeals,
  aggregateDeals,
  getDealWithImages,
  findDeal,
  createDeal,
  updateDeal,
  countDeals,
  findVotes,
  createVote,
  updateVote,
  countVotes,
   findSimilarCandidatesByCategory,
  findSimilarCandidatesBySeller,
  getDealCards,
  getPaginatedDealCards
}
