/**
 * src/bot/index.js
 *
 * Webex bot initialization and command registration.
 *
 * Extracted during the 2026-05-28 refactor to make index.js a thin bootstrap.
 */

import framework from 'webex-node-bot-framework';
import os from 'node:os';
import { logger } from '../utils/logger.js';

import { handleHelp } from '../commands/help.js';
import { handleUnknown } from '../commands/unknownCommand.js';
import { handleWoSummary } from '../commands/woSummary.js';
import { handleWoAttachments } from '../commands/woAttachments.js';
import { handleWoHistory } from '../commands/woHistory.js';
import { handleAvStatus } from '../commands/avStatus.js';
import { handleWoApprove } from '../commands/woApprove.js';
import { handleWoConfirmed } from '../commands/woConfirmed.js';
import { handleWoAddNote } from '../commands/woAddNote.js';
import { handleWoAttach } from '../commands/woAttach.js';
import { handleWoTrackStatus } from '../commands/woTrackStatus.js';
import { handleWoTrackTest } from '../commands/woTrackTest.js';
import { handleWoCreate } from '../commands/woCreate.js';
import approvalService from '../services/approvalService.js';
import invoiceApprovalService from '../services/invoiceApprovalService.js';
import workOrderCreateService from '../services/workOrderCreateService.js';
import { installMercuryGuard } from './mercuryGuard.js';
import db from '../db/mappings.js';

/**
 * Initialize and start the Webex bot framework.
 * @param {object} options
 * @param {object} options.webexConfig - The webex auth section from config
 * @returns {object} The Framework instance
 */
export function initializeBot({ webexConfig }) {
  if (!webexConfig?.token) {
    throw new Error('webexConfig.token is required to initialize the bot');
  }

  const Framework = new framework({
    ...webexConfig,
    spawn: false,
    mentionOnly: true,
    removeME: false,
    suppressDirectSpaceSpawnFailures: true
  });

  Framework.start();

  logger('bot', `ServChan bot instance pid=${process.pid} hostname=${os.hostname()}`);

  // Prevent Mercury websocket INVALID_STATE_ERROR from crashing Node (see
  // src/bot/mercuryGuard.js for details). Must be installed before events flow.
  installMercuryGuard(Framework);

  Framework.on("initialized", () => {
    logger('bot', "Webex Framework is all fired up! [Press CTRL-C to quit]");
  });

  Framework.on('spawn', (bot, id) => {
    // Optional detailed logging
    // logger('bot', `Bot spawned in room: ${bot.room?.title || id}`);
  });

  Framework.on('error', (err) => {
    if (err.message && !err.message.includes('Could not find a room')) {
      logger('bot:error', err.message, 'error');
    }
  });

  // NEW: Handle Adaptive Card submissions (e.g. proposal approvals)
  Framework.on('attachmentAction', async (bot, trigger) => {
    try {
      const actionType = trigger?.attachmentAction?.inputs?.action;
      if (
        actionType === 'approveInvoice' ||
        actionType === 'rejectInvoice' ||
        actionType === 'dismissInvoiceCard'
      ) {
        await invoiceApprovalService.handleInvoiceApprovalSubmit(bot, trigger, { db });
        return;
      }
      if (actionType === 'createWorkOrder' || actionType === 'dismissCreateWoCard') {
        await workOrderCreateService.handleCreateWorkOrderSubmit(bot, trigger);
        return;
      }
      await approvalService.handleApprovalSubmit(bot, trigger, { db });
    } catch (e) {
      logger('bot:approvalAction', `Handler error: ${e.message}`, 'error');
      try {
        await bot.say(`⚠️ Approval action failed: ${e.message}. Please try again or approve in ServiceChannel.`);
      } catch (sayErr) {
        logger('bot:approvalAction', `Could not reply in room (Mercury may be disconnected): ${sayErr.message}`, 'warn');
      }
    }
  });

  // Command registration - single .hears handler
  Framework.hears(/.*/, async (bot, trigger) => {
    try {
      let rawText = trigger.text?.trim() || '';

      // Strip common bot mention patterns
      const botMentionPatterns = [
        /^ServiceChannel\s+/i,
        /^@ServiceChannel\s+/i,
        /^ServiceChannel@webex\.bot\s+/i,
      ];

      for (const pattern of botMentionPatterns) {
        rawText = rawText.replace(pattern, '').trim();
      }

      const parts = rawText.split(/\s+/);
      const command = parts[0]?.toLowerCase().replace(/^\//, '') || '';
      const args = parts.slice(1);

      // Attach args for command handlers that expect them
      trigger.args = args;

      switch (command) {
        case 'test':
          await bot.say(`[TEST] Echo: "${rawText}"`);
          break;
        case 'help':
          await handleHelp(bot, trigger);
          break;
        case 'avstatus':
          await handleAvStatus(bot, trigger);
          break;
        case 'wosummary':
          await handleWoSummary(bot, trigger);
          break;
        case 'woattachments':
          await handleWoAttachments(bot, trigger);
          break;
        case 'wohistory':
          await handleWoHistory(bot, trigger);
          break;
        case 'woapprove':
        case 'approve':
        case 'requestapproval':
          await handleWoApprove(bot, trigger);
          break;
        case 'confirmed':
          await handleWoConfirmed(bot, trigger);
          break;
        case 'addnote':
          await handleWoAddNote(bot, trigger);
          break;
        case 'attach':
        case 'upload':
          await handleWoAttach(bot, trigger);
          break;
        case 'trackstatus':
          await handleWoTrackStatus(bot, trigger);
          break;
        case 'tracktest':
          await handleWoTrackTest(bot, trigger);
          break;
        case 'createwo':
          await handleWoCreate(bot, trigger);
          break;
        default:
          await handleUnknown(bot, trigger);
          break;
      }
    } catch (e) {
      logger('bot:command', `Command handler error: ${e.message}`, 'error');
      try {
        await bot.say(`⚠️ Command failed: ${e.message}`);
      } catch (_) {
        logger('bot:command', 'Could not send error reply (Mercury may be disconnected)', 'warn');
      }
    }
  }, null, 1);

  return Framework;
}

/**
 * Graceful shutdown helper for the bot framework.
 */
export async function stopBot(Framework) {
  if (Framework && typeof Framework.stop === 'function') {
    try {
      await Framework.stop();
      logger('bot', 'Framework stopped cleanly');
    } catch (err) {
      logger('bot:error', `Error stopping Framework: ${err.message}`, 'error');
    }
  }
}

export default { initializeBot, stopBot };