import express from 'express';
import { Booking, Service, User } from '../models/index.js';
import { Op } from 'sequelize';
import { auth } from '../middleware/authMiddleware.js';
import { validate } from '../middleware/authMiddleware.js';
import { bookingSchemaValidation } from '../middleware/validationSchemas.js';
import { sendNotification } from '../socket/index.js';

const router = express.Router();

router.post('/', auth(['user']), validate(bookingSchemaValidation), async (req, res) => {
  try {
    const { serviceId, scheduledAt, address, duration, notes } = req.body;
    const service = await Service.findByPk(serviceId, { include: [{ model: User, as: 'provider' }] });
    if (!service) return res.status(404).json({ error: 'Service not found' });
    const price = service.price_type === 'hourly' ? service.price * (duration || 1) : service.price;
    const booking = await Booking.create({
      user_id: req.user.id, provider_id: service.provider.id, service_id: serviceId,
      scheduled_at: new Date(scheduledAt), address, duration: duration || service.duration || 1, price, notes
    });
    await sendNotification(req.app.get('io'), service.provider.id, 'booking', 'New Booking Request', `You have a new booking for ${service.title}`, { bookingId: booking.id });
    res.status(201).json({ booking });
  } catch (e) {
    res.status(500).json({ error: 'Booking failed' });
  }
});

router.get('/', auth(), async (req, res) => {
  try {
    const { status, page = 1, limit = 10 } = req.query;
    const offset = (page - 1) * limit;
    const where = req.user.role === 'provider' ? { provider_id: req.user.id } : { user_id: req.user.id };
    if (status) where.status = status;
    const { count, rows: bookings } = await Booking.findAndCountAll({
      where, include: [
        { model: Service, as: 'service', attributes: ['id', 'title', 'price', 'images', 'price_type'] },
        { model: User, as: 'user', attributes: ['id', 'name', 'avatar', 'phone'] },
        { model: User, as: 'provider', attributes: ['id', 'name', 'avatar', 'phone'] }
      ],
      offset: parseInt(offset), limit: parseInt(limit), order: [['created_at', 'DESC']]
    });
    res.json({ bookings, total: count, page: parseInt(page), pages: Math.ceil(count / limit) });
  } catch (e) {
    res.status(500).json({ error: 'Failed to fetch bookings' });
  }
});

router.get('/:id', auth(), async (req, res) => {
  try {
    const booking = await Booking.findByPk(req.params.id, {
      include: [
        { model: Service, as: 'service' },
        { model: User, as: 'user', attributes: ['id', 'name', 'avatar', 'phone'] },
        { model: User, as: 'provider', attributes: ['id', 'name', 'avatar', 'phone'] }
      ]
    });
    if (!booking) return res.status(404).json({ error: 'Booking not found' });
    if (booking.user_id !== req.user.id && booking.provider_id !== req.user.id && req.user.role !== 'admin') {
      return res.status(403).json({ error: 'Forbidden' });
    }
    res.json({ booking });
  } catch (e) {
    res.status(500).json({ error: 'Failed to fetch booking' });
  }
});

router.put('/:id/status', auth(['provider']), async (req, res) => {
  try {
    const { status } = req.body;
    const booking = await Booking.findOne({ where: { id: req.params.id, provider_id: req.user.id } });
    if (!booking) return res.status(404).json({ error: 'Booking not found' });
    const validTransitions = {
      pending: ['accepted', 'cancelled'],
      accepted: ['in_progress', 'cancelled'],
      in_progress: ['completed', 'cancelled'],
      completed: [],
      cancelled: [],
      disputed: []
    };
    if (!validTransitions[booking.status]?.includes(status)) return res.status(400).json({ error: 'Invalid status transition' });
    booking.status = status;
    if (status === 'completed') booking.completed_at = new Date();
    if (status === 'cancelled') { booking.cancelled_at = new Date(); booking.cancellation_reason = req.body.reason; }
    await booking.save();
    await sendNotification(req.app.get('io'), booking.user_id, 'booking', `Booking ${status}`, `Your booking has been ${status}`, { bookingId: booking.id });
    req.app.get('io').to(`booking:${booking.id}`).emit('booking:status', { bookingId: booking.id, status });
    res.json({ booking });
  } catch (e) {
    res.status(500).json({ error: 'Status update failed' });
  }
});

export default router;