import { Router } from 'express';
import { prisma } from '../config/database.js';
import { authenticate } from '../middleware/auth.js';
import { validate } from '../middleware/validate.js';
import { createOfferSchema, respondOfferSchema } from '../validators/offer.js';
import { AppError } from '../middleware/errorHandler.js';

const router = Router();

router.get('/', authenticate, async (req, res, next) => {
  try {
    const { type = 'received' } = req.query;
    const where = type === 'sent'
      ? { buyerId: req.userId }
      : { sellerId: req.userId };

    const offers = await prisma.offer.findMany({
      where,
      include: {
        listing: { include: { images: { take: 1, orderBy: { order: 'asc' } } } },
        buyer: { select: { id: true, fullName: true, nickname: true, avatar: true } },
        seller: { select: { id: true, fullName: true, nickname: true, avatar: true } },
      },
      orderBy: { createdAt: 'desc' },
    });
    res.json(offers);
  } catch (error) {
    next(error);
  }
});

router.post('/', authenticate, validate(createOfferSchema), async (req, res, next) => {
  try {
    const { amount, message, listingId } = req.body;

    const listing = await prisma.listing.findUnique({ where: { id: listingId } });
    if (!listing) throw new AppError(404, 'Listing not found');
    if (listing.status !== 'ACTIVE') throw new AppError(400, 'Listing is not active');
    if (listing.sellerId === req.userId) throw new AppError(400, 'Cannot make offer on your own listing');

    const offer = await prisma.offer.create({
      data: { amount, message, listingId, buyerId: req.userId!, sellerId: listing.sellerId },
      include: {
        listing: { include: { images: { take: 1 } } },
        buyer: { select: { id: true, fullName: true, nickname: true, avatar: true } },
        seller: { select: { id: true, fullName: true, nickname: true, avatar: true } },
      },
    });

    await prisma.notification.create({
      data: {
        userId: listing.sellerId,
        type: 'NEW_OFFER',
        title: 'New Offer',
        body: `${offer.buyer.fullName} made an offer of $${amount} for ${listing.title}`,
        data: { listingId, offerId: offer.id, amount },
      },
    });

    res.status(201).json(offer);
  } catch (error) {
    next(error);
  }
});

router.patch('/:id', authenticate, validate(respondOfferSchema), async (req, res, next) => {
  try {
    const existing = await prisma.offer.findUnique({ where: { id: req.params.id }, include: { listing: true } });
    if (!existing) throw new AppError(404, 'Offer not found');
    if (existing.sellerId !== req.userId) throw new AppError(403, 'Not authorized');
    if (existing.status !== 'PENDING') throw new AppError(400, 'Offer already responded to');

    const { status, counterAmount } = req.body;

    const offer = await prisma.offer.update({
      where: { id: req.params.id },
      data: { status, counterAmount },
      include: {
        listing: { include: { images: { take: 1 } } },
        buyer: { select: { id: true, fullName: true, nickname: true, avatar: true } },
        seller: { select: { id: true, fullName: true, nickname: true, avatar: true } },
      },
    });

    if (status === 'ACCEPTED') {
      await prisma.listing.update({ where: { id: existing.listingId }, data: { status: 'SOLD' } });
      await prisma.offer.updateMany({
        where: { listingId: existing.listingId, id: { not: existing.id }, status: 'PENDING' },
        data: { status: 'DECLINED' },
      });
    }

    const notificationType = status === 'ACCEPTED' ? 'OFFER_ACCEPTED' : status === 'DECLINED' ? 'OFFER_DECLINED' : 'NEW_OFFER';
    await prisma.notification.create({
      data: {
        userId: existing.buyerId,
        type: notificationType,
        title: status === 'ACCEPTED' ? 'Offer Accepted' : status === 'DECLINED' ? 'Offer Declined' : 'Counter Offer',
        body: `Your offer for ${existing.listing.title} was ${status.toLowerCase()}`,
        data: { offerId: existing.id, listingId: existing.listingId },
      },
    });

    res.json(offer);
  } catch (error) {
    next(error);
  }
});

export default router;
