const { Op } = require('sequelize');
const db = require('../models');

const DEFAULT_EMAIL_SUBJECT = 'Purchase Order {PO_NUMBER}';
const DEFAULT_EMAIL_BODY = [
  'Dear {VENDOR_NAME},',
  '',
  'A Purchase Order has been created.',
  'PO Number: {PO_NUMBER}',
  'PO Date: {PO_DATE}',
  'Total Amount: {TOTAL_AMOUNT}',
  '',
  'Regards,',
  '{COMPANY_NAME}'
].join('\n');
const DEFAULT_WHATSAPP_BODY = 'Dear {VENDOR_NAME}, PO {PO_NUMBER} dated {PO_DATE} has been created. Total Amount: {TOTAL_AMOUNT}.';

const formatDate = (value) => {
  if (!value) return '';
  const d = new Date(value);
  if (Number.isNaN(d.getTime())) return '';
  const dd = String(d.getDate()).padStart(2, '0');
  const mm = String(d.getMonth() + 1).padStart(2, '0');
  const yyyy = d.getFullYear();
  return `${dd}-${mm}-${yyyy}`;
};

const fmtMoney = (value) => {
  const n = parseFloat(value || 0);
  return Number.isFinite(n) ? n.toFixed(2) : '0.00';
};

const getPrimaryVendorContact = async (vendorId) => {
  if (!vendorId) return { email: '', mobile: '' };
  const preferred = await db.BPAddress.findOne({
    where: { bp_id: vendorId, status: 'ACTIVE', address_type: 'BILLING' },
    order: [['is_default', 'DESC'], ['id', 'ASC']]
  });
  if (preferred) {
    return {
      email: preferred.email || '',
      mobile: preferred.mobile || preferred.phone || ''
    };
  }
  const anyAddress = await db.BPAddress.findOne({
    where: { bp_id: vendorId, status: 'ACTIVE' },
    order: [['id', 'ASC']]
  });
  return {
    email: anyAddress?.email || '',
    mobile: anyAddress?.mobile || anyAddress?.phone || ''
  };
};

const getSettings = async (companyId) => {
  if (!companyId) return null;
  const settings = await db.NotificationSetting.findOne({
    where: { company_id: companyId, status: { [Op.ne]: 'INACTIVE' } }
  });
  return settings;
};

const ensureSettings = async (companyId, userId = null) => {
  let settings = await getSettings(companyId);
  if (settings) return settings;
  settings = await db.NotificationSetting.create({
    company_id: companyId,
    auto_email_po: false,
    manual_email_po: true,
    auto_whatsapp_po: false,
    manual_whatsapp_po: true,
    email_subject_template: DEFAULT_EMAIL_SUBJECT,
    email_body_template: DEFAULT_EMAIL_BODY,
    whatsapp_message_template: DEFAULT_WHATSAPP_BODY,
    status: 'ACTIVE',
    created_by: userId,
    updated_by: userId
  });
  return settings;
};

const replaceTemplate = (template, values) => {
  let output = String(template || '');
  Object.entries(values).forEach(([k, v]) => {
    output = output.replace(new RegExp(`\\{${k}\\}`, 'g'), String(v || ''));
  });
  return output;
};

const loadPOContext = async (poId) => {
  const po = await db.PurchaseOrder.findByPk(poId, {
    include: [
      { model: db.Company, as: 'company', attributes: ['id', 'name', 'legal_name'] },
      { model: db.BusinessPartner, as: 'vendor', attributes: ['id', 'name', 'legal_name', 'vendor_name', 'phone_numbers'] }
    ]
  });
  if (!po) throw new Error('Purchase Order not found');
  const contact = await getPrimaryVendorContact(po.vendor_id);
  const vendorName = po.vendor?.vendor_name || po.vendor?.name || po.vendor?.legal_name || 'Vendor';
  return {
    po,
    vendorName,
    companyName: po.company?.name || po.company?.legal_name || 'Company',
    vendorEmail: contact.email || '',
    vendorMobile: contact.mobile || po.vendor?.phone_numbers || ''
  };
};

const buildTemplateValues = ({ po, vendorName, companyName }) => ({
  PO_NUMBER: po.po_number || '',
  PO_DATE: formatDate(po.po_date),
  VENDOR_NAME: vendorName,
  TOTAL_AMOUNT: fmtMoney(po.total_amount),
  COMPANY_NAME: companyName
});

const sendEmailForPO = async ({ poId, userId = null, isManual = false }) => {
  const ctx = await loadPOContext(poId);
  const settings = await ensureSettings(ctx.po.company_id, userId);
  if (isManual && !settings.manual_email_po) {
    throw new Error('Manual Email notification is disabled in Notification Settings');
  }
  if (!isManual && !settings.auto_email_po) {
    return { skipped: true, channel: 'EMAIL', reason: 'Automatic Email disabled' };
  }
  if (!ctx.vendorEmail) throw new Error('Vendor email is not configured');
  if (!settings.smtp_host || !settings.smtp_port || !settings.smtp_from_email) {
    throw new Error('SMTP settings are incomplete');
  }

  const values = buildTemplateValues(ctx);
  const subject = replaceTemplate(settings.email_subject_template || DEFAULT_EMAIL_SUBJECT, values);
  const body = replaceTemplate(settings.email_body_template || DEFAULT_EMAIL_BODY, values);

  let nodemailer;
  try {
    // Loaded lazily so server remains functional if dependency is missing.
    // Install with: npm install nodemailer
    // eslint-disable-next-line global-require
    nodemailer = require('nodemailer');
  } catch (error) {
    throw new Error('Email dependency "nodemailer" is not installed on server');
  }

  const transporter = nodemailer.createTransport({
    host: settings.smtp_host,
    port: parseInt(settings.smtp_port, 10) || 587,
    secure: Boolean(settings.smtp_secure),
    auth: settings.smtp_user
      ? {
          user: settings.smtp_user,
          pass: settings.smtp_password || ''
        }
      : undefined
  });

  await transporter.sendMail({
    from: settings.smtp_from_name
      ? `"${settings.smtp_from_name}" <${settings.smtp_from_email}>`
      : settings.smtp_from_email,
    to: ctx.vendorEmail,
    subject,
    text: body
  });

  return { sent: true, channel: 'EMAIL', to: ctx.vendorEmail };
};

const sendWhatsAppForPO = async ({ poId, userId = null, isManual = false }) => {
  const ctx = await loadPOContext(poId);
  const settings = await ensureSettings(ctx.po.company_id, userId);
  if (isManual && !settings.manual_whatsapp_po) {
    throw new Error('Manual WhatsApp notification is disabled in Notification Settings');
  }
  if (!isManual && !settings.auto_whatsapp_po) {
    return { skipped: true, channel: 'WHATSAPP', reason: 'Automatic WhatsApp disabled' };
  }
  if (!ctx.vendorMobile) throw new Error('Vendor mobile number is not configured');
  if (!settings.whatsapp_api_url) {
    throw new Error('WhatsApp API URL is not configured');
  }
  if (typeof fetch !== 'function') {
    throw new Error('WhatsApp sending is not supported on this runtime');
  }

  const values = buildTemplateValues(ctx);
  const message = replaceTemplate(settings.whatsapp_message_template || DEFAULT_WHATSAPP_BODY, values);
  const headers = { 'Content-Type': 'application/json' };
  if (settings.whatsapp_api_token) {
    headers.Authorization = `Bearer ${settings.whatsapp_api_token}`;
  }

  const response = await fetch(settings.whatsapp_api_url, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      to: ctx.vendorMobile,
      message,
      po_number: ctx.po.po_number,
      po_id: ctx.po.id
    })
  });
  if (!response.ok) {
    const errText = await response.text();
    throw new Error(`WhatsApp API failed: ${response.status} ${errText || response.statusText}`);
  }

  return { sent: true, channel: 'WHATSAPP', to: ctx.vendorMobile };
};

const triggerAutoNotificationsForPO = async ({ poId, userId = null }) => {
  const out = { email: null, whatsapp: null };
  try {
    out.email = await sendEmailForPO({ poId, userId, isManual: false });
  } catch (error) {
    out.email = { sent: false, channel: 'EMAIL', error: error.message };
  }
  try {
    out.whatsapp = await sendWhatsAppForPO({ poId, userId, isManual: false });
  } catch (error) {
    out.whatsapp = { sent: false, channel: 'WHATSAPP', error: error.message };
  }
  return out;
};

module.exports = {
  DEFAULT_EMAIL_SUBJECT,
  DEFAULT_EMAIL_BODY,
  DEFAULT_WHATSAPP_BODY,
  ensureSettings,
  getSettings,
  sendEmailForPO,
  sendWhatsAppForPO,
  triggerAutoNotificationsForPO
};
