const db = require('../models');
const { sendResponse, sendError } = require('../utils/response');
const asyncHandler = require('../middlewares/asyncHandler');
const materialSubstitutionService = require('../services/materialSubstitutionService');

/**
 * Get substitution rules for a material
 * GET /api/v1/master/material-substitution/rules
 */
exports.getSubstitutionRules = asyncHandler(async (req, res) => {
  const { companyId, plantId, materialId, effectiveDate } = req.query;
  const userCompanyId = req.user?.companyId;

  if (!materialId) {
    return sendError(res, 'Material ID is required', 400);
  }

  const effectiveCompanyId = companyId || userCompanyId;
  if (!effectiveCompanyId || !plantId) {
    return sendError(res, 'Company ID and Plant ID are required', 400);
  }

  const rules = await materialSubstitutionService.getSubstitutionRules(
    effectiveCompanyId,
    plantId,
    materialId,
    effectiveDate ? new Date(effectiveDate) : null
  );

  sendResponse(res, 200, true, 'Substitution rules retrieved successfully', rules);
});

/**
 * Create substitution master rule
 * POST /api/v1/master/material-substitution
 */
exports.createSubstitutionMaster = asyncHandler(async (req, res) => {
  const substitutionData = req.body;
  const userId = req.user?.userId || null;

  const substitution = await db.MaterialSubstitutionMaster.create({
    ...substitutionData,
    created_by: userId,
    updated_by: userId
  });

  sendResponse(res, 201, true, 'Substitution rule created successfully', substitution);
});

/**
 * Get substitution master rules
 * GET /api/v1/master/material-substitution
 */
exports.getSubstitutionMasters = asyncHandler(async (req, res) => {
  const { companyId, plantId, originalMaterialId, substituteMaterialId, status } = req.query;
  const userCompanyId = req.user?.companyId;

  const effectiveCompanyId = companyId || userCompanyId;
  if (!effectiveCompanyId || !plantId) {
    return sendError(res, 'Company ID and Plant ID are required', 400);
  }

  const where = {
    company_id: effectiveCompanyId,
    plant_id: plantId
  };

  if (originalMaterialId) where.original_material_id = originalMaterialId;
  if (substituteMaterialId) where.substitute_material_id = substituteMaterialId;
  if (status) where.status = status;

  const rules = await db.MaterialSubstitutionMaster.findAll({
    where,
    include: [
      { model: db.Material, as: 'originalMaterial' },
      { model: db.Material, as: 'substituteMaterial' }
    ],
    order: [['original_material_id', 'ASC'], ['substitution_ratio', 'ASC']]
  });

  sendResponse(res, 200, true, 'Substitution rules retrieved successfully', rules);
});

/**
 * Substitute Production Order Component
 * POST /api/v1/production/substitute-component/:componentId
 */
exports.substituteProductionOrderComponent = asyncHandler(async (req, res) => {
  const { componentId } = req.params;
  const { substituteMaterialId, substitutionRatio, reason } = req.body;
  const userId = req.user?.userId || null;

  if (!substituteMaterialId) {
    return sendError(res, 'Substitute Material ID is required', 400);
  }

  const result = await materialSubstitutionService.substituteProductionOrderComponent(
    componentId,
    substituteMaterialId,
    substitutionRatio || null,
    reason || null,
    userId
  );

  sendResponse(res, 200, true, 'Component substituted successfully', result);
});

/**
 * Substitute Material Request Item
 * POST /api/v1/stores/substitute-item/:itemId
 */
exports.substituteMaterialRequestItem = asyncHandler(async (req, res) => {
  const { itemId } = req.params;
  const { substituteMaterialId, substitutionRatio, reason } = req.body;
  const userId = req.user?.userId || null;

  if (!substituteMaterialId) {
    return sendError(res, 'Substitute Material ID is required', 400);
  }

  const result = await materialSubstitutionService.substituteMaterialRequestItem(
    itemId,
    substituteMaterialId,
    substitutionRatio || null,
    reason || null,
    userId
  );

  sendResponse(res, 200, true, 'Item substituted successfully', result);
});

/**
 * Approve/Reject substitution
 * POST /api/v1/master/material-substitution/:transactionId/approve
 */
exports.approveSubstitution = asyncHandler(async (req, res) => {
  const { transactionId } = req.params;
  const { action, remarks } = req.body;
  const userId = req.user?.userId || null;

  if (!action || !['APPROVE', 'REJECT'].includes(action.toUpperCase())) {
    return sendError(res, 'Action must be APPROVE or REJECT', 400);
  }

  const transaction = await materialSubstitutionService.approveSubstitution(
    transactionId,
    action.toUpperCase(),
    remarks || null,
    userId
  );

  sendResponse(res, 200, true, `Substitution ${action.toLowerCase()}d successfully`, transaction);
});

/**
 * Get substitution transactions
 * GET /api/v1/master/material-substitution/transactions
 */
exports.getSubstitutionTransactions = asyncHandler(async (req, res) => {
  const filters = req.query;
  const userCompanyId = req.user?.companyId;

  if (userCompanyId && !filters.companyId) {
    filters.companyId = userCompanyId;
  }

  const transactions = await materialSubstitutionService.getSubstitutionTransactions(filters);

  sendResponse(res, 200, true, 'Substitution transactions retrieved successfully', transactions);
});

