const express = require('express');
const { v4: uuidv4 } = require('uuid');
const router = express.Router();

module.exports = (pool, query, authMiddleware) => {
  // Apply authentication middleware to all routes
  router.use(authMiddleware);
  
  // Create a new product with multiple images
  router.post('/', async (req, res, next) => {
    try {
      const {
        name,
        description,
        categoryName,
        price,
        stockQuantity,
        weightGrams,
        lengthCm,
        widthCm,
        heightCm,
        origin,
        age,
        materialType,
        color,
        images,
        tags
      } = req.body;
      
      // Validate required fields
      if (!name || !description || !categoryName || !price || !stockQuantity) {
        return res.status(400).json({
          error: true,
          message: 'Required fields missing: name, description, categoryName, price, and stockQuantity are mandatory'
        });
      }
      
      // Begin transaction
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Get category ID by name
        const categoryResult = await client.query(
          'SELECT id FROM product_categories WHERE name = $1',
          [categoryName]
        );
        
        if (categoryResult.rows.length === 0) {
          return res.status(404).json({
            error: true,
            message: `Category "${categoryName}" not found`
          });
        }
        
        const categoryId = categoryResult.rows[0].id;
        
        // Create product
        const productId = uuidv4();
        await client.query(
          `INSERT INTO products (
            id, name, description, category_id, price, stock_quantity,
            weight_grams, length_cm, width_cm, height_cm,
            origin, age, material_type, color
          ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)`,
          [
            productId, name, description, categoryId, price, stockQuantity,
            weightGrams || null, lengthCm || null, widthCm || null, heightCm || null,
            origin || null, age || null, materialType || null, color || null
          ]
        );
        
        // Add images if provided
        if (images && images.length > 0) {
          for (let i = 0; i < images.length; i++) {
            const { path, isPrimary = (i === 0) } = images[i];
            
            await client.query(
              'INSERT INTO product_images (product_id, image_path, display_order, is_primary) VALUES ($1, $2, $3, $4)',
              [productId, path, i, isPrimary]
            );
          }
        }
        
        // Add tags if provided
        if (tags && tags.length > 0) {
          for (const tagName of tags) {
            // Get tag ID
            let tagResult = await client.query(
              'SELECT id FROM tags WHERE name = $1',
              [tagName]
            );
            
            let tagId;
            
            // If tag doesn't exist, create it
            if (tagResult.rows.length === 0) {
              const newTagResult = await client.query(
                'INSERT INTO tags (name) VALUES ($1) RETURNING id',
                [tagName]
              );
              tagId = newTagResult.rows[0].id;
            } else {
              tagId = tagResult.rows[0].id;
            }
            
            // Add tag to product
            await client.query(
              'INSERT INTO product_tags (product_id, tag_id) VALUES ($1, $2)',
              [productId, tagId]
            );
          }
        }
        
        await client.query('COMMIT');
        
        // Get complete product with images and tags
        const productQuery = `
          SELECT p.*, 
                 pc.name as category_name,
                 ARRAY_AGG(DISTINCT t.name) FILTER (WHERE t.name IS NOT NULL) AS tags,
                 json_agg(json_build_object(
                   'id', pi.id,
                   'path', pi.image_path,
                   'isPrimary', pi.is_primary,
                   'displayOrder', pi.display_order
                 )) FILTER (WHERE pi.id IS NOT NULL) AS images
          FROM products p
          JOIN product_categories pc ON p.category_id = pc.id
          LEFT JOIN product_tags pt ON p.id = pt.product_id
          LEFT JOIN tags t ON pt.tag_id = t.id
          LEFT JOIN product_images pi ON p.id = pi.product_id
          WHERE p.id = $1
          GROUP BY p.id, pc.name
        `;
        
        const product = await query(productQuery, [productId]);
        
        res.status(201).json({
          message: 'Product created successfully',
          product: product.rows[0]
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      next(error);
    }
  });

  router.post('/:id/stock-notification', async (req, res, next) => {
    try {
      const { id } = req.params;
      const { enabled, email, threshold } = req.body;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Check if product exists
      const productCheck = await query(
        'SELECT * FROM products WHERE id = $1',
        [id]
      );
      
      if (productCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Product not found'
        });
      }
      
      // Store notification settings as JSONB
      const notificationSettings = {
        enabled,
        email: email || null,
        threshold: threshold || 0
      };
      
      // Update product with notification settings
      const result = await query(
        `UPDATE products 
         SET stock_notification = $1
         WHERE id = $2
         RETURNING *`,
        [JSON.stringify(notificationSettings), id]
      );
      
      res.json({
        message: 'Stock notification settings updated successfully',
        product: result.rows[0]
      });
    } catch (error) {
      next(error);
    }
  });
  
  // Update an existing product
  router.put('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      const {
        name,
        description,
        categoryName,
        price,
        stockQuantity,
        weightGrams,
        lengthCm,
        widthCm,
        heightCm,
        origin,
        age,
        materialType,
        color,
        images,
        tags
      } = req.body;
      
      // Begin transaction
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Check if product exists
        const productCheck = await client.query(
          'SELECT * FROM products WHERE id = $1',
          [id]
        );
        
        if (productCheck.rows.length === 0) {
          return res.status(404).json({
            error: true,
            message: 'Product not found'
          });
        }
        
        // If category is changing, get the new category ID
        let categoryId = productCheck.rows[0].category_id;
        if (categoryName) {
          const categoryResult = await client.query(
            'SELECT id FROM product_categories WHERE name = $1',
            [categoryName]
          );
          
          if (categoryResult.rows.length === 0) {
            return res.status(404).json({
              error: true,
              message: `Category "${categoryName}" not found`
            });
          }
          
          categoryId = categoryResult.rows[0].id;
        }
        
        // Update product
        const updateFields = [];
        const updateValues = [];
        let valueIndex = 1;
        
        if (name) {
          updateFields.push(`name = $${valueIndex}`);
          updateValues.push(name);
          valueIndex++;
        }
        
        if (description) {
          updateFields.push(`description = $${valueIndex}`);
          updateValues.push(description);
          valueIndex++;
        }
        
        if (categoryName) {
          updateFields.push(`category_id = $${valueIndex}`);
          updateValues.push(categoryId);
          valueIndex++;
        }
        
        if (price) {
          updateFields.push(`price = $${valueIndex}`);
          updateValues.push(price);
          valueIndex++;
        }
        
        if (stockQuantity !== undefined) {
          updateFields.push(`stock_quantity = $${valueIndex}`);
          updateValues.push(stockQuantity);
          valueIndex++;
        }
        
        if (weightGrams !== undefined) {
          updateFields.push(`weight_grams = $${valueIndex}`);
          updateValues.push(weightGrams);
          valueIndex++;
        }
        
        if (lengthCm !== undefined) {
          updateFields.push(`length_cm = $${valueIndex}`);
          updateValues.push(lengthCm);
          valueIndex++;
        }
        
        if (widthCm !== undefined) {
          updateFields.push(`width_cm = $${valueIndex}`);
          updateValues.push(widthCm);
          valueIndex++;
        }
        
        if (heightCm !== undefined) {
          updateFields.push(`height_cm = $${valueIndex}`);
          updateValues.push(heightCm);
          valueIndex++;
        }
        
        if (origin !== undefined) {
          updateFields.push(`origin = $${valueIndex}`);
          updateValues.push(origin);
          valueIndex++;
        }
        
        if (age !== undefined) {
          updateFields.push(`age = $${valueIndex}`);
          updateValues.push(age);
          valueIndex++;
        }
        
        if (materialType !== undefined) {
          updateFields.push(`material_type = $${valueIndex}`);
          updateValues.push(materialType);
          valueIndex++;
        }
        
        if (color !== undefined) {
          updateFields.push(`color = $${valueIndex}`);
          updateValues.push(color);
          valueIndex++;
        }
        
        if (updateFields.length > 0) {
          const updateQuery = `
            UPDATE products 
            SET ${updateFields.join(', ')}
            WHERE id = $${valueIndex}
          `;
          
          updateValues.push(id);
          
          await client.query(updateQuery, updateValues);
        }
        
        // Update images if provided
        if (images) {
          // Remove existing images
          await client.query(
            'DELETE FROM product_images WHERE product_id = $1',
            [id]
          );
          
          // Add new images
          for (let i = 0; i < images.length; i++) {
            const { path, isPrimary = (i === 0) } = images[i];
            
            await client.query(
              'INSERT INTO product_images (product_id, image_path, display_order, is_primary) VALUES ($1, $2, $3, $4)',
              [id, path, i, isPrimary]
            );
          }
        }
        
        // Update tags if provided
        if (tags) {
          // Remove existing tags
          await client.query(
            'DELETE FROM product_tags WHERE product_id = $1',
            [id]
          );
          
          // Add new tags
          for (const tagName of tags) {
            // Get tag ID
            let tagResult = await client.query(
              'SELECT id FROM tags WHERE name = $1',
              [tagName]
            );
            
            let tagId;
            
            // If tag doesn't exist, create it
            if (tagResult.rows.length === 0) {
              const newTagResult = await client.query(
                'INSERT INTO tags (name) VALUES ($1) RETURNING id',
                [tagName]
              );
              tagId = newTagResult.rows[0].id;
            } else {
              tagId = tagResult.rows[0].id;
            }
            
            // Add tag to product
            await client.query(
              'INSERT INTO product_tags (product_id, tag_id) VALUES ($1, $2)',
              [id, tagId]
            );
          }
        }
        
        await client.query('COMMIT');
        
        // Get updated product
        const productQuery = `
          SELECT p.*, 
                 pc.name as category_name,
                 ARRAY_AGG(DISTINCT t.name) FILTER (WHERE t.name IS NOT NULL) AS tags,
                 json_agg(json_build_object(
                   'id', pi.id,
                   'path', pi.image_path,
                   'isPrimary', pi.is_primary,
                   'displayOrder', pi.display_order
                 )) FILTER (WHERE pi.id IS NOT NULL) AS images
          FROM products p
          JOIN product_categories pc ON p.category_id = pc.id
          LEFT JOIN product_tags pt ON p.id = pt.product_id
          LEFT JOIN tags t ON pt.tag_id = t.id
          LEFT JOIN product_images pi ON p.id = pi.product_id
          WHERE p.id = $1
          GROUP BY p.id, pc.name
        `;
        
        const product = await query(productQuery, [id]);
        
        res.json({
          message: 'Product updated successfully',
          product: product.rows[0]
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      next(error);
    }
  });
  
  // Delete a product
  router.delete('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      
      // Check if product exists
      const productCheck = await query(
        'SELECT * FROM products WHERE id = $1',
        [id]
      );
      
      if (productCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Product not found'
        });
      }
      
      // Delete product (cascade will handle related records)
      await query(
        'DELETE FROM products WHERE id = $1',
        [id]
      );
      
      res.json({
        message: 'Product deleted successfully'
      });
    } catch (error) {
      next(error);
    }
  });
  
  return router;
};