const ErrorResponse = require('../utils/errorResponse');
const asyncHandler = require('../middleware/async');
const Banner = require('../models/Banner');
const path = require('path');
const fs = require('fs');

// Define uploads directory path
const uploadsDir = path.join(process.cwd(), 'uploads');

// @desc    Get all banners
// @route   GET /api/v1/banners
// @access  Public
exports.getBanners = asyncHandler(async (req, res, next) => {
  const { type, isActive } = req.query;
  
  // Build query
  const query = {};
  if (type) query.type = type;
  if (isActive) query.isActive = isActive === 'true';

  const banners = await Banner.find(query)
    .sort({ position: 1, createdAt: -1 })
    .populate('createdBy', 'name');

  res.status(200).json({
    success: true,
    count: banners.length,
    data: banners
  });
});

// @desc    Get active banners by type
// @route   GET /api/v1/banners/active
// @access  Public
exports.getActiveBanners = asyncHandler(async (req, res, next) => {
  const { type = 'main' } = req.query;
  const banners = await Banner.getActiveBanners(type);
  
  res.status(200).json({
    success: true,
    count: banners.length,
    data: banners
  });
});

// @desc    Get single banner
// @route   GET /api/v1/banners/:id
// @access  Public
exports.getBanner = asyncHandler(async (req, res, next) => {
  const banner = await Banner.findById(req.params.id).populate('createdBy', 'name');

  if (!banner) {
    return next(
      new ErrorResponse(`Banner not found with id of ${req.params.id}`, 404)
    );
  }

  res.status(200).json({
    success: true,
    data: banner
  });
});

// @desc    Create new banner
// @route   POST /api/v1/banners
// @access  Private/Admin
exports.createBanner = asyncHandler(async (req, res, next) => {
  // Add user to req.body
  req.body.createdBy = req.user.id;

  const banner = await Banner.create(req.body);

  res.status(201).json({
    success: true,
    data: banner
  });
});

// @desc    Update banner
// @route   PUT /api/v1/banners/:id
// @access  Private/Admin
exports.updateBanner = asyncHandler(async (req, res, next) => {
  let banner = await Banner.findById(req.params.id);

  if (!banner) {
    return next(
      new ErrorResponse(`Banner not found with id of ${req.params.id}`, 404)
    );
  }

  // Make sure user is banner owner or admin
  if (banner.createdBy.toString() !== req.user.id && req.user.role !== 'admin') {
    return next(
      new ErrorResponse(
        `User ${req.user.id} is not authorized to update this banner`,
        401
      )
    );
  }

  banner = await Banner.findByIdAndUpdate(req.params.id, req.body, {
    new: true,
    runValidators: true
  });

  res.status(200).json({
    success: true,
    data: banner
  });
});

// @desc    Delete banner
// @route   DELETE /api/v1/banners/:id
// @access  Private/Admin
exports.deleteBanner = asyncHandler(async (req, res, next) => {
  const banner = await Banner.findById(req.params.id);

  if (!banner) {
    return next(
      new ErrorResponse(`Banner not found with id of ${req.params.id}`, 404)
    );
  }

  // Delete the associated image file if it exists
  if (banner.image) {
    const uploadsDir = path.join(__dirname, '../uploads');
    const imagePath = path.join(uploadsDir, banner.image);
    
    if (fs.existsSync(imagePath)) {
      try {
        fs.unlinkSync(imagePath);
      } catch (err) {
        console.error('Error deleting banner image:', err);
      }
    }
  }

  await banner.deleteOne();

  res.status(200).json({
    success: true,
    data: {}
  });
});

// @desc    Upload photo for banner
// @route   PUT /api/v1/banners/:id/photo
// @access  Private/Admin
exports.bannerPhotoUpload = asyncHandler(async (req, res, next) => {
  try {
    const banner = await Banner.findById(req.params.id);

    if (!banner) {
      return next(
        new ErrorResponse(`Banner not found with id of ${req.params.id}`, 404)
      );
    }

    if (!req.uploadedFile) {
      return next(new ErrorResponse('No file was uploaded', 400));
    }

    const { path: relativePath, fullPath, url } = req.uploadedFile;

    // Verify the file was actually saved
    if (!fs.existsSync(fullPath)) {
      return next(new ErrorResponse('Failed to save the uploaded file', 500));
    }

    // Delete old photo if exists
    if (banner.image) {
      try {
        // The banner.image should be the relative path from the uploads directory
        const oldFilePath = path.join(process.cwd(), 'uploads', banner.image);
        if (fs.existsSync(oldFilePath)) {
          fs.unlinkSync(oldFilePath);
          console.log('Deleted old banner image:', oldFilePath);
        }
      } catch (err) {
        console.error('Error deleting old banner image:', err);
        // Continue with the new upload even if old file deletion fails
      }
    }

    // Ensure we have a clean path (just the filename for banners)
    const filename = path.basename(relativePath);
    
    // Update banner with new image path (relative to uploads directory)
    banner.image = `banners/${filename}`;
    await banner.save();
    
    // Construct the correct image URL
    const baseUrl = `${req.protocol}://${req.get('host')}`;
    
    // Create the full URL
    const imageUrl = `${baseUrl}/uploads/banners/${filename}`;
    
    console.log('Generated image URL:', {
      baseUrl,
      originalPath: relativePath,
      savedPath: banner.image,
      finalUrl: imageUrl
    });
    
    // Set the imageUrl for the response
    banner.imageUrl = imageUrl;

    res.status(200).json({
      success: true,
      data: {
        ...banner.toObject(),
        imageUrl: imageUrl
      }
    });
  } catch (error) {
    // Clean up the uploaded file if there was an error
    if (req.uploadedFile?.fullPath && fs.existsSync(req.uploadedFile.fullPath)) {
      try {
        fs.unlinkSync(req.uploadedFile.fullPath);
      } catch (e) {
        console.error('Error cleaning up failed upload:', e);
      }
    }
    
    console.error('Error in banner photo upload:', error);
    next(error);
  }
});
