import { prisma } from '@/lib/db/prisma';
import { Prisma, QuestionStatus } from '@prisma/client';

export const questionRepository = {
  // Lightweight projection used in lists. Avoids pulling the full
  // description text for every row.
  listByCategory(categoryId: number, take = 50) {
    return prisma.question.findMany({
      where: { categoryId },
      orderBy: { createdAt: 'desc' },
      take,
      select: questionListSelect,
    });
  },

  recent(take = 10) {
    return prisma.question.findMany({
      orderBy: { createdAt: 'desc' },
      take,
      select: questionListSelect,
    });
  },

  mostViewed(take = 10) {
    return prisma.question.findMany({
      orderBy: { views: 'desc' },
      take,
      select: questionListSelect,
    });
  },

  unanswered(take = 10) {
    return prisma.question.findMany({
      where: { status: QuestionStatus.OPEN },
      orderBy: { createdAt: 'desc' },
      take,
      select: questionListSelect,
    });
  },

  // Search by title/description/product. MySQL full-text would be
  // ideal at scale, but a LIKE-based search keeps the schema simple
  // and works fine for an internal tool.
  search(term: string, opts: { categoryId?: number } = {}) {
    const q = `%${term}%`;
    return prisma.question.findMany({
      where: {
        AND: [
          opts.categoryId ? { categoryId: opts.categoryId } : {},
          {
            OR: [
              { title: { contains: term } },
              { description: { contains: term } },
              { productName: { contains: term } },
            ],
          },
        ],
      },
      orderBy: { createdAt: 'desc' },
      take: 50,
      select: questionListSelect,
    });
  },

  // Full detail for the question page, including all answers and the
  // user who posted each one.
  findByIdWithDetail(id: number) {
    return prisma.question.findUnique({
      where: { id },
      include: {
        user: { select: { id: true, name: true } },
        category: { select: { id: true, name: true, slug: true } },
        answers: {
          orderBy: [{ isBest: 'desc' }, { createdAt: 'asc' }],
          include: {
            user: { select: { id: true, name: true } },
          },
        },
      },
    });
  },

  create(data: Prisma.QuestionUncheckedCreateInput) {
    return prisma.question.create({ data });
  },

  incrementViews(id: number) {
    return prisma.question.update({
      where: { id },
      data: { views: { increment: 1 } },
    });
  },

  setBestAnswer(questionId: number, answerId: number) {
    // Wrap in a transaction so the best_answer_id, the answer flag,
    // and the question status all change together. Without this,
    // a partial failure would leave the data inconsistent.
    return prisma.$transaction(async (tx) => {
      await tx.answer.updateMany({
        where: { questionId },
        data: { isBest: false },
      });
      await tx.answer.update({
        where: { id: answerId },
        data: { isBest: true },
      });
      return tx.question.update({
        where: { id: questionId },
        data: {
          bestAnswerId: answerId,
          status: QuestionStatus.SOLVED,
        },
      });
    });
  },

  setStatus(id: number, status: QuestionStatus) {
    return prisma.question.update({ where: { id }, data: { status } });
  },
};

// Shared select for list views. Centralised so the API contract for
// list rows stays consistent everywhere.
const questionListSelect = {
  id: true,
  title: true,
  productName: true,
  status: true,
  views: true,
  createdAt: true,
  category: { select: { id: true, name: true, slug: true } },
  user: { select: { id: true, name: true } },
  _count: { select: { answers: true } },
} satisfies Prisma.QuestionSelect;
