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

/**
 * Get BOM Report with hierarchical structure (main components and sub-components)
 * This function builds a tree structure where:
 * - Main components are direct children of BOM Header
 * - Sub-components are components that have their own BOM (recursive structure)
 */
exports.getBOMReport = asyncHandler(async (req, res) => {
  const { bomHeaderId, companyId, plantId, materialId } = req.query;
  const userId = req.user?.userId || null;

  const where = {};
  const bomHeaderWhere = {};

  // Filter by company
  const companyIdValue = companyId || req.user?.companyId;
  if (companyIdValue) {
    bomHeaderWhere.company_id = companyIdValue;
  }

  // Filter by plant
  if (plantId) {
    bomHeaderWhere.plant_id = plantId;
  }

  // Filter by BOM Header ID
  if (bomHeaderId) {
    bomHeaderWhere.id = bomHeaderId;
  }

  // Filter by material (main material in BOM Header)
  if (materialId) {
    bomHeaderWhere.material_id = materialId;
  }

  // Only active BOMs
  bomHeaderWhere.status = 'ACTIVE';

  // Fetch BOM Headers with their components
  const bomHeaders = await db.BOMHeader.findAll({
    where: bomHeaderWhere,
    include: [
      {
        model: db.Material,
        as: 'material',
        required: false,
        attributes: ['id', 'material_number', 'description', 'material_type', 'material_group'],
        include: [
          { model: db.MaterialType, as: 'materialType', required: false, attributes: ['id', 'type_code', 'type_name'] },
          { model: db.MaterialGroup, as: 'materialGroup', required: false, attributes: ['id', 'group_code', 'group_name'] },
        ],
      },
      {
        model: db.Company,
        as: 'company',
        required: false,
        attributes: ['id', 'code', 'name'],
      },
      {
        model: db.Plant,
        as: 'plant',
        required: false,
        attributes: ['id', 'code', 'name'],
      },
      {
        model: db.BOMComponent,
        as: 'components',
        where: { status: 'ACTIVE' },
        required: false,
        include: [
          {
            model: db.Material,
            as: 'material',
            attributes: ['id', 'material_number', 'description', 'material_type', 'material_group'],
            include: [
              { model: db.MaterialType, as: 'materialType', attributes: ['id', 'type_code', 'type_name'] },
              { model: db.MaterialGroup, as: 'materialGroup', attributes: ['id', 'group_code', 'group_name'] },
            ],
          },
          {
            model: db.UOM,
            as: 'componentUOM',
            attributes: ['id', 'uom_code', 'uom_name'],
          },
        ],
        order: [['item_number', 'ASC']],
      },
    ],
    order: [['bom_number', 'ASC']],
  });

  // Build hierarchical report structure
  const reportData = [];

  for (const bomHeader of bomHeaders) {
    const mainMaterial = bomHeader.material;
    const components = bomHeader.components || [];

    // Process main components (direct children of BOM Header)
    const mainComponents = [];
    const subComponentMap = new Map(); // Map to track sub-components

    for (const component of components) {
      const componentMaterial = component.material;
      
      // Check if this component material has its own BOM (making it a sub-component)
      const subBOM = await db.BOMHeader.findOne({
        where: {
          material_id: componentMaterial.id,
          company_id: bomHeader.company_id,
          status: 'ACTIVE',
        },
        include: [
          {
            model: db.BOMComponent,
            as: 'components',
            where: { status: 'ACTIVE' },
            required: false,
            include: [
              {
                model: db.Material,
                as: 'material',
                attributes: ['id', 'material_number', 'description', 'material_type', 'material_group'],
                include: [
                  { model: db.MaterialType, as: 'materialType', attributes: ['id', 'type_code', 'type_name'] },
                  { model: db.MaterialGroup, as: 'materialGroup', attributes: ['id', 'group_code', 'group_name'] },
                ],
              },
              {
                model: db.UOM,
                as: 'componentUOM',
                attributes: ['id', 'uom_code', 'uom_name'],
              },
            ],
            order: [['item_number', 'ASC']],
          },
        ],
      });

      const componentData = {
        id: component.id,
        item_number: component.item_number,
        material_id: component.material_id,
        material_number: componentMaterial?.material_number || '',
        material_description: componentMaterial?.description || '',
        material_type: componentMaterial?.materialType?.type_name || componentMaterial?.material_type || '',
        material_group: componentMaterial?.materialGroup?.group_name || componentMaterial?.material_group || '',
        quantity: parseFloat(component.quantity) || 0,
        uom_id: component.component_uom_id,
        uom_code: component.componentUOM?.uom_code || '',
        uom_name: component.componentUOM?.uom_name || '',
        scrap_percentage: parseFloat(component.scrap_percentage) || 0,
        operation_number: component.operation_number || null,
        status: component.status,
        is_sub_component: !!subBOM, // Flag to indicate if this is a sub-component
        sub_components: [], // Will be populated if subBOM exists
      };

      // If this component has its own BOM, fetch its sub-components
      if (subBOM && subBOM.components && subBOM.components.length > 0) {
        componentData.sub_components = subBOM.components.map((subComp) => ({
          id: subComp.id,
          item_number: subComp.item_number,
          material_id: subComp.material_id,
          material_number: subComp.material?.material_number || '',
          material_description: subComp.material?.description || '',
          material_type: subComp.material?.materialType?.type_name || subComp.material?.material_type || '',
          material_group: subComp.material?.materialGroup?.group_name || subComp.material?.material_group || '',
          quantity: parseFloat(subComp.quantity) || 0,
          uom_id: subComp.component_uom_id,
          uom_code: subComp.componentUOM?.uom_code || '',
          uom_name: subComp.componentUOM?.uom_name || '',
          scrap_percentage: parseFloat(subComp.scrap_percentage) || 0,
          operation_number: subComp.operation_number || null,
          status: subComp.status,
        }));
      }

      mainComponents.push(componentData);
    }

    reportData.push({
      bom_header_id: bomHeader.id,
      bom_number: bomHeader.bom_number,
      bom_type: bomHeader.bom_type,
      alternative: bomHeader.alternative,
      drawing_number: bomHeader.drawing_number,
      revision_number: bomHeader.revision_number,
      main_material_id: mainMaterial?.id || null,
      main_material_number: mainMaterial?.material_number || '',
      main_material_description: mainMaterial?.description || '',
      main_material_type: mainMaterial?.materialType?.type_name || mainMaterial?.material_type || '',
      main_material_group: mainMaterial?.materialGroup?.group_name || mainMaterial?.material_group || '',
      company_id: bomHeader.company_id,
      company_code: bomHeader.company?.code || '',
      company_name: bomHeader.company?.name || '',
      plant_id: bomHeader.plant_id,
      plant_code: bomHeader.plant?.code || '',
      plant_name: bomHeader.plant?.name || '',
      main_components: mainComponents,
      total_main_components: mainComponents.length,
      total_sub_components: mainComponents.reduce((sum, comp) => sum + (comp.sub_components?.length || 0), 0),
    });
  }

  sendResponse(res, 200, true, 'BOM Report retrieved successfully', {
    report_data: reportData,
    total_boms: reportData.length,
  });
});

