const fs = require('fs');
const path = require('path');

function getArg(name) {
  const index = process.argv.indexOf(`--${name}`);
  if (index === -1 || index + 1 >= process.argv.length) return '';
  return process.argv[index + 1];
}

function ensureDir(dirPath) {
  fs.mkdirSync(dirPath, { recursive: true });
}

function timestampForFile() {
  return new Date().toISOString().replace(/[:.]/g, '-');
}

function clearAuthDir(authDir) {
  try {
    fs.rmSync(authDir, { recursive: true, force: true });
  } catch (_) {
  }
  ensureDir(authDir);
}

function getStatusCode(error) {
  if (!error) return undefined;
  if (error.output && error.output.statusCode) return error.output.statusCode;
  if (error.statusCode) return error.statusCode;
  return undefined;
}

async function main() {
  const mode = (getArg('mode') || 'send').toLowerCase();
  const phone = getArg('phone').replace(/\D/g, '');
  const filePath = getArg('file');
  const caption = getArg('caption') || 'MyBiz invoice';
  const message = getArg('message') || caption;
  const isTextMode = mode === 'text' || mode === 'message' || mode === 'reminder';
  const programData = process.env.ProgramData || process.cwd();
  const logDir = getArg('logdir') || path.join(programData, 'MyBiz_ACCGST', 'WhatsAppLogs');
  const statusDir = getArg('statusdir') || path.join(programData, 'MyBiz_ACCGST', 'WhatsAppQr');
  ensureDir(logDir);
  ensureDir(statusDir);

  const logFile = path.join(logDir, `whatsapp-${timestampForFile()}.log`);
  const qrFile = path.join(statusDir, 'qr.png');
  const qrTempFile = path.join(statusDir, 'qr.tmp.png');
  const statusFile = path.join(statusDir, 'status.txt');
  const statusTempFile = path.join(statusDir, 'status.tmp.txt');

  function log(text) {
    const line = `${new Date().toISOString()} ${text}`;
    console.log(text);
    try {
      fs.appendFileSync(logFile, `${line}\n`);
    } catch (_) {
    }
  }

  function writeStatus(state, text) {
    try {
      const content = `${state}|${String(text || '').replace(/[\r\n|]+/g, ' ')}`;
      fs.writeFileSync(statusTempFile, content, 'utf8');
      fs.renameSync(statusTempFile, statusFile);
    } catch (error) {
      log(`RF_STATUS_WRITE_FAILED ${error.message || error}`);
    }
  }

  function fail(marker, error) {
    const text = error && error.message ? error.message : String(error);
    log(`${marker} ${text}`);
    if (mode === 'login') writeStatus('FAILED', text);
    throw new Error(text);
  }

  log(`RF_WHATSAPP_STARTING mode=${mode} (Baileys)`);
  if (mode === 'login') {
    writeStatus('STARTING', 'Starting WhatsApp connection...');
    try { fs.rmSync(qrFile, { force: true }); } catch (_) {}
    try { fs.rmSync(qrTempFile, { force: true }); } catch (_) {}
  }

  if (mode !== 'login' && !/^91[6-9][0-9]{9}$/.test(phone)) {
    fail('RF_SEND_FAILED', 'Invalid WhatsApp mobile number. Use a valid Indian 10 digit mobile number.');
  }

  if (mode !== 'login' && !isTextMode && (!filePath || !fs.existsSync(filePath))) {
    fail('RF_SEND_FAILED', `Invoice PDF not found: ${filePath}`);
  }

  if (mode !== 'login' && isTextMode && !String(message || '').trim()) {
    fail('RF_SEND_FAILED', 'WhatsApp text message is empty.');
  }

  const authDir = path.join(programData, 'MyBiz_ACCGST', 'WhatsAppSession', 'baileys_auth');
  ensureDir(authDir);

  if (mode === 'login') {
    clearAuthDir(authDir);
  } else {
    const credsFile = path.join(authDir, 'creds.json');
    if (!fs.existsSync(credsFile)) {
      fail('RF_SEND_FAILED', 'WhatsApp not logged in. Please scan QR from WhatsApp Settings first.');
    }
  }

  const {
    default: makeWASocket,
    useMultiFileAuthState,
    DisconnectReason,
    fetchLatestBaileysVersion,
    Browsers
  } = require('@whiskeysockets/baileys');
  const pino = require('pino');
  const QRCode = require('qrcode');

  const versionInfo = await fetchLatestBaileysVersion();
  log(`RF_BAILEYS_VERSION ${versionInfo.version.join('.')} isLatest=${versionInfo.isLatest}`);

  let retryCount = 0;
  const maxRetries = 5;

  async function startSocket() {
    const { state, saveCreds } = await useMultiFileAuthState(authDir);
    const sock = makeWASocket({
      auth: state,
      printQRInTerminal: false,
      browser: Browsers.ubuntu('Chrome'),
      version: versionInfo.version,
      logger: pino({ level: 'silent' }),
      syncFullHistory: false,
      generateHighQualityLinkPreview: false
    });

    sock.ev.on('creds.update', saveCreds);

    return new Promise((resolve, reject) => {
      let finished = false;

      function finish(code, error) {
        if (finished) return;
        finished = true;
        try { sock.end(undefined); } catch (_) {}
        if (code === 0) resolve('done');
        else if (code === 2) resolve('reconnect');
        else reject(error || new Error('WhatsApp failed.'));
      }

      sock.ev.on('connection.update', async (update) => {
        const { connection, lastDisconnect, qr } = update;

        if (qr && mode === 'login') {
          try {
            await QRCode.toFile(qrTempFile, qr, {
              type: 'png',
              width: 512,
              margin: 2,
              color: { dark: '#000000', light: '#FFFFFF' }
            });
            try { fs.rmSync(qrFile, { force: true }); } catch (_) {}
            fs.renameSync(qrTempFile, qrFile);
            writeStatus('QR_READY', 'QR ready - scan from WhatsApp Linked devices.');
            log(`RF_QR_IMAGE_READY ${qrFile}`);
          } catch (qrError) {
            log(`RF_QR_IMAGE_ERROR ${qrError.message || qrError}`);
            writeStatus('FAILED', `Unable to create QR image: ${qrError.message || qrError}`);
          }
        }

        if (connection === 'close') {
          const closeError = lastDisconnect && lastDisconnect.error;
          const statusCode = getStatusCode(closeError);
          log(`RF_CONNECTION_CLOSED statusCode=${statusCode} retry=${retryCount}/${maxRetries}`);

          if ((statusCode === 515 || statusCode === 408 || statusCode === 428) && retryCount < maxRetries) {
            finish(2);
            return;
          }

          if (statusCode === 405 && retryCount < maxRetries) {
            clearAuthDir(authDir);
            finish(2);
            return;
          }

          if (statusCode === DisconnectReason.loggedOut) {
            clearAuthDir(authDir);
            finish(1, new Error('WhatsApp session logged out. Please scan QR again.'));
            return;
          }

          finish(1, new Error(`WhatsApp connection failed (code ${statusCode || 'unknown'}). Check internet and date/time, then try again.`));
        }

        if (connection === 'open') {
          log('RF_AUTH_READY');
          retryCount = 0;

          if (mode === 'login') {
            writeStatus('CONNECTED', 'CONNECTED - WhatsApp session saved.');
            log('RF_LOGIN_SUCCESS WhatsApp session saved.');
            setTimeout(() => finish(0), 3000);
            return;
          }

          try {
            const chatId = `${phone}@s.whatsapp.net`;
            if (isTextMode) {
              log(`RF_SENDING_TEXT to ${chatId}`);
              await sock.sendMessage(chatId, { text: message });
            } else {
              const fileBuffer = fs.readFileSync(filePath);
              const fileName = path.basename(filePath);
              log(`RF_SENDING to ${chatId} file=${fileName}`);
              await sock.sendMessage(chatId, {
                document: fileBuffer,
                mimetype: 'application/pdf',
                fileName,
                caption
              });
            }
            log('RF_SEND_COMPLETE');
            setTimeout(() => finish(0), 1500);
          } catch (sendError) {
            finish(1, sendError);
          }
        }
      });

      const timeoutMs = mode === 'login' ? 300000 : 120000;
      setTimeout(() => {
        if (!finished) {
          finish(1, new Error(mode === 'login'
            ? 'QR code was not scanned within 5 minutes.'
            : 'WhatsApp connection timeout. Scan QR and try again.'));
        }
      }, timeoutMs);
    });
  }

  let result = 'reconnect';
  while (result === 'reconnect' && retryCount < maxRetries) {
    retryCount += 1;
    if (retryCount > 1) {
      const delay = Math.min(retryCount * 2000, 8000);
      log(`RF_RECONNECT_DELAY ${delay}ms`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
    result = await startSocket();
  }

  if (result === 'reconnect') {
    fail(mode === 'login' ? 'RF_LOGIN_FAILED' : 'RF_SEND_FAILED',
      'WhatsApp connection failed after multiple retries.');
  }
}

main().then(() => {
  process.exit(0);
}).catch((error) => {
  const text = error && error.message ? error.message : String(error);
  try {
    const mode = (getArg('mode') || 'send').toLowerCase();
    if (mode === 'login') {
      const programData = process.env.ProgramData || process.cwd();
      const statusDir = getArg('statusdir') || path.join(programData, 'MyBiz_ACCGST', 'WhatsAppQr');
      ensureDir(statusDir);
      fs.writeFileSync(path.join(statusDir, 'status.txt'), `FAILED|${text.replace(/[\r\n|]+/g, ' ')}`, 'utf8');
    }
  } catch (_) {
  }
  console.error(text);
  process.exit(1);
});
