import { questionRepository } from '@/lib/repositories/question.repository';
import { categoryRepository } from '@/lib/repositories/category.repository';
import { faqRepository } from '@/lib/repositories/faq.repository';
import { HttpError } from '@/lib/auth/session';
import { CreateQuestionInput } from '@/lib/validators';
import { QuestionStatus } from '@prisma/client';

export const questionService = {
  recent: () => questionRepository.recent(),
  mostViewed: () => questionRepository.mostViewed(),
  unanswered: () => questionRepository.unanswered(),

  search(term: string, categoryId?: number) {
    const trimmed = term.trim();
    if (!trimmed) return Promise.resolve([]);
    return questionRepository.search(trimmed, { categoryId });
  },

  async listByCategorySlug(slug: string) {
    const category = await categoryRepository.findBySlug(slug);
    if (!category) throw new HttpError(404, 'Category not found');
    const questions = await questionRepository.listByCategory(category.id);
    return { category, questions };
  },

  async getDetail(id: number) {
    const question = await questionRepository.findByIdWithDetail(id);
    if (!question) throw new HttpError(404, 'Question not found');
    // Fire and forget the view increment so the page render is not
    // blocked by an extra DB write.
    questionRepository.incrementViews(id).catch(() => {});
    return question;
  },

  async create(userId: number, input: CreateQuestionInput) {
    const category = await categoryRepository.findById(input.categoryId);
    if (!category || !category.isActive) {
      throw new HttpError(400, 'Selected category is not available');
    }
    return questionRepository.create({
      userId,
      categoryId: input.categoryId,
      productName: input.productName,
      title: input.title,
      description: input.description,
      imageUrl: input.imageUrl ?? null,
    });
  },

  // Marking a best answer is the trigger that auto-promotes the
  // question into the FAQ table. The planning doc describes this as a
  // direct outcome of solving a question.
  async markBestAnswer(opts: {
    questionId: number;
    answerId: number;
    actorId: number;
    actorRole: 'ADMIN' | 'EMPLOYEE';
  }) {
    const question = await questionRepository.findByIdWithDetail(opts.questionId);
    if (!question) throw new HttpError(404, 'Question not found');

    // Only the question owner or an admin can mark the best answer.
    const isOwner = question.userId === opts.actorId;
    const isAdmin = opts.actorRole === 'ADMIN';
    if (!isOwner && !isAdmin) {
      throw new HttpError(403, 'Only the question owner or an admin can mark the best answer');
    }

    const answer = question.answers.find((a) => a.id === opts.answerId);
    if (!answer) throw new HttpError(400, 'Answer does not belong to this question');

    const updated = await questionRepository.setBestAnswer(opts.questionId, opts.answerId);
    await faqRepository.upsertForQuestion(opts.questionId, question.categoryId);
    return updated;
  },

  async reopen(questionId: number) {
    await faqRepository.removeForQuestion(questionId);
    return questionRepository.setStatus(questionId, QuestionStatus.ANSWERED);
  },
};
