const Brand = require('../models/Brand');
const { deleteFile, getUploadsPath } = require('../utils/fileUtils');
const path = require('path');
const fs = require('fs').promises;

// Get all brands with pagination and search
const getAllBrands = async (req, res) => {
  try {
    const {
      page = 1,
      limit = 10,
      search,
      company,
      sortBy = 'createdAt',
      sortOrder = 'desc'
    } = req.query;

    const options = {
      page: parseInt(page),
      limit: parseInt(limit),
      search: search || undefined,
      company: company || undefined
    };

    const result = await Brand.findAllActive(options);

    res.json({
      success: true,
      data: result.items,
      pagination: {
        currentPage: result.currentPage,
        totalPages: result.totalPages,
        totalBrands: result.total,
        hasNextPage: result.hasNextPage,
        hasPreviousPage: result.hasPreviousPage
      },
      msg: 'Brands retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching brands:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error fetching brands'
    });
  }
};

// Get brand by ID with details
const getBrandById = async (req, res) => {
  try {
    const { id } = req.params;
    
    // Validate ID format
    if (!id || !/^[0-9a-fA-F]{24}$/.test(id)) {
      return res.status(400).json({
        success: false,
        msg: 'Invalid brand ID format'
      });
    }
    
    const brand = await Brand.findByIdWithDetails(id);

    if (!brand) {
      return res.status(404).json({
        success: false,
        msg: 'Brand not found'
      });
    }

    res.json({
      success: true,
      data: brand,
      msg: 'Brand retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching brand:', error);
    
    // Handle specific error types
    if (error.name === 'CastError') {
      return res.status(400).json({
        success: false,
        msg: 'Invalid brand ID format'
      });
    }
    
    res.status(500).json({
      success: false,
      msg: 'Error fetching brand details',
      error: process.env.NODE_ENV === 'development' ? error.message : undefined
    });
  }
};

// Get brands with item counts (for analytics)
const getBrandsWithItemCounts = async (req, res) => {
  try {
    const { limit = 20 } = req.query;
    const brands = await Brand.findWithItemCounts({ limit: parseInt(limit) });

    res.json({
      success: true,
      data: brands,
      msg: 'Brands with item counts retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching brands with item counts:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error fetching brands with item counts'
    });
  }
};

// Search brands
const searchBrands = async (req, res) => {
  try {
    const { query, limit = 10 } = req.query;

    if (!query) {
      return res.status(400).json({
        success: false,
        msg: 'Search query is required'
      });
    }

    const brands = await Brand.findAllActive({
      search: query,
      limit: parseInt(limit),
      page: 1
    });

    res.json({
      success: true,
      data: brands.items,
      total: brands.total,
      msg: 'Search completed successfully'
    });
  } catch (error) {
    console.error('Error searching brands:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error searching brands'
    });
  }
};

// Get brands by company
const getBrandsByCompany = async (req, res) => {
  try {
    const { companyName } = req.params;
    const { page = 1, limit = 10 } = req.query;

    const brands = await Brand.findAllActive({
      company: companyName,
      page: parseInt(page),
      limit: parseInt(limit)
    });

    res.json({
      success: true,
      data: brands.items,
      pagination: {
        currentPage: brands.currentPage,
        totalPages: brands.totalPages,
        totalBrands: brands.total,
        hasNextPage: brands.hasNextPage,
        hasPreviousPage: brands.hasPreviousPage
      },
      msg: 'Brands by company retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching brands by company:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error fetching brands by company'
    });
  }
};

// Create new brand
const createBrand = async (req, res) => {
  try {
    const { brandName, companyName, description } = req.body;

    // Validation
    if (!brandName || !brandName.trim()) {
      return res.status(400).json({
        success: false,
        msg: 'Brand name is required'
      });
    }

    // Handle uploaded image
    let imagePath = null;
    if (req.file) {
      imagePath = `/uploads/brands/${req.file.filename}`;
    }

    const newBrand = await Brand.createBrand({
      brandName,
      companyName,
      description,
      images: imagePath
    });

    res.status(201).json({
      success: true,
      data: newBrand,
      msg: 'Brand created successfully'
    });
  } catch (error) {
    console.error('Error creating brand:', error);

    // Handle specific validation errors
    if (error.message === 'Brand name already exists') {
      return res.status(409).json({
        success: false,
        msg: error.message
      });
    }

    res.status(500).json({
      success: false,
      msg: error.message || 'Error creating brand'
    });
  }
};

// Update brand
const updateBrand = async (req, res) => {
  try {
    const { id } = req.params;
    const { brandName, companyName, description, status } = req.body;

    // Check if brand exists
    const existingBrand = await Brand.findById(id);
    if (!existingBrand) {
      return res.status(404).json({
        success: false,
        msg: 'Brand not found'
      });
    }

    // Handle image update from form data (req.file) or direct URL (req.body.images)
    let imagePath = existingBrand.images; // Keep existing image by default
    let oldImagePath = null;

    // If a new file is uploaded
    if (req.file) {
      // Set new image path
      imagePath = `/uploads/brands/${req.file.filename}`;
      
      // Mark old image for deletion if it exists
      if (existingBrand.images) {
        const filename = existingBrand.images.split('/').pop();
        oldImagePath = path.join(getUploadsPath(), 'brands', filename);
      }
    } 
    // If image is being removed (sent as removeImage flag)
    else if (req.body.removeImage === 'true') {
      // Mark old image for deletion
      if (existingBrand.images) {
        const filename = existingBrand.images.split('/').pop();
        oldImagePath = path.join(getUploadsPath(), 'brands', filename);
      }
      imagePath = ''; // Clear the image path
    }

    // Delete old image file if needed
    if (oldImagePath) {
      try {
        await deleteFile(oldImagePath);
      } catch (error) {
        console.error('Error deleting old brand image:', error);
        // Don't fail the request if image deletion fails
      }
    }

    const updateData = {
      brandName,
      companyName,
      description,
      images: imagePath,
      status
    };

    const updatedBrand = await Brand.updateBrand(id, updateData);

    res.json({
      success: true,
      data: updatedBrand,
      msg: 'Brand updated successfully'
    });
  } catch (error) {
    console.error('Error updating brand:', error);

    // Handle specific validation errors
    if (error.message === 'Brand name already exists') {
      return res.status(409).json({
        success: false,
        msg: error.message
      });
    }

    res.status(500).json({
      success: false,
      msg: error.message || 'Error updating brand'
    });
  }
};

// Toggle brand status
const toggleBrandStatus = async (req, res) => {
  try {
    const { id } = req.params;

    // Check if brand exists
    const existingBrand = await Brand.findById(id);
    if (!existingBrand) {
      return res.status(404).json({
        success: false,
        msg: 'Brand not found'
      });
    }

    const updatedBrand = await Brand.findByIdAndUpdate(
      id,
      { status: !existingBrand.status },
      { new: true }
    );

    res.json({
      success: true,
      data: updatedBrand,
      msg: `Brand ${updatedBrand.status ? 'activated' : 'deactivated'} successfully`
    });
  } catch (error) {
    console.error('Error toggling brand status:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error toggling brand status'
    });
  }
};

// Permanently delete brand
const deleteBrand = async (req, res) => {
  try {
    const { id } = req.params;

    // Check if brand exists
    const existingBrand = await Brand.findById(id);
    if (!existingBrand) {
      return res.status(404).json({
        success: false,
        msg: 'Brand not found'
      });
    }

    // Check if brand has associated items
    const itemsWithBrand = await Brand.findByIdWithDetails(id);
    if (itemsWithBrand && itemsWithBrand.itemCount > 0) {
      return res.status(400).json({
        success: false,
        msg: `Cannot delete brand with ${itemsWithBrand.itemCount} associated items. Please delete all items first or reassign them to another brand.`
      });
    }

    // Delete associated image if exists
    if (existingBrand.images) {
      try {
        // The images field might be a JSON string or a direct path
        let imagePath;
        
        try {
          // Try to parse as JSON first
          const images = JSON.parse(existingBrand.images);
          // If it's an array, take the first image
          imagePath = Array.isArray(images) ? images[0] : images;
        } catch (e) {
          // If not JSON, use the value directly
          imagePath = existingBrand.images;
        }

        if (!imagePath) {
          console.log('No valid image path found in brand.images');
          return;
        }

        // Extract just the filename from the path/URL
        const filename = path.basename(imagePath);
        
        // Try different possible locations for the file
        const possiblePaths = [
          // Direct path if it's an absolute path
          imagePath,
          // Relative to uploads/brands/
          path.join(getUploadsPath('brands'), filename),
          // Relative to uploads/
          path.join(getUploadsPath(), filename),
          // If the path includes 'uploads/brands/' already
          path.join(process.cwd(), 'uploads', 'brands', filename),
          // If the path is just the filename
          path.join(process.cwd(), 'uploads', filename)
        ];

        let deleted = false;
        
        // Try each possible path until we find and delete the file
        for (const currentPath of possiblePaths) {
          try {
            console.log(`Attempting to delete file at: ${currentPath}`);
            await fs.access(currentPath);
            await deleteFile(currentPath);
            console.log(`Successfully deleted file: ${currentPath}`);
            deleted = true;
            break; // Stop after successful deletion
          } catch (err) {
            if (err.code !== 'ENOENT') {
              console.error(`Error accessing file at ${currentPath}:`, err);
            }
          }
        }

        if (!deleted) {
          console.warn('Could not find or delete the image file at any of the following paths:', possiblePaths);
        }
      } catch (error) {
        console.error('Error during image file deletion:', error);
        // Don't fail the entire operation if image deletion fails
      }
    }

    await Brand.deleteBrand(id);

    res.json({
      success: true,
      msg: 'Brand and associated files permanently deleted successfully'
    });
  } catch (error) {
    console.error('Error deleting brand:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error deleting brand'
    });
  }
};

// Get brand statistics
const getBrandStatistics = async (req, res) => {
  try {
    const statistics = await Brand.getStatistics();

    res.json({
      success: true,
      data: statistics,
      msg: 'Brand statistics retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching brand statistics:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error fetching brand statistics'
    });
  }
};

// Get brands with low item count (for inventory management)
const getBrandsNeedingAttention = async (req, res) => {
  try {
    const { threshold = 5 } = req.query;

    const brands = await Brand.aggregate([
      {
        $lookup: {
          from: 'items',
          let: { brandId: '$_id' },
          pipeline: [
            {
              $match: {
                $expr: { $eq: ['$brandId', '$$brandId'] }
              }
            },
            {
              $count: 'count'
            }
          ],
          as: 'itemCount'
        }
      },
      {
        $addFields: {
          items_count: { $arrayElemAt: ['$itemCount.count', 0] }
        }
      },
      {
        $match: {
          $or: [
            { items_count: { $lt: parseInt(threshold) } },
            { items_count: { $exists: false } }
          ]
        }
      },
      {
        $project: {
          itemCount: 0
        }
      },
      {
        $sort: { items_count: 1, brandName: 1 }
      }
    ]);

    res.json({
      success: true,
      data: brands,
      msg: 'Brands needing attention retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching brands needing attention:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error fetching brands needing attention'
    });
  }
};

module.exports = {
  getAllBrands,
  getBrandById,
  getBrandsWithItemCounts,
  searchBrands,
  getBrandsByCompany,
  createBrand,
  updateBrand,
  toggleBrandStatus,
  deleteBrand,
  getBrandStatistics,
  getBrandsNeedingAttention
}; 