const { logger } = require('nodejs-log-agent');
const { generatePDF } = require('../libs/pdfGenerate');
const db = require("../models");
const moment = require('moment')
require('moment/locale/id') // load locale Indonesia
moment.locale('id') // set locale default ke Indonesia

const Joi = require('joi');
const { getInvoice } = require('../libs/whmcs');

const generatePDFSchema = Joi.object({
  client_name: Joi.string().required(),
  client_phone: Joi.string().required(),
  client_address: Joi.string().required(),
  inv_id: Joi.alternatives().try(Joi.string(), Joi.number()).required(),
  inv_status: Joi.string().required(),
  inv_date: Joi.string().required(),
  inv_duedate: Joi.string().required(),
  sub_total: Joi.string().required(),
  total: Joi.string().required(),
  ppn: Joi.string().required(),
  credit: Joi.string().required(),
  balance: Joi.string().required(),
  company: Joi.string().required(),
  items: Joi.array().items(
    Joi.object({
      id: Joi.any().required(),
      description: Joi.string().required(),
      amount: Joi.string().required()
    })
  ).required(),
  transaction: Joi.array().items(
    Joi.object({
      id: Joi.any().required(),
      gateway: Joi.string().required(),
      date: Joi.string().required(),
      description: Joi.string().required(),
      amount: Joi.string().required()
    })
  )
});

const generatePDFController = async (req, res) => {
  const data = req.body;

  // Validasi input
  const { error } = generatePDFSchema.validate(data);
  if (error) {
    logger.warn(`[PDF] Invalid input for inv_id ${data?.inv_id || 'N/A'}: ${error.message}`);
    return res.status(400).json({ status: false, message: 'Invalid input', error: error.details });
  }

  try {
    logger.info(`[PDF] Start generating PDF for invoice ${data.inv_id} - ${data.client_name}`);

    const result = await handlePDFGeneration(data);

    if (!result.status) {
      logger.error(`[PDF] Failed to generate PDF for ${data.inv_id}: ${result.message || 'unknown error'}`);
      return res.status(500).json({ status: false, message: 'Failed to generate PDF', error: result });
    }

    logger.info(`[PDF] Successfully generated PDF for invoice ${data.inv_id}`);
    return res.json({
      status: true,
      message: 'PDF generated successfully',
      pdfPath: result.pdfPath
    });
  } catch (err) {
    logger.error(`[PDF] Unexpected error while generating PDF for invoice ${data.inv_id || 'N/A'}: ${err.message}`, {
      stack: err.stack,
      context: 'generatePDFController'
    });
    const isDevelopment = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test';

    return res.status(500).json({
      status: false,
      message: isDevelopment ? err.message : 'Internal server error',
      error: isDevelopment ? err.stack : 'An unexpected error occurred.'
    });
  }
};

// Helper function to generate PDF
const handlePDFGeneration = async (datawhmcs) => {
    const generateinvoice = await generatePDF(datawhmcs);
    if (generateinvoice.status) {
        await db.invoice.update({ pdfCreated: true, pdfName: generateinvoice.pdfPath }, { where: { inv_id: datawhmcs.inv_id } });
    }
    return generateinvoice;
};

const generateBYID = async (req, res) => {
  try {
    const inv_id = req.params.inv_id;
    const datafromwhmcs = await getInvoice(inv_id);
    const datawhmcs = await db.invoice.findOne({
      where: { inv_id },
      include: [
        { model: db.invoicedetails, as: 'invoiceDetails' },
        { model: db.invoice_trans, as: 'invoiceTrans' },
        { model: db.invoiceitem, as: 'invoiceitem' }
      ]
    });

    if (!datawhmcs) {
      logger.warn(`[PDF] Invoice not found for inv_id: ${inv_id}`);
      return res.status(404).json({ status: false, message: 'Invoice not found' });
    }

    logger.info(`[PDF] Found invoice ${inv_id}, preparing data for PDF generation.`);
    const formattedData = formatInvoiceResponse(datawhmcs, datafromwhmcs.company);
    const result = await handlePDFGeneration(formattedData);

    if (!result.status) {
      logger.error(`[PDF] Failed to generate PDF for ${inv_id}: ${result.message || 'unknown error'}`);
      return res.status(500).json({ status: false, message: 'Failed to generate PDF', error: result });
    }

    logger.info(`[PDF] Successfully generated PDF for invoice ${inv_id}`);
    return res.json({
      status: true,
      message: 'PDF generated successfully',
      pdfPath: result.pdfPath
    });
  } catch (err) {
    logger.error(`[PDF] Unexpected error in generateBYID for inv_id ${req.params.inv_id || 'N/A'}: ${err.message}`, {
      stack: err.stack,
      context: 'generateBYID'
    });
    const isDevelopment = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test';

    return res.status(500).json({
      status: false,
      message: isDevelopment ? err.message : 'Internal server error',
      error: isDevelopment ? err.stack : 'An unexpected error occurred.'
    });
  }
}

const formatInvoiceResponse = (datawhmcs, company) => {
  // Provide safe defaults for all potentially missing data
  const details = datawhmcs.invoiceDetails?.dataValues || {};
  const items = datawhmcs.invoiceitem || [];
  const transactions = datawhmcs.invoiceTrans || [];

  return {
    // Core invoice data with fallbacks
    inv_id: datawhmcs.inv_id,
    inv_status: datawhmcs.inv_status,
    inv_date: details.inv_date
      ? moment(details.inv_date).format('dddd, DD MMMM YYYY')
      : '',
    inv_duedate: details.inv_duedate
      ? moment(details.inv_duedate).format('dddd, DD MMMM YYYY')
      : '',

    // Client details with fallbacks
    client_name: details.client_name || datawhmcs.inv_name || 'N/A',
    client_phone: datawhmcs.phoneNumber || '',
    client_address: details.client_address || '',
    company: company || '',

    // Financial details
    sub_total: details.sub_total || '0',
    total: details.total || '0',
    ppn: details.ppn || '0',
    credit: details.credit || '0',
    balance: details.total || '0',

    // Safely map items and transactions, ensuring they are always arrays
    items: Array.isArray(items) ? items.map(item => ({
      description: item.description || '',
      amount: item.total || '0'
    })) : [],
    transaction: Array.isArray(transactions) ? transactions.map(trx => ({
      gateway: trx.gateway === 'banktransfer' ? 'Bank Transfer' : (trx.gateway || ''),
      date: trx.date ? moment(trx.date).format('dddd, DD MMMM YYYY') : '',
      description: trx.description || '',
      amount: trx.amount || '0'
    })) : []
  }
}
module.exports = {generatePDFController, generateBYID};