'use strict';

const { Supplier, PurchaseOrder } = require('../models');
const { Op } = require('sequelize');
const { validationResult } = require('express-validator');

/**
 * Get all suppliers with pagination, filtering, and sorting
 * @route GET /api/suppliers
 */
exports.getAllSuppliers = async (req, res) => {
  try {
    const {
      page = 1,
      limit = 10,
      search = '',
      isActive,
      city,
      sortBy = 'createdAt',
      sortOrder = 'DESC'
    } = req.query;

    const offset = (page - 1) * limit;
    const whereClause = {};

    // Search filter
    if (search) {
      whereClause[Op.or] = [
        { name: { [Op.iLike]: `%${search}%` } },
        { contactPerson: { [Op.iLike]: `%${search}%` } },
        { email: { [Op.iLike]: `%${search}%` } },
        { phone: { [Op.iLike]: `%${search}%` } }
      ];
    }

    // Active status filter
    if (isActive !== undefined && isActive !== '') {
      whereClause.isActive = isActive === 'true';
    }

    // Location filters
    if (city) {
      whereClause.city = city;
    }

    const { count, rows } = await Supplier.findAndCountAll({
      where: whereClause,
      limit: parseInt(limit),
      offset: parseInt(offset),
      order: [[sortBy, sortOrder.toUpperCase()]],
      include: [{
        model: PurchaseOrder,
        as: 'purchaseOrders',
        attributes: ['id', 'orderNumber', 'totalAmount', 'status'],
        separate: true,
        limit: 5,
        order: [['createdAt', 'DESC']]
      }],
      distinct: true
    });

    console.log(`Fetched ${rows.length} suppliers out of ${count} total`);

    return res.status(200).json({
      success: true,
      data: {
        suppliers: rows,
        totalSuppliers: count,        // ✅ Match frontend expectation
        currentPage: parseInt(page),   // ✅ Match frontend expectation
        limit: parseInt(limit),        // ✅ Match frontend expectation
        totalPages: Math.ceil(count / limit)
      }
    });
  } catch (error) {
    console.error('Error fetching suppliers:', error);
    return res.status(500).json({
      success: false,
      message: 'Error fetching suppliers',
      error: error.message
    });
  }
};
/**
 * Get a single supplier by ID
 * @route GET /api/suppliers/:id
 */
exports.getSupplierById = async (req, res) => {
  try {
    const { id } = req.params;
    const { includePurchaseOrders = 'true' } = req.query;

    const includeOptions = [];
    if (includePurchaseOrders === 'true') {
      includeOptions.push({
        model: PurchaseOrder,
        as: 'purchaseOrders',
        order: [['createdAt', 'DESC']]
      });
    }

    const supplier = await Supplier.findByPk(id, {
      include: includeOptions
    });

    if (!supplier) {
      return res.status(404).json({
        success: false,
        message: 'Supplier not found'
      });
    }

    return res.status(200).json({
      success: true,
      data: supplier
    });
  } catch (error) {
    console.error('Error fetching supplier:', error);
    return res.status(500).json({
      success: false,
      message: 'Error fetching supplier',
      error: error.message
    });
  }
};

/**
 * Create a new supplier
 * @route POST /api/suppliers
 */
exports.createSupplier = async (req, res) => {
  try {
    // Validate request
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({
        success: false,
        message: 'Validation errors',
        errors: errors.array()
      });
    }

    const {
      name,
      contactPerson,
      email,
      phone,
      address,
      city,
      country,
      taxId,
      paymentTerms,
      isActive = true
    } = req.body;

    // Check for duplicate email
    if (email) {
      const existingSupplier = await Supplier.findOne({ where: { email } });
      if (existingSupplier) {
        return res.status(409).json({
          success: false,
          message: 'A supplier with this email already exists'
        });
      }
    }

    const supplier = await Supplier.create({
      name,
      contactPerson,
      email,
      phone,
      address,
      city,
      country,
      taxId,
      paymentTerms,
      isActive
    });

    return res.status(201).json({
      success: true,
      message: 'Supplier created successfully',
      data: supplier
    });
  } catch (error) {
    console.error('Error creating supplier:', error);
    return res.status(500).json({
      success: false,
      message: 'Error creating supplier',
      error: error.message
    });
  }
};

/**
 * Update a supplier
 * @route PUT /api/suppliers/:id
 */
exports.updateSupplier = async (req, res) => {
  try {
    const { id } = req.params;
    const errors = validationResult(req);
    
    if (!errors.isEmpty()) {
      return res.status(400).json({
        success: false,
        message: 'Validation errors',
        errors: errors.array()
      });
    }

    const supplier = await Supplier.findByPk(id);
    if (!supplier) {
      return res.status(404).json({
        success: false,
        message: 'Supplier not found'
      });
    }

    // Check for duplicate email if email is being updated
    if (req.body.email && req.body.email !== supplier.email) {
      const existingSupplier = await Supplier.findOne({
        where: {
          email: req.body.email,
          id: { [Op.ne]: id }
        }
      });
      if (existingSupplier) {
        return res.status(409).json({
          success: false,
          message: 'A supplier with this email already exists'
        });
      }
    }

    const {
      name,
      contactPerson,
      email,
      phone,
      address,
      city,
      country,
      taxId,
      paymentTerms,
      isActive
    } = req.body;

    await supplier.update({
      name,
      contactPerson,
      email,
      phone,
      address,
      city,
      country,
      taxId,
      paymentTerms,
      isActive
    });

    return res.status(200).json({
      success: true,
      message: 'Supplier updated successfully',
      data: supplier
    });
  } catch (error) {
    console.error('Error updating supplier:', error);
    return res.status(500).json({
      success: false,
      message: 'Error updating supplier',
      error: error.message
    });
  }
};

/**
 * Soft delete supplier (deactivate)
 * @route DELETE /api/suppliers/:id
 */
exports.deleteSupplier = async (req, res) => {
  try {
    const { id } = req.params;
    const { permanent = 'false' } = req.query;

    const supplier = await Supplier.findByPk(id);
    if (!supplier) {
      return res.status(404).json({
        success: false,
        message: 'Supplier not found'
      });
    }

    // Check if supplier has associated purchase orders
    const purchaseOrderCount = await PurchaseOrder.count({
      where: { supplierId: id }
    });

    if (purchaseOrderCount > 0 && permanent === 'true') {
      return res.status(400).json({
        success: false,
        message: 'Cannot permanently delete supplier with existing purchase orders. Deactivate instead.',
        purchaseOrderCount
      });
    }

    if (permanent === 'true' && purchaseOrderCount === 0) {
      await supplier.destroy();
      return res.status(200).json({
        success: true,
        message: 'Supplier permanently deleted'
      });
    } else {
      // Soft delete - just deactivate
      await supplier.update({ isActive: false });
      return res.status(200).json({
        success: true,
        message: 'Supplier deactivated successfully',
        data: supplier
      });
    }
  } catch (error) {
    console.error('Error deleting supplier:', error);
    return res.status(500).json({
      success: false,
      message: 'Error deleting supplier',
      error: error.message
    });
  }
};

/**
 * Activate/Reactivate a supplier
 * @route PATCH /api/suppliers/:id/activate
 */
exports.activateSupplier = async (req, res) => {
  try {
    const { id } = req.params;

    const supplier = await Supplier.findByPk(id);
    if (!supplier) {
      return res.status(404).json({
        success: false,
        message: 'Supplier not found'
      });
    }

    await supplier.update({ isActive: true });

    return res.status(200).json({
      success: true,
      message: 'Supplier activated successfully',
      data: supplier
    });
  } catch (error) {
    console.error('Error activating supplier:', error);
    return res.status(500).json({
      success: false,
      message: 'Error activating supplier',
      error: error.message
    });
  }
};

/**
 * Get supplier statistics
 * @route GET /api/suppliers/:id/statistics
 */
exports.getSupplierStatistics = async (req, res) => {
  try {
    const { id } = req.params;

    const supplier = await Supplier.findByPk(id);
    if (!supplier) {
      return res.status(404).json({
        success: false,
        message: 'Supplier not found'
      });
    }

    const purchaseOrders = await PurchaseOrder.findAll({
      where: { supplierId: id },
      attributes: ['totalAmount', 'status', 'createdAt']
    });

    const statistics = {
      totalOrders: purchaseOrders.length,
      totalSpent: purchaseOrders.reduce((sum, po) => sum + parseFloat(po.totalAmount || 0), 0),
      ordersByStatus: {
        pending: purchaseOrders.filter(po => po.status === 'pending').length,
        approved: purchaseOrders.filter(po => po.status === 'approved').length,
        completed: purchaseOrders.filter(po => po.status === 'completed').length,
        cancelled: purchaseOrders.filter(po => po.status === 'cancelled').length
      },
      averageOrderValue: purchaseOrders.length > 0 
        ? purchaseOrders.reduce((sum, po) => sum + parseFloat(po.totalAmount || 0), 0) / purchaseOrders.length 
        : 0,
      lastOrderDate: purchaseOrders.length > 0 
        ? purchaseOrders.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))[0].createdAt 
        : null
    };

    return res.status(200).json({
      success: true,
      data: {
        supplier: {
          id: supplier.id,
          name: supplier.name
        },
        statistics
      }
    });
  } catch (error) {
    console.error('Error fetching supplier statistics:', error);
    return res.status(500).json({
      success: false,
      message: 'Error fetching supplier statistics',
      error: error.message
    });
  }
};

/**
 * Bulk operations on suppliers
 * @route POST /api/suppliers/bulk
 */
exports.bulkOperation = async (req, res) => {
  try {
    const { operation, supplierIds } = req.body;

    if (!operation || !supplierIds || !Array.isArray(supplierIds)) {
      return res.status(400).json({
        success: false,
        message: 'Invalid request. Provide operation and supplierIds array'
      });
    }

    let result;
    switch (operation) {
      case 'activate':
        result = await Supplier.update(
          { isActive: true },
          { where: { id: { [Op.in]: supplierIds } } }
        );
        break;
      case 'deactivate':
        result = await Supplier.update(
          { isActive: false },
          { where: { id: { [Op.in]: supplierIds } } }
        );
        break;
      case 'delete':
        // Only delete suppliers without purchase orders
        const suppliersWithOrders = await PurchaseOrder.findAll({
          where: { supplierId: { [Op.in]: supplierIds } },
          attributes: ['supplierId'],
          group: ['supplierId']
        });
        const supplierIdsWithOrders = suppliersWithOrders.map(po => po.supplierId);
        const safeToDelete = supplierIds.filter(id => !supplierIdsWithOrders.includes(id));
        
        result = await Supplier.destroy({
          where: { id: { [Op.in]: safeToDelete } }
        });
        break;
      default:
        return res.status(400).json({
          success: false,
          message: 'Invalid operation. Use: activate, deactivate, or delete'
        });
    }

    return res.status(200).json({
      success: true,
      message: `Bulk ${operation} completed`,
      affectedRecords: result[0] || result
    });
  } catch (error) {
    console.error('Error in bulk operation:', error);
    return res.status(500).json({
      success: false,
      message: 'Error performing bulk operation',
      error: error.message
    });
  }
};

/**
 * Export suppliers to CSV/JSON
 * @route GET /api/suppliers/export
 */
exports.exportSuppliers = async (req, res) => {
  try {
    const { format = 'json', isActive } = req.query;
    const whereClause = {};

    if (isActive !== undefined) {
      whereClause.isActive = isActive === 'true';
    }

    const suppliers = await Supplier.findAll({
      where: whereClause,
      order: [['name', 'ASC']]
    });

    if (format === 'csv') {
      const csvData = convertToCSV(suppliers);
      res.setHeader('Content-Type', 'text/csv');
      res.setHeader('Content-Disposition', 'attachment; filename=suppliers.csv');
      return res.status(200).send(csvData);
    }

    res.setHeader('Content-Type', 'application/json');
    res.setHeader('Content-Disposition', 'attachment; filename=suppliers.json');
    return res.status(200).json({
      success: true,
      exportDate: new Date().toISOString(),
      count: suppliers.length,
      data: suppliers
    });
  } catch (error) {
    console.error('Error exporting suppliers:', error);
    return res.status(500).json({
      success: false,
      message: 'Error exporting suppliers',
      error: error.message
    });
  }
};

/**
 * Helper function to convert data to CSV
 */
const convertToCSV = (data) => {
  if (data.length === 0) return '';

  const headers = Object.keys(data[0].toJSON());
  const csvRows = [headers.join(',')];

  for (const row of data) {
    const values = headers.map(header => {
      const value = row[header];
      return `"${value !== null && value !== undefined ? value.toString().replace(/"/g, '""') : ''}"`;
    });
    csvRows.push(values.join(','));
  }

  return csvRows.join('\n');
};