import { Router } from 'express';
import { Booking, Service, Vehicle } from '../models/index.js';
import { requireAuth, requireRole } from '../middleware/auth.js';
import { sendError } from '../util/httpError.js';

const router = Router();

function toBookingResponse(row) {
  return {
    id: Number(row.id),
    user_id: Number(row.user_id),
    vehicle_id: Number(row.vehicle_id),
    service_id: Number(row.service_id),
    booking_type: row.booking_type,
    home_address: row.home_address,
    contact_name: row.contact_name,
    contact_phone: row.contact_phone,
    customer_note: row.customer_note,
    status: row.status,
    scheduled_date: row.scheduled_date,
    created_at: row.created_at,
    vehicle_brand: row.vehicle?.brand ?? null,
    vehicle_model: row.vehicle?.model ?? null,
    number_plate: row.vehicle?.number_plate ?? null,
    service_name: row.service?.name ?? null,
    service_price: row.service?.price ?? null,
  };
}

router.post('/', requireAuth, requireRole('customer'), async (req, res) => {
  const {
    vehicle_id,
    service_id,
    scheduled_date,
    booking_type = 'workshop',
    home_address,
    contact_name,
    contact_phone,
    customer_note,
  } = req.body || {};
  if (!vehicle_id || !service_id || !scheduled_date) {
    return sendError(
      res,
      400,
      'VALIDATION_ERROR',
      'vehicle_id, service_id, scheduled_date required'
    );
  }
  if (!['workshop', 'home'].includes(booking_type)) {
    return sendError(res, 400, 'VALIDATION_ERROR', 'booking_type must be workshop or home');
  }
  if (booking_type === 'home' && (!home_address || !contact_phone)) {
    return sendError(
      res,
      400,
      'VALIDATION_ERROR',
      'home_address and contact_phone required for home booking'
    );
  }
  const vehicle = await Vehicle.findOne({
    where: { id: Number(vehicle_id), user_id: req.user.id },
  });
  if (!vehicle) {
    return sendError(res, 404, 'NOT_FOUND', 'Vehicle not found');
  }
  const created = await Booking.create({
    user_id: req.user.id,
    vehicle_id: Number(vehicle_id),
    service_id: Number(service_id),
    booking_type,
    home_address: booking_type === 'home' ? String(home_address).trim() : null,
    contact_name: contact_name ? String(contact_name).trim() : null,
    contact_phone: booking_type === 'home' ? String(contact_phone).trim() : null,
    customer_note: customer_note ? String(customer_note).trim() : null,
    status: 'pending',
    scheduled_date,
  });
  const booking = await Booking.findByPk(created.id, {
    include: [
      { model: Vehicle, as: 'vehicle', attributes: ['brand', 'model', 'number_plate'] },
      { model: Service, as: 'service', attributes: ['name', 'price'] },
    ],
  });
  return res.status(201).json({ booking: toBookingResponse(booking) });
});

router.get('/', requireAuth, async (req, res) => {
  const include = [
    { model: Vehicle, as: 'vehicle', attributes: ['brand', 'model', 'number_plate'] },
    { model: Service, as: 'service', attributes: ['name', 'price'] },
  ];
  if (req.user.role === 'admin') {
    const rows = await Booking.findAll({ include, order: [['id', 'DESC']] });
    return res.json({ bookings: rows.map(toBookingResponse) });
  }
  if (req.user.role === 'customer') {
    const rows = await Booking.findAll({
      where: { user_id: req.user.id },
      include,
      order: [['id', 'DESC']],
    });
    return res.json({ bookings: rows.map(toBookingResponse) });
  }
  return sendError(res, 403, 'FORBIDDEN', 'Role cannot list bookings here');
});

router.get('/:id', requireAuth, async (req, res) => {
  const id = Number(req.params.id);
  const b = await Booking.findByPk(id, {
    include: [
      { model: Vehicle, as: 'vehicle', attributes: ['brand', 'model', 'number_plate'] },
      { model: Service, as: 'service', attributes: ['name', 'price'] },
    ],
  });
  if (!b) {
    return sendError(res, 404, 'NOT_FOUND', 'Booking not found');
  }
  if (req.user.role === 'customer' && Number(b.user_id) !== req.user.id) {
    return sendError(res, 403, 'FORBIDDEN', 'Not your booking');
  }
  if (req.user.role === 'employee') {
    return sendError(res, 403, 'FORBIDDEN', 'Use tasks view');
  }
  return res.json({ booking: toBookingResponse(b) });
});

router.patch('/:id', requireAuth, requireRole('admin', 'super_admin'), async (req, res) => {
  const id = Number(req.params.id);
  const status = req.body?.status;
  const allowed = ['pending', 'confirmed', 'in_progress', 'completed', 'cancelled'];
  if (!allowed.includes(status)) {
    return sendError(res, 400, 'VALIDATION_ERROR', 'Invalid status');
  }
  const booking = await Booking.findByPk(id);
  if (!booking) {
    return sendError(res, 404, 'NOT_FOUND', 'Booking not found');
  }
  booking.status = status;
  await booking.save();
  const out = await Booking.findByPk(id, {
    include: [
      { model: Vehicle, as: 'vehicle', attributes: ['brand', 'model', 'number_plate'] },
      { model: Service, as: 'service', attributes: ['name', 'price'] },
    ],
  });
  return res.json({ booking: toBookingResponse(out) });
});

export default router;
