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

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

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

    const result = await Category.findAllActive(options);

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

// Get category by ID with details
const getCategoryById = 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 category ID format'
      });
    }
    
    const category = await Category.findByIdWithDetails(id);
    
    if (!category) {
      return res.status(404).json({
        success: false,
        msg: 'Category not found'
      });
    }
    
    res.json({
      success: true,
      data: category,
      msg: 'Category retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching category:', error);
    
    // Handle specific error types
    if (error.name === 'CastError') {
      return res.status(400).json({
        success: false,
        msg: 'Invalid category ID format'
      });
    }
    
    res.status(500).json({
      success: false,
      msg: 'Error fetching category details',
      error: process.env.NODE_ENV === 'development' ? error.message : undefined
    });
  }
};

// Create new category
const createCategory = async (req, res) => {
  try {
    const { name, description, code, subtitle } = req.body;
    
    // Validation
    if (!name || !name.trim()) {
      return res.status(400).json({
        success: false,
        msg: 'Category name is required'
      });
    }

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

    const newCategory = await Category.createCategory({
      name,
      description,
      code,
      image: imagePath,
      subtitle
    });

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

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

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

// Update category
const updateCategory = async (req, res) => {
  try {
    const { id } = req.params;
    const { name, description, code, subtitle, status, position } = req.body;
    
    // Check if category exists
    const existingCategory = await Category.findById(id);
    if (!existingCategory) {
      return res.status(404).json({
        success: false,
        msg: 'Category not found'
      });
    }

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

    // If a new file is uploaded
    if (req.file) {
      // Set new image path
      imagePath = `/uploads/categories/${req.file.filename}`;
      
      // Mark old image for deletion if it exists
      if (existingCategory.image) {
        const filename = existingCategory.image.split('/').pop();
        oldImagePath = path.join(getUploadsPath(), 'categories', filename);
      }
    } 
    // If image is being removed (sent as removeImage flag)
    else if (req.body.removeImage === 'true') {
      // Mark old image for deletion
      if (existingCategory.image) {
        const filename = existingCategory.image.split('/').pop();
        oldImagePath = path.join(getUploadsPath(), 'categories', 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 category image:', error);
        // Don't fail the request if image deletion fails
      }
    }

    const updateData = {
      name,
      description,
      code,
      image: imagePath,
      subtitle,
      status,
      ...(position !== undefined && { position: parseInt(position) })
    };

    const updatedCategory = await Category.updateCategory(id, updateData);

    res.json({
      success: true,
      data: updatedCategory,
      msg: 'Category updated successfully'
    });
  } catch (error) {
    console.error('Error updating category:', error);

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

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

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

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

    const updatedCategory = await Category.findByIdAndUpdate(
      id,
      { status: !existingCategory.status },
      { new: true }
    );

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

// Permanently delete category (hard delete)
const deleteCategory = async (req, res) => {
  try {
    const { id } = req.params;
    
    // Check if category exists
    const existingCategory = await Category.findById(id);
    if (!existingCategory) {
      return res.status(404).json({
        success: false,
        msg: 'Category not found'
      });
    }

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

    // Delete associated image if exists
    if (existingCategory.image) {
      try {
        // The image field might be a string or an object with url property
        let imagePath = existingCategory.image;
        
        // If it's an object with url property, use that
        if (typeof existingCategory.image === 'object' && existingCategory.image.url) {
          imagePath = existingCategory.image.url;
        }

        if (!imagePath) {
          console.log('No valid image path found in category.image');
          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/categories/
          path.join(getUploadsPath('categories'), filename),
          // Relative to uploads/
          path.join(getUploadsPath(), filename),
          // If the path includes 'uploads/categories/' already
          path.join(process.cwd(), 'uploads', 'categories', 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 category image at: ${currentPath}`);
            await fs.access(currentPath);
            await deleteFile(currentPath);
            console.log(`Successfully deleted category image: ${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 category image at any of the following paths:', possiblePaths);
        }
      } catch (error) {
        console.error('Error during category image file deletion:', error);
        // Don't fail the entire operation if image deletion fails
      }
    }

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

// Get category statistics
const getCategoryStatistics = async (req, res) => {
  try {
    const statistics = await Category.getStatistics();

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

// Get active categories
const getActiveCategories = async (req, res) => {
  try {
    const { limit = 10 } = req.query;
    
    // Use findAllActive method or a safe alternative
    const result = await Category.findAllActive({
      limit: parseInt(limit),
      page: 1,
      search: undefined,
      filter: { status: true }
    });

    // If findAllActive doesn't exist, fallback to a safe query
    const categories = result.items || await Category.find({ status: true })
      .select('_id name image slug')
      .limit(parseInt(limit))
      .sort({ sortOrder: 1, name: 1 })
      .lean();

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

// Search categories
const searchCategories = 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 categories = await Category.findAllActive({
      search: query,
      limit: parseInt(limit),
      page: 1
    });

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

module.exports = {
  getAllCategories,
  getCategoryById,
  createCategory,
  updateCategory,
  toggleCategoryStatus,
  deleteCategory,
  getCategoryStatistics,
  searchCategories,
  getActiveCategories
}; 