const Account = require('../models/account.model');
const ProductService = require('../services/product');
const { validationResult } = require('express-validator');
const mongoose = require('mongoose');

class ProductController {
  /**
   * Create a new product
   * @param {Object} req - Express request object
   * @param {Object} res - Express response object
   */
  static async createProduct(req, res) {
    try {
      // Validate request
      if (!req.body.name || !req.body.price || !req.body.stock) {
        console.log('Product name, price, and stock are required');
        return res.status(400).json({
          success: false,
          message: 'Product name, price, and stock are required',
        });
      }

      // Get user ID from authenticated user
      const userId = req.user.id;

      if (!req.file) {
        console.log('Product image is required');
        return res.status(400).json({
          success: false,
          message: 'Product image is required',
        });
      }

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      const productData = {
        ...req.body,
        userId, // Associate product with the authenticated user
      };

      const fileBase64 = req.file.buffer.toString('base64');
      const dataUri = `data:${req.file.mimetype};base64,${fileBase64}`;

      productData.file = dataUri;

      const product = await ProductService.createProduct(productData);
      res.status(201).json({
        success: true,
        message: 'Product created successfully',
        data: product,
      });
    } catch (error) {
      console.log(error);
      res.status(500).json({
        success: false,
        message: error.message,
      });
    }
  }

  /**
   * Get product by ID
   * @param {Object} req - Express request object
   * @param {Object} res - Express response object
   */
  static async getProduct(req, res) {
    try {
      const { id } = req.params;

      if (!mongoose.Types.ObjectId.isValid(id)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid product ID format',
        });
      }

      let isAdmin =
        req.user?.role === 'ADMIN' || req.user?.role === 'SUPER_ADMIN';
      const product = await ProductService.getProductById(
        id,
        req.user?.id,
        isAdmin,
      );
      res.status(200).json({
        success: true,
        data: product,
      });
    } catch (error) {
      if (error.message === 'Product not found') {
        return res.status(404).json({
          success: false,
          message: error.message,
        });
      }
      res.status(500).json({
        success: false,
        message: error.message,
      });
    }
  }

  /**
   * Update product
   * @param {Object} req - Express request object
   * @param {Object} res - Express response object
   */
  static async updateProduct(req, res) {
    try {
      const { id } = req.params;

      if (!mongoose.Types.ObjectId.isValid(id)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid product ID format',
        });
      }

      // Validate request
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({ errors: errors.array() });
      }

      const product = await ProductService.updateProduct(
        id,
        req.body,
        req.user.id,
      );
      res.status(200).json({
        success: true,
        message: 'Product updated successfully',
        data: product,
      });
    } catch (error) {
      if (
        error.message === 'Product not found' ||
        error.message === 'Category not found'
      ) {
        return res.status(404).json({
          success: false,
          message: error.message,
        });
      }
      res.status(500).json({
        success: false,
        message: error.message,
      });
    }
  }

  /**
   * Delete product
   * @param {Object} req - Express request object
   * @param {Object} res - Express response object
   */
  static async deleteProduct(req, res) {
    try {
      const { id } = req.params;

      if (!mongoose.Types.ObjectId.isValid(id)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid product ID format',
        });
      }

      await ProductService.deleteProduct(id);
      res.status(200).json({
        success: true,
        message: 'Product deleted successfully',
      });
    } catch (error) {
      if (error.message === 'Product not found') {
        return res.status(404).json({
          success: false,
          message: error.message,
        });
      }
      res.status(500).json({
        success: false,
        message: error.message,
      });
    }
  }

  /**
   * List products
   * @param {Object} req - Express request object
   * @param {Object} res - Express response object
   */
  static async listProducts(req, res) {
    try {
      let isAdmin =
        req.user?.role === 'ADMIN' || req.user?.role === 'SUPER_ADMIN';
      const { page = 1, limit = 10, ...filters } = req.query;
      const skip = (parseInt(page) - 1) * parseInt(limit);

      const { products, count } = await ProductService.listProducts(
        filters,
        parseInt(limit),
        parseInt(skip),
        req.user?.id,
        isAdmin,
      );

      return res.status(200).json({
        success: true,
        data: products,
        pagination: {
          total: count,
          page: parseInt(page),
          pages: Math.ceil(count / limit),
          limit: parseInt(limit),
        },
      });
    } catch (error) {
      console.log(error);
      return res.status(500).json({
        success: false,
        message: error.message,
      });
    }
  }

  /**
   * Get products by user ID
   * @param {Object} req - Express request object
   * @param {Object} res - Express response object
   */
  static async getProductsByUser(req, res) {
    try {
      const { userId } = req.params;

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      let isAdmin =
        req.user?.role === 'ADMIN' || req.user?.role === 'SUPER_ADMIN';
      const owner = req.user?.id;
      const { page = 1, limit = 10, ...filters } = req.query;
      const skip = (parseInt(page) - 1) * parseInt(limit);

      const { products, count } = await ProductService.getProductsByUser(
        userId,
        filters,
        parseInt(limit),
        parseInt(skip),
        isAdmin,
        owner,
      );

      return res.status(200).json({
        success: true,
        data: products,
        pagination: {
          total: count,
          page: parseInt(page),
          pages: Math.ceil(count / limit),
          limit: parseInt(limit),
        },
      });
    } catch (error) {
      return res.status(500).json({
        success: false,
        message: error.message,
      });
    }
  }

  /**
   * Get products by user ID for dashboard
   * @param {Object} req - Express request object
   * @param {Object} res - Express response object
   */
  static async getUserDashboardProducts(req, res) {
    try {
      const { userId } = req.params;
      const { page = 1, limit = 10, ...filters } = req.query;
      const skip = (parseInt(page) - 1) * parseInt(limit);

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      const user = await Account.findById(userId);
      if (!user) {
        return res
          .status(404)
          .json({ status: 'error', message: 'User not found' });
      }

      const { products, count } = await ProductService.userDashboardProduct(
        userId,
        filters,
        parseInt(limit),
        parseInt(skip),
      );

      res.status(200).json({
        success: true,
        data: products,
        pagination: {
          total: count,
          page: parseInt(page),
          pages: Math.ceil(count / limit),
          limit: parseInt(limit),
        },
      });
    } catch (error) {
      res.status(500).json({
        success: false,
        message: error.message,
      });
    }
  }

  /**
   * Toggle product status
   * @param {Object} req - Express request object
   * @param {Object} res - Express response object
   */
  static async toggleProductStatus(req, res) {
    try {
      const { id } = req.params;

      if (!mongoose.Types.ObjectId.isValid(id)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid product ID format',
        });
      }

      const product = await ProductService.toggleProductStatus(id);
      res.status(200).json({
        success: true,
        message: 'Product status updated successfully',
        data: product,
      });
    } catch (error) {
      if (error.message === 'Product not found') {
        return res.status(404).json({
          success: false,
          message: error.message,
        });
      }
      res.status(500).json({
        success: false,
        message: error.message,
      });
    }
  }

  /**
   * Get top products
   * @param {Object} req - Express request object
   * @param {Object} res - Express response object
   */
  static async getTopProducts(req, res) {
    try {
      const limit = req.query.limit || 10;
      const products = await ProductService.getTopProducts(parseInt(limit));

      res.status(200).json({
        success: true,
        data: products,
      });
    } catch (error) {
      res.status(500).json({
        success: false,
        message: error.message,
      });
    }
  }

  /**
   * Get products by category name
   * @param {Object} req - Express request object
   * @param {Object} res - Express response object
   */
  static async getProductsByCategory(req, res) {
    try {
      const isAdmin =
        req.user?.role === 'ADMIN' || req.user?.role === 'SUPER_ADMIN';
      const { page = 1, limit = 10, ...filters } = req.query;
      const skip = (parseInt(page) - 1) * parseInt(limit);
      const categoryName = req.params.categoryName;

      const { products, count } = await ProductService.getProductsByCategory(
        categoryName,
        filters,
        parseInt(limit),
        parseInt(skip),
        req.user?.id,
        isAdmin,
      );

      res.status(200).json({
        success: true,
        data: products,
        pagination: {
          total: count,
          page: parseInt(page),
          pages: Math.ceil(count / limit),
          limit: parseInt(limit),
        },
      });
    } catch (error) {
      res.status(500).json({
        success: false,
        message: error.message,
      });
    }
  }
}

module.exports = ProductController;
