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

/**
 * Get Business Partner data for printing
 */
exports.getPrintData = asyncHandler(async (req, res) => {
  const { id } = req.params;

  const businessPartner = await db.BusinessPartner.findByPk(id, {
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.VendorCategory,
        as: 'vendorCategory',
        attributes: ['id', 'category_code', 'category_name'],
        required: false
      },
      {
        model: db.BPAddress,
        as: 'addresses',
        where: { status: 'ACTIVE' },
        required: false,
        include: [
          { model: db.City, as: 'city', attributes: ['id', 'city_name'] },
          { model: db.State, as: 'state', attributes: ['id', 'state_name', 'state_code'] },
          { model: db.Country, as: 'country', attributes: ['id', 'country_name'] },
        ]
      },
      {
        model: db.BPBank,
        as: 'banks',
        where: { status: 'ACTIVE' },
        required: false,
        include: [
          { model: db.Bank, as: 'bank', attributes: ['id', 'bank_name', 'bank_code'] }
        ]
      },
      {
        model: db.BPGSTIN,
        as: 'gstins',
        where: { status: 'ACTIVE' },
        required: false,
        include: [
          { model: db.City, as: 'city', attributes: ['id', 'city_name'] },
          { model: db.State, as: 'state', attributes: ['id', 'state_name', 'state_code'] },
          { model: db.Country, as: 'country', attributes: ['id', 'country_name'] },
        ]
      },
      {
        model: db.Currency,
        as: 'currency',
        attributes: ['id', 'currency_code', 'currency_name']
      }
    ]
  });

  if (!businessPartner) {
    return sendError(res, 'Business Partner not found', 404);
  }

  // Get print header based on company
  let printHeader = null;
  if (businessPartner.company_id) {
    printHeader = await db.PrintHeader.findOne({
      where: {
        company_id: businessPartner.company_id,
        status: 'ACTIVE'
      },
      order: [['id', 'DESC']] // Get the latest active header
    });

    // Convert print header file paths to URLs if exists
    if (printHeader) {
      // Use configured base URL (without /api/v1 for static files)
      let baseUrl = process.env.API_BASE_URL || process.env.BASE_URL || 'http://localhost:5006';
      // Remove /api/v1 if present to get the base server URL for static files
      baseUrl = baseUrl.replace(/\/api\/v1$/, '');
      
      // Ensure baseUrl has protocol
      if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {
        baseUrl = `http://${baseUrl}`;
      }
      
      // Helper function to construct file URL
      const constructFileUrl = (filePath) => {
        if (!filePath) return null;
        // If already a full URL, return as is
        if (filePath.startsWith('http')) return filePath;
        // If already starts with /uploads, use it directly
        if (filePath.startsWith('/uploads')) {
          return `${baseUrl}${filePath}`;
        }
        // Otherwise, prepend /uploads/ to the path
        const normalizedPath = filePath.replace(/\\/g, '/');
        const uploadsPath = normalizedPath.startsWith('/') ? normalizedPath : `/${normalizedPath}`;
        return `${baseUrl}/uploads${uploadsPath}`;
      };
      
      printHeader = {
        ...printHeader.toJSON(),
        logo_url: constructFileUrl(printHeader.logo_path),
        certification_logo_url: constructFileUrl(printHeader.quality_certification_logo_path),
      };
    }
  }

  // Get document number for Supplier Registration Form
  let documentNumber = null;
  if (businessPartner.company_id) {
    const document = await db.Document.findOne({
      where: {
        company_id: businessPartner.company_id,
        erp_module: 'BUSINESS_PARTNER',
        status: 'ACTIVE'
      },
      order: [['id', 'DESC']]
    });
    if (document) {
      documentNumber = document.document_number;
    }
  }

  // Check if vendor is Job Worker
  const isJobWorker = businessPartner.vendorCategory?.category_code === 'JOB_WORKER' || 
                      businessPartner.vendorCategory?.category_name?.toUpperCase().includes('JOB WORKER');

  // Get factory address (if exists)
  const factoryAddress = businessPartner.addresses?.find(addr => 
    addr.address_type === 'FACTORY' || addr.address_type === 'SHIPPING'
  ) || null;

  // Format the data for printing
  const data = {
    businessPartner: businessPartner.toJSON(),
    printHeader: printHeader,
    documentNumber: documentNumber,
    isJobWorker: isJobWorker,
    vendorCategory: businessPartner.vendorCategory,
    // Get default/primary addresses, banks, and GSTINs
    defaultAddress: businessPartner.addresses?.find(addr => addr.is_default) || businessPartner.addresses?.[0] || null,
    factoryAddress: factoryAddress,
    defaultBank: businessPartner.banks?.find(bank => bank.is_default) || businessPartner.banks?.[0] || null,
    defaultGSTIN: businessPartner.gstins?.find(gstin => gstin.is_default) || businessPartner.gstins?.[0] || null,
    allAddresses: businessPartner.addresses || [],
    allBanks: businessPartner.banks || [],
    allGSTINs: businessPartner.gstins || [],
  };

  sendResponse(res, 200, true, 'Business Partner print data retrieved successfully', data);
});

/**
 * Approve a Business Partner
 */
exports.approve = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const userId = req.user?.userId || null;

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

  const businessPartner = await db.BusinessPartner.findByPk(id);

  if (!businessPartner) {
    return sendError(res, 'Business Partner not found', 404);
  }

  if (businessPartner.approval_status === 'APPROVED') {
    return sendError(res, 'Business Partner is already approved', 400);
  }

  if (businessPartner.approval_status === 'REJECTED') {
    return sendError(res, 'Cannot approve a rejected Business Partner. Please create a new one.', 400);
  }

  await businessPartner.update({
    approval_status: 'APPROVED',
    approved_by: userId,
    approved_at: new Date(),
    updated_by: userId
  });

  const updatedBP = await db.BusinessPartner.findByPk(id, {
    include: [
      { model: db.Company, as: 'company', attributes: ['id', 'code', 'name'] },
      { model: db.VendorCategory, as: 'vendorCategory', attributes: ['id', 'category_code', 'category_name'] }
    ]
  });

  sendResponse(res, 200, true, 'Business Partner approved successfully', updatedBP);
});

/**
 * Reject a Business Partner
 */
exports.reject = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const { rejection_reason } = req.body;
  const userId = req.user?.userId || null;

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

  if (!rejection_reason || rejection_reason.trim() === '') {
    return sendError(res, 'Rejection reason is required', 400);
  }

  const businessPartner = await db.BusinessPartner.findByPk(id);

  if (!businessPartner) {
    return sendError(res, 'Business Partner not found', 404);
  }

  if (businessPartner.approval_status === 'REJECTED') {
    return sendError(res, 'Business Partner is already rejected', 400);
  }

  if (businessPartner.approval_status === 'APPROVED') {
    return sendError(res, 'Cannot reject an approved Business Partner', 400);
  }

  await businessPartner.update({
    approval_status: 'REJECTED',
    rejected_by: userId,
    rejected_at: new Date(),
    rejection_reason: rejection_reason.trim(),
    updated_by: userId
  });

  const updatedBP = await db.BusinessPartner.findByPk(id, {
    include: [
      { model: db.Company, as: 'company', attributes: ['id', 'code', 'name'] },
      { model: db.VendorCategory, as: 'vendorCategory', attributes: ['id', 'category_code', 'category_name'] }
    ]
  });

  sendResponse(res, 200, true, 'Business Partner rejected successfully', updatedBP);
});

/**
 * Get Approved Suppliers List for Report
 */
exports.getApprovedSuppliers = asyncHandler(async (req, res) => {
  const { companyId, company_id } = req.query;
  const companyIdValue = companyId || company_id || req.user?.companyId;

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

  // Get approved vendors (suppliers)
  const approvedSuppliers = await db.BusinessPartner.findAll({
    where: {
      company_id: companyIdValue,
      bp_type: { [db.Sequelize.Op.in]: ['VENDOR', 'BOTH'] },
      approval_status: 'APPROVED',
      status: 'ACTIVE'
    },
    include: [
      {
        model: db.BPAddress,
        as: 'addresses',
        where: { 
          status: 'ACTIVE',
          is_default: true
        },
        required: false,
        include: [
          { model: db.City, as: 'city', attributes: ['id', 'city_name'] },
          { model: db.State, as: 'state', attributes: ['id', 'state_name', 'state_code'] },
          { model: db.Country, as: 'country', attributes: ['id', 'country_name'] },
        ]
      },
      {
        model: db.BPGSTIN,
        as: 'gstins',
        where: { 
          status: 'ACTIVE',
          is_default: true
        },
        required: false,
        include: [
          { model: db.State, as: 'state', attributes: ['id', 'state_name', 'gst_state_code'] }
        ]
      },
      {
        model: db.VendorCategory,
        as: 'vendorCategory',
        attributes: ['id', 'category_code', 'category_name'],
        required: false
      }
    ],
    order: [['name', 'ASC']]
  });

  // Get document number from document master
  let documentNumber = null;
  const document = await db.Document.findOne({
    where: {
      company_id: companyIdValue,
      erp_module: 'BUSINESS_PARTNER',
      status: 'ACTIVE'
    },
    order: [['id', 'DESC']]
  });
  if (document) {
    documentNumber = document.document_number;
  }

  // Get company details
  const company = await db.Company.findByPk(companyIdValue, {
    attributes: ['id', 'code', 'name', 'legal_name']
  });

  if (!company) {
    return sendError(res, 'Company not found', 404);
  }

  // Format data for report
  const reportData = {
    company: company,
    documentNumber: documentNumber,
    suppliers: approvedSuppliers.map(bp => {
      const defaultAddress = bp.addresses?.[0] || null;
      const defaultGSTIN = bp.gstins?.[0] || null;
      
      // Format address
      let address = '';
      if (defaultAddress) {
        const parts = [
          defaultAddress.address_line1,
          defaultAddress.address_line2,
          defaultAddress.city?.city_name,
          defaultAddress.state?.state_name,
          defaultAddress.pincode
        ].filter(Boolean);
        address = parts.join(', ');
      }

      return {
        id: bp.id,
        supplier_code: bp.bp_number || '',
        supplier_name: bp.name,
        contact_no: defaultAddress?.phone || defaultAddress?.mobile || '',
        email: defaultAddress?.email || '',
        website: defaultAddress?.website || '',
        scope_of_supply: bp.vendorCategory?.category_name || '',
        gst_no: defaultGSTIN?.gstin || '',
        pan_no: bp.pan || '',
        address: address
      };
    })
  };

  sendResponse(res, 200, true, 'Approved suppliers list retrieved successfully', reportData);
});
