const path = require('path');
const fs = require('fs');
const { Booking } = require('../models');
const bookingService = require('../services/BookingService');

class BookingController {
  async create(req, res, next) {
    try {
      const result = await bookingService.createBooking(req.body);
      res.status(201).json({
        message: 'Booking created successfully',
        booking: result.booking,
        availability: result.availability,
      });
    } catch (error) {
      next(error);
    }
  }

  async getByReference(req, res, next) {
    try {
      const booking = await bookingService.getBookingByReference(req.params.reference);
      res.json({ booking });
    } catch (error) {
      next(error);
    }
  }

  async updateStatus(req, res, next) {
    try {
      const { status } = req.body;
      if (!status) {
        return res.status(400).json({ error: 'Status is required' });
      }

      const booking = await bookingService.updateBookingStatus(req.params.id, status, req.user);
      res.json({
        message: `Booking ${status}`,
        booking,
      });
    } catch (error) {
      next(error);
    }
  }

  async getAll(req, res, next) {
    try {
      const { status, date } = req.query;
      const bookings = await bookingService.getAllBookings({ status, date });
      res.json({ bookings });
    } catch (error) {
      next(error);
    }
  }

  async checkAvailability(req, res, next) {
    try {
      const { scheduleId, seats, fromStopId, toStopId } = req.query;
      if (!scheduleId || !seats) {
        return res.status(400).json({ error: 'scheduleId and seats required' });
      }

      const availability = await bookingService.checkAvailability(
        parseInt(scheduleId),
        parseInt(seats),
        fromStopId ? parseInt(fromStopId) : undefined,
        toStopId ? parseInt(toStopId) : undefined
      );

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

  async update(req, res, next) {
    try {
      const booking = await bookingService.updateBooking(req.params.id, req.body);
      res.json({ message: 'Booking updated', booking });
    } catch (error) {
      next(error);
    }
  }

  async delete(req, res, next) {
    try {
      const result = await bookingService.deleteBooking(req.params.id, req.user);
      res.json(result);
    } catch (error) {
      next(error);
    }
  }

  async uploadImage(req, res, next) {
    try {
      if (!req.file) return res.status(400).json({ error: 'No image uploaded' });
      const imagePath = `/uploads/${req.file.filename}`;
      const booking = await bookingService.uploadBookingImage(req.params.id, imagePath);
      res.json({ message: 'Image uploaded', image_url: imagePath, booking });
    } catch (error) {
      next(error);
    }
  }

  async uploadPOP(req, res, next) {
    try {
      if (!req.file) return res.status(400).json({ error: 'No proof of payment uploaded' });
      const filePath = `/uploads/${req.file.filename}`;
      const booking = await bookingService.uploadProofOfPayment(req.params.id, filePath);
      res.json({ message: 'Proof of payment uploaded', proof_of_payment: filePath, booking });
    } catch (error) {
      next(error);
    }
  }

  async downloadPOP(req, res, next) {
    try {
      const booking = await Booking.findByPk(req.params.id);
      if (!booking || !booking.proof_of_payment) {
        return res.status(404).json({ error: 'No proof of payment found' });
      }
      const filePath = path.join(__dirname, '..', booking.proof_of_payment);
      if (!fs.existsSync(filePath)) {
        return res.status(404).json({ error: 'File not found on server' });
      }
      const filename = path.basename(filePath);
      res.download(filePath, `POP_${booking.booking_reference}_${filename}`);
    } catch (error) {
      next(error);
    }
  }
}

module.exports = new BookingController();
