const dealDB = require("../db/deal.db")
const commentDB = require("../db/comment.db")
const prisma = require("../db/client")

function assertPositiveInt(v, name = "id") {
  const n = Number(v)
  if (!Number.isInteger(n) || n <= 0) throw new Error(`Geçersiz ${name}.`)
  return n
}

const DEFAULT_LIMIT = 20
const MAX_LIMIT = 50
const MAX_SKIP = 5000

function clampPagination({ page, limit }) {
  const rawPage = Number(page)
  const rawLimit = Number(limit)
  const normalizedPage = Number.isFinite(rawPage) ? Math.max(1, Math.floor(rawPage)) : 1
  let normalizedLimit = Number.isFinite(rawLimit) ? Math.max(1, Math.floor(rawLimit)) : DEFAULT_LIMIT
  normalizedLimit = Math.min(MAX_LIMIT, normalizedLimit)
  const skip = (normalizedPage - 1) * normalizedLimit
  if (skip > MAX_SKIP) throw new Error("PAGE_TOO_DEEP")
  return { page: normalizedPage, limit: normalizedLimit, skip }
}

function parseParentId(value) {
  if (value === undefined) return null
  if (value === null) return null
  if (value === "" || value === "null") return null
  const pid = Number(value)
  if (!Number.isInteger(pid) || pid <= 0) throw new Error("Geçersiz parentId.")
  return pid
}

function normalizeSort(value) {
  const normalized = String(value || "new").trim().toLowerCase()
  if (["top", "best", "liked"].includes(normalized)) return "TOP"
  return "NEW"
}


async function getCommentsByDealId(dealId, { parentId, page, limit, sort, viewer } = {}) {
  const id = Number(dealId)

  const deal = await dealDB.findDeal({ id })
  if (!deal) throw new Error("Deal bulunamadı.")

  const include = {
    user: { select: { id: true, username: true, avatarUrl: true } },
    _count: { select: { replies: true } },
  }
  const pagination = clampPagination({ page, limit })
  const parsedParentId = parseParentId(parentId)
  const sortMode = normalizeSort(sort)
  const orderBy =
    sortMode === "TOP"
      ? [{ likeCount: "desc" }, { createdAt: "desc" }]
      : [{ createdAt: "desc" }]

  const where = { dealId: id, parentId: parsedParentId }
  const [results, total] = await Promise.all([
    commentDB.findComments(where, {
      include,
      orderBy,
      skip: pagination.skip,
      take: pagination.limit,
    }),
    commentDB.countComments(where),
  ])

  let likedIds = new Set()
  if (viewer?.userId && results.length > 0) {
    const commentLikeDb = require("../db/commentLike.db")
    const likes = await commentLikeDb.findLikesByUserAndCommentIds(
      viewer.userId,
      results.map((c) => c.id)
    )
    likedIds = new Set(likes.map((l) => l.commentId))
  }

  const enriched = results.map((comment) => ({
    ...comment,
    myLike: likedIds.has(comment.id),
  }))

  return {
    page: pagination.page,
    total,
    totalPages: Math.ceil(total / pagination.limit),
    results: enriched,
  }
}

async function createComment({ dealId, userId, text, parentId = null }) {
  if (!text || typeof text !== "string" || !text.trim()) {
    throw new Error("Yorum boş olamaz.")
  }

  const trimmed = text.trim()
  const include = { user: { select: { id: true, username: true, avatarUrl: true } } }

  return prisma.$transaction(async (tx) => {
    const deal = await dealDB.findDeal({ id: dealId }, { select: { id: true, status: true } }, tx)
    if (!deal) throw new Error("Deal bulunamadı.")
    if (deal.status !== "ACTIVE" && deal.status !== "EXPIRED") {
      throw new Error("Bu deal için yorum açılamaz.")
    }

    // ✅ Reply ise parent doğrula
    let parent = null
    if (parentId != null) {
      const pid = Number(parentId)
      if (!Number.isFinite(pid) || pid <= 0) throw new Error("Geçersiz parentId.")

      parent = await commentDB.findComment({ id: pid }, { select: { id: true, dealId: true } }, tx)
      if (!parent) throw new Error("Yanıtlanan yorum bulunamadı.")
      if (parent.dealId !== dealId) throw new Error("Yanıtlanan yorum bu deal'a ait değil.")
    }

    const comment = await commentDB.createComment(
      {
        text: trimmed,
        userId,
        dealId,
        parentId: parent ? parent.id : null,
      },
      { include },
      tx
    )

    await dealDB.updateDeal(
      { id: dealId },
      { commentCount: { increment: 1 } },
      {},
      tx
    )

    return comment
  })
}


async function deleteComment(commentId, userId) {

  const comment = await commentDB.findComment(
    { id: commentId },
    { select: { userId: true, dealId: true, deletedAt: true } }
  )

  if (!comment || comment.deletedAt) throw new Error("Yorum bulunamadı.")
  if (comment.userId !== userId) throw new Error("Bu yorumu silme yetkin yok.")

  await prisma.$transaction(async (tx) => {
    const result = await commentDB.softDeleteComment({ id: commentId, deletedAt: null }, tx)
    if (result.count > 0) {
      await dealDB.updateDeal(
        { id: comment.dealId },
        { commentCount: { decrement: 1 } },
        {},
        tx
      )
    }
  })

  return { message: "Yorum silindi." }
}

async function commentChange(length,dealId){



}

module.exports = {
  getCommentsByDealId,
  createComment,
  deleteComment,
}
