const express = require('express');
const router = express.Router();
const db = require('../models');
const createMasterController = require('../controllers/masterController');
const { authenticate } = require('../middlewares/auth');
const { bulkImportMaterials } = require('../controllers/materialController');
const bomHeaderController = require('../controllers/bomHeaderController');
const bomComponentController = require('../controllers/bomComponentController');
const routingController = require('../controllers/routingController');
const materialDrawingController = require('../controllers/materialDrawingController');
const materialSubstitutionController = require('../controllers/materialSubstitutionController');

// Business Partner specific routes - must be defined BEFORE generic routes to avoid route conflicts
const businessPartnerController = require('../controllers/businessPartnerController');
const approvedSuppliersReportController = require('../controllers/approvedSuppliersReportController');
const supplierRegistrationPDFController = require('../controllers/supplierRegistrationPDFController');
router.get('/businesspartner/approved-suppliers', authenticate, businessPartnerController.getApprovedSuppliers);
router.get('/businesspartner/approved-suppliers/pdf', authenticate, approvedSuppliersReportController.generatePDF);
router.get('/businesspartner/:id/print/pdf', authenticate, supplierRegistrationPDFController.generatePDF);

const masterModels = {
  company: { Model: db.Company, name: 'Company' },
  companybankdetail: { Model: db.CompanyBankDetail, name: 'CompanyBankDetail' },
  plant: { Model: db.Plant, name: 'Plant' },
  gstin: { Model: db.GSTIN, name: 'GSTIN' },
  businesspartner: { Model: db.BusinessPartner, name: 'BusinessPartner' },
  bpaddress: { Model: db.BPAddress, name: 'BPAddress' },
  bpbank: { Model: db.BPBank, name: 'BPBank' },
  bpgstin: { Model: db.BPGSTIN, name: 'BPGSTIN' },
  material: { Model: db.Material, name: 'Material' },
  materialtype: { Model: db.MaterialType, name: 'MaterialType' },
  materialgroup: { Model: db.MaterialGroup, name: 'MaterialGroup' },
  materialthickness: { Model: db.MaterialThickness, name: 'MaterialThickness' },
  materialgrade: { Model: db.MaterialGrade, name: 'MaterialGrade' },
  materialsheettype: { Model: db.MaterialSheetType, name: 'MaterialSheetType' },
  materialplant: { Model: db.MaterialPlant, name: 'MaterialPlant' },
  materialvaluation: { Model: db.MaterialValuation, name: 'MaterialValuation' },
  materialsupplier: { Model: db.MaterialSupplier, name: 'MaterialSupplier' },
  bomheader: { Model: db.BOMHeader, name: 'BOMHeader' },
  bomcomponent: { Model: db.BOMComponent, name: 'BOMComponent' },
  routing: { Model: db.Routing, name: 'Routing' },
  routingoperation: { Model: db.RoutingOperation, name: 'RoutingOperation' },
  operationname: { Model: db.OperationName, name: 'OperationName' },
  operationcode: { Model: db.OperationCode, name: 'OperationCode' },
  workcenter: { Model: db.WorkCenter, name: 'WorkCenter' },
  productionoperator: { Model: db.ProductionOperator, name: 'ProductionOperator' },
  glaccount: { Model: db.GLAccount, name: 'GLAccount' },
  costcenter: { Model: db.CostCenter, name: 'CostCenter' },
  currency: { Model: db.Currency, name: 'Currency' },
  currencyrate: { Model: db.CurrencyRate, name: 'CurrencyRate' },
  fiscalyear: { Model: db.FiscalYear, name: 'FiscalYear' },
  fiscalperiod: { Model: db.FiscalPeriod, name: 'FiscalPeriod' },
  taxmaster: { Model: db.TaxMaster, name: 'TaxMaster' },
  tdsmaster: { Model: db.TDSMaster, name: 'TDSMaster' },
  vendorcategory: { Model: db.VendorCategory, name: 'VendorCategory' },
  numberformat: { Model: db.NumberFormat, name: 'NumberFormat' },
  department: { Model: db.Department, name: 'Department' },
  designation: { Model: db.Designation, name: 'Designation' },
  employee: { Model: db.Employee, name: 'Employee' },
  user: { Model: db.User, name: 'User' },
  role: { Model: db.Role, name: 'Role' },
  permission: { Model: db.Permission, name: 'Permission' },
  userrole: { Model: db.UserRole, name: 'UserRole' },
  rolepermission: { Model: db.RolePermission, name: 'RolePermission' },
  uom: { Model: db.UOM, name: 'UOM' },
  uomconversion: { Model: db.UOMConversion, name: 'UOMConversion' },
  country: { Model: db.Country, name: 'Country' },
  state: { Model: db.State, name: 'State' },
  city: { Model: db.City, name: 'City' },
  bank: { Model: db.Bank, name: 'Bank' },
  storagelocation: { Model: db.StorageLocation, name: 'StorageLocation' },
  notificationsetting: { Model: db.NotificationSetting, name: 'NotificationSetting' },
  printheader: { Model: db.PrintHeader, name: 'PrintHeader' },
  document: { Model: db.Document, name: 'Document' },
  machine: { Model: db.Machine, name: 'Machine' },
  paymentmode: { Model: db.PaymentMode, name: 'PaymentMode' },
  scrapreasonmaster: { Model: db.ScrapReasonMaster, name: 'ScrapReasonMaster' },
  materialsubstitutionmaster: { Model: db.MaterialSubstitutionMaster, name: 'MaterialSubstitutionMaster' },
  fabricator: { Model: db.Fabricator, name: 'Fabricator' },
};

Object.keys(masterModels).forEach((route) => {
  const { Model, name } = masterModels[route];
  
  // Skip if Model is not available
  if (!Model) {
    console.error(`ERROR: Model for route '${route}' is not available. Model name: ${name}. Skipping route registration.`);
    console.error(`Available models in db:`, Object.keys(db).filter(key => key.includes('Material')));
    return;
  }
  
  // Use custom controller for bomheader, bomcomponent and routing, generic for others
  if (route === 'bomheader') {
    router.get(`/${route}`, authenticate, bomHeaderController.getAll);
    router.get(`/${route}/:id/pdf`, authenticate, bomHeaderController.generatePDF);
    router.get(`/${route}/:id`, authenticate, bomHeaderController.getById);
    router.post(`/${route}`, authenticate, bomHeaderController.create);
    router.put(`/${route}/:id`, authenticate, bomHeaderController.update);
    router.delete(`/${route}/:id`, authenticate, bomHeaderController.delete);
  } else if (route === 'bomcomponent') {
    router.get(`/${route}`, authenticate, bomComponentController.getAll);
    router.get(`/${route}/:id`, authenticate, bomComponentController.getById);
    router.post(`/${route}`, authenticate, bomComponentController.create);
    router.put(`/${route}/:id`, authenticate, bomComponentController.update);
    router.delete(`/${route}/:id`, authenticate, bomComponentController.delete);
  } else if (route === 'routing') {
    router.get(`/${route}`, authenticate, routingController.getAll);
    router.get(`/${route}/:id`, authenticate, routingController.getById);
    router.post(`/${route}`, authenticate, routingController.create);
    router.put(`/${route}/:id`, authenticate, routingController.update);
    router.delete(`/${route}/:id`, authenticate, routingController.delete);
  } else if (route === 'printheader') {
    // Use custom controller for printheader to handle hard delete
    const printHeaderController = require('../controllers/printHeaderController');
    router.get(`/${route}`, authenticate, createMasterController(Model, name).getAll);
    router.get(`/${route}/:id`, authenticate, createMasterController(Model, name).getById);
    router.post(`/${route}`, authenticate, createMasterController(Model, name).create);
    router.put(`/${route}/:id`, authenticate, createMasterController(Model, name).update);
    router.delete(`/${route}/:id`, authenticate, printHeaderController.delete);
  } else if (route === 'document') {
    // Use custom controller for document to handle file uploads
    const documentController = require('../controllers/documentController');
    const { uploadDocumentFile } = require('../middlewares/uploadMiddleware');
    router.get(`/${route}`, authenticate, documentController.getAll);
    router.get(`/${route}/:id`, authenticate, documentController.getById);
    router.post(`/${route}`, authenticate, uploadDocumentFile, documentController.create);
    router.put(`/${route}/:id`, authenticate, uploadDocumentFile, documentController.update);
    router.delete(`/${route}/:id`, authenticate, documentController.delete);
    router.post(`/${route}/:id/upload`, authenticate, documentController.uploadFile);
    router.delete(`/${route}/:id/file`, authenticate, documentController.deleteFile);
  } else if (route === 'materialplant') {
    // Use custom controller for materialplant to handle opening balance
    const materialPlantController = require('../controllers/materialPlantController');
    router.get(`/${route}`, authenticate, materialPlantController.getAll);
    router.get(`/${route}/:id`, authenticate, materialPlantController.getById);
    router.post(`/${route}`, authenticate, materialPlantController.create);
    router.put(`/${route}/:id`, authenticate, materialPlantController.update);
    router.delete(`/${route}/:id`, authenticate, materialPlantController.delete);
  } else {
    const controller = createMasterController(Model, name);
    router.get(`/${route}`, authenticate, controller.getAll);
    router.get(`/${route}/:id`, authenticate, controller.getById);
    router.post(`/${route}`, authenticate, controller.create);
    router.put(`/${route}/:id`, authenticate, controller.update);
    router.delete(`/${route}/:id`, authenticate, controller.delete);
  }
});

// Special routes for material import
router.post('/material/import', authenticate, bulkImportMaterials);

// Material drawing routes
router.post('/material/:material_id/drawing', authenticate, materialDrawingController.uploadDrawing);
router.get('/material/:material_id/drawing', authenticate, materialDrawingController.getDrawing);
router.delete('/material/:material_id/drawing', authenticate, materialDrawingController.deleteDrawing);

// Print Header routes
const printHeaderController = require('../controllers/printHeaderController');
router.post('/printheader/:header_id/logo', authenticate, printHeaderController.uploadLogo);
router.get('/printheader/:id/print', authenticate, printHeaderController.getPrintHeader);

// Business Partner specific routes (continued - :id routes can be after generic routes)
router.get('/businesspartner/:id/print', authenticate, businessPartnerController.getPrintData);
router.post('/businesspartner/:id/approve', authenticate, businessPartnerController.approve);
router.post('/businesspartner/:id/reject', authenticate, businessPartnerController.reject);

// Number Generation routes
const numberGenerationService = require('../services/numberGenerationService');
router.get('/numberformat/material/preview', authenticate, async (req, res) => {
  try {
    const { company_id, material_type_id } = req.query;
    
    if (!company_id || !material_type_id) {
      return res.status(400).json({
        success: false,
        message: 'company_id and material_type_id are required'
      });
    }

    const format = await numberGenerationService.getMaterialNumberFormat(
      parseInt(company_id),
      parseInt(material_type_id)
    );

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

    res.json({
      success: true,
      data: format
    });
  } catch (error) {
    console.error('Error getting material number format:', error);
    res.status(500).json({
      success: false,
      message: error.message || 'Failed to get material number format'
    });
  }
});

router.post('/numberformat/material/generate', authenticate, async (req, res) => {
  try {
    const { company_id, material_type_id } = req.body;
    
    if (!company_id || !material_type_id) {
      return res.status(400).json({
        success: false,
        message: 'company_id and material_type_id are required'
      });
    }

    const materialNumber = await numberGenerationService.generateMaterialNumber(
      parseInt(company_id),
      parseInt(material_type_id)
    );

    res.json({
      success: true,
      data: {
        material_number: materialNumber
      }
    });
  } catch (error) {
    console.error('Error generating material number:', error);
    res.status(500).json({
      success: false,
      message: error.message || 'Failed to generate material number'
    });
  }
});

// Material Substitution Routes
router.get('/material-substitution/rules', authenticate, materialSubstitutionController.getSubstitutionRules);
router.get('/material-substitution', authenticate, materialSubstitutionController.getSubstitutionMasters);
router.post('/material-substitution', authenticate, materialSubstitutionController.createSubstitutionMaster);
router.get('/material-substitution/transactions', authenticate, materialSubstitutionController.getSubstitutionTransactions);
router.post('/material-substitution/:transactionId/approve', authenticate, materialSubstitutionController.approveSubstitution);

module.exports = router;

