import { Router } from 'express';
import prisma from '../lib/prisma';
import {
  asyncHandler,
  sendSuccess,
  AppError,
  validate,
  paramId,
} from '../lib/utils';
import { authenticate, authorize, AuthRequest } from '../middleware/auth';
import { createReviewSchema } from '../validators/schemas';
import { syncWorkerReviewStats } from '../lib/reviewStats';
import {
  checkReviewEligibility,
  checkHireReviewEligibility,
  findPendingReviewJobs,
  findPendingHireReviews,
} from '../lib/reviewEligibility';
import { createAndEmitNotification } from '../services/notification.service';

const router = Router();

router.get(
  '/eligible/:jobId',
  authenticate,
  authorize('CUSTOMER'),
  asyncHandler(async (req: AuthRequest, res) => {
    const eligibility = await checkReviewEligibility(
      paramId(req.params.jobId),
      req.user!.userId
    );
    sendSuccess(res, eligibility);
  })
);

router.get(
  '/eligible-hire/:hireInvitationId',
  authenticate,
  authorize('CUSTOMER'),
  asyncHandler(async (req: AuthRequest, res) => {
    const eligibility = await checkHireReviewEligibility(
      paramId(req.params.hireInvitationId),
      req.user!.userId
    );
    sendSuccess(res, eligibility);
  })
);

router.get(
  '/pending',
  authenticate,
  authorize('CUSTOMER'),
  asyncHandler(async (req: AuthRequest, res) => {
    const [jobs, hires] = await Promise.all([
      findPendingReviewJobs(req.user!.userId),
      findPendingHireReviews(req.user!.userId),
    ]);

    const pendingJobs = jobs.map((job) => ({
      kind: 'job' as const,
      id: job.id,
      title: job.title,
      categoryName: job.category.name,
      worker: job.worker,
    }));

    const pendingHires = hires.map((hire) => ({
      kind: 'hire' as const,
      id: hire.id,
      title: 'Direct hire',
      categoryName: hire.worker.skills[0]?.category.name ?? 'Service',
      worker: hire.worker,
    }));

    sendSuccess(res, [...pendingHires, ...pendingJobs]);
  })
);

router.get(
  '/my',
  authenticate,
  authorize('CUSTOMER'),
  asyncHandler(async (req: AuthRequest, res) => {
    const reviews = await prisma.review.findMany({
      where: { customerId: req.user!.userId },
      orderBy: { createdAt: 'desc' },
      include: {
        worker: {
          include: { user: { select: { firstName: true, lastName: true, avatarUrl: true } } },
        },
        job: { select: { id: true, title: true } },
        hireInvitation: { select: { id: true, status: true } },
      },
    });
    sendSuccess(res, reviews);
  })
);

router.post(
  '/',
  authenticate,
  authorize('CUSTOMER'),
  validate(createReviewSchema),
  asyncHandler(async (req: AuthRequest, res) => {
    const {
      jobId,
      hireInvitationId,
      qualityRating,
      communicationRating,
      punctualityRating,
      comment,
    } = req.body;

    const eligibility = hireInvitationId
      ? await checkHireReviewEligibility(hireInvitationId, req.user!.userId)
      : await checkReviewEligibility(jobId, req.user!.userId);

    if (!eligibility.eligible) {
      throw new AppError(eligibility.reason, 403);
    }

    if (eligibility.source === 'job' && eligibility.jobId) {
      const existing = await prisma.review.findUnique({ where: { jobId: eligibility.jobId } });
      if (existing) throw new AppError('Review already submitted for this job', 409);
    }
    if (eligibility.source === 'hire' && eligibility.hireInvitationId) {
      const existing = await prisma.review.findUnique({
        where: { hireInvitationId: eligibility.hireInvitationId },
      });
      if (existing) throw new AppError('Review already submitted for this hire', 409);
    }

    const overallRating = (qualityRating + communicationRating + punctualityRating) / 3;

    const review = await prisma.review.create({
      data: {
        jobId: eligibility.jobId ?? null,
        hireInvitationId: eligibility.hireInvitationId ?? null,
        customerId: req.user!.userId,
        workerId: eligibility.workerId,
        qualityRating,
        communicationRating,
        punctualityRating,
        overallRating,
        comment,
      },
      include: {
        job: { select: { title: true } },
        hireInvitation: { select: { id: true } },
        customer: { select: { firstName: true, lastName: true } },
        worker: {
          include: { user: { select: { id: true, firstName: true, lastName: true } } },
        },
      },
    });

    await syncWorkerReviewStats(eligibility.workerId);

    const customerName = `${review.customer.firstName} ${review.customer.lastName}`;
    const contextLabel = review.job?.title ?? 'your direct hire';
    await createAndEmitNotification(
      review.worker.user.id,
      'REVIEW_RECEIVED',
      'New Review Received',
      `${customerName} left you a ${overallRating.toFixed(1)}-star review for "${contextLabel}"`,
      {
        reviewId: review.id,
        jobId: eligibility.jobId ?? null,
        hireInvitationId: eligibility.hireInvitationId ?? null,
        workerId: eligibility.workerId,
        overallRating,
      }
    );

    sendSuccess(res, review, 'Review submitted', 201);
  })
);

router.get(
  '/worker/:workerId',
  asyncHandler(async (req, res) => {
    const reviews = await prisma.review.findMany({
      where: { workerId: paramId(req.params.workerId) },
      orderBy: { createdAt: 'desc' },
      include: {
        customer: { select: { firstName: true, lastName: true, avatarUrl: true } },
        job: { select: { title: true } },
        hireInvitation: { select: { id: true } },
      },
    });
    sendSuccess(res, reviews);
  })
);

export default router;
