const db = require('../models');
const { sendResponse, sendError } = require('../utils/response');
const asyncHandler = require('../middlewares/asyncHandler');
const { getPagination, getPagingData } = require('../utils/pagination');
const { Op } = require('sequelize');

/**
 * Material Master Report
 * Returns materials with related master references (type/group/UOM) and optional plant-specific MRP fields.
 *
 * Query params:
 * - companyId (optional; defaults to user company for non-superadmin)
 * - plantId (optional; includes MaterialPlant for that plant)
 * - status (optional; ACTIVE/INACTIVE/BLOCKED)
 * - materialTypeId (optional)
 * - materialGroupId (optional)
 * - search (optional; material number/description)
 * - page, limit (optional; default 1/20)
 * - export=true (optional; returns up to 50000 rows, page ignored)
 */
exports.getMaterialMasterReport = asyncHandler(async (req, res) => {
  try {
    const {
      page = 1,
      limit = 20,
      export: exportFlag,
      search,
      status,
      companyId,
      company_id,
      plantId,
      plant_id,
      materialTypeId,
      material_type_id,
      materialGroupId,
      material_group_id,
    } = req.query;

    const isExport = exportFlag === 'true' || exportFlag === true || exportFlag === 1 || exportFlag === '1';

    const effectiveLimit = isExport ? 50000 : parseInt(limit, 10) || 20;
    const effectivePage = isExport ? 1 : parseInt(page, 10) || 1;
    const { limit: limitNum, offset } = getPagination(effectivePage, effectiveLimit);

    const where = {};

    // Company filter: mimic masterController behavior
    const companyIdValue = companyId || company_id;
    const isSuperAdmin = req.user && (req.user.isSuperAdmin || req.user.is_super_admin);
    if (!isSuperAdmin) {
      // Non-super admin users default to their company
      if (req.user?.companyId) {
        where.company_id = req.user.companyId;
      } else if (companyIdValue) {
        where.company_id = parseInt(companyIdValue, 10);
      }
    } else if (companyIdValue && companyIdValue !== 'null' && companyIdValue !== 'undefined' && companyIdValue !== '') {
      const companyIdNum = parseInt(companyIdValue, 10);
      if (!isNaN(companyIdNum)) where.company_id = companyIdNum;
    }

    // Status filter (Material has status enum)
    if (status && status !== 'ALL') {
      where.status = status;
    } else {
      where.status = { [Op.ne]: 'DELETED' };
    }

    const typeId = materialTypeId || material_type_id;
    if (typeId && typeId !== 'null' && typeId !== 'undefined' && typeId !== '') {
      where.material_type_id = parseInt(typeId, 10);
    }

    const groupId = materialGroupId || material_group_id;
    if (groupId && groupId !== 'null' && groupId !== 'undefined' && groupId !== '') {
      where.material_group_id = parseInt(groupId, 10);
    }

    if (search && String(search).trim()) {
      const q = String(search).trim();
      where[Op.or] = [
        { material_number: { [Op.like]: `%${q}%` } },
        { description: { [Op.like]: `%${q}%` } },
        { hsn_code: { [Op.like]: `%${q}%` } },
      ];
    }

    const plantIdValue = plantId || plant_id;
    const include = [
      { model: db.Company, as: 'company', attributes: ['id', 'code', 'name'], required: false },
      { model: db.MaterialType, as: 'materialType', attributes: ['id', 'type_code', 'type_name'], required: false },
      { model: db.MaterialGroup, as: 'materialGroup', attributes: ['id', 'group_code', 'group_name'], required: false },
      { model: db.UOM, as: 'baseUOM', attributes: ['id', 'uom_code', 'uom_name'], required: false },
    ];

    if (plantIdValue && plantIdValue !== 'null' && plantIdValue !== 'undefined' && plantIdValue !== '') {
      include.push({
        model: db.MaterialPlant,
        as: 'materialPlants',
        required: false,
        where: { plant_id: parseInt(plantIdValue, 10) },
        attributes: [
          'id',
          'plant_id',
          'storage_location',
          'mrp_type',
          'mrp_controller',
          'reorder_point',
          'safety_stock',
          'max_stock',
          'procurement_type',
          'opening_balance',
          'opening_balance_date',
          'opening_balance_unit_cost',
          'status',
        ],
        include: [
          { model: db.Plant, as: 'plant', attributes: ['id', 'code', 'name'], required: false },
        ],
      });
    }

    const records = await db.Material.findAndCountAll({
      where,
      include,
      order: [['material_number', 'ASC']],
      limit: limitNum,
      offset,
    });

    const items = (records.rows || []).map((r) => {
      const row = r?.toJSON ? r.toJSON() : r;
      if (!row) return row;
      const typeName = row.materialType?.type_name ?? row.materialType?.type_code ?? row.material_type ?? '';
      const groupName = row.materialGroup?.group_name ?? row.materialGroup?.group_code ?? row.material_group ?? '';
      return {
        ...row,
        company_name: row.company?.name ?? row.company?.code ?? '',
        type_name: typeName,
        group_name: groupName,
        base_uom_code: row.baseUOM?.uom_code ?? row.baseUOM?.uom_name ?? '',
      };
    });
    const response = getPagingData({ count: records.count || 0, rows: items }, effectivePage, limitNum);

    sendResponse(res, 200, true, 'Material Master Report generated successfully', response);
  } catch (error) {
    console.error('Material Master Report error:', error);
    return sendError(res, error.message || 'Failed to generate Material Master Report', 500);
  }
});

