/**
 * Upload Webex message files to a ServiceChannel work order.
 */

import { uploadWorkOrderAttachment } from '../integrations/serviceChannel/attachments.js';
import { addWorkOrderNote } from '../integrations/serviceChannel/client.js';
import { tryClaimBotMessage } from '../db/botMessageDedup.js';
import {
  markAttachmentPosted,
  registerUploadEchoSuppress,
} from '../db/uploadEchoSuppress.js';
import { resolveDisplayName, resolveWoRoomContext } from '../utils/woRoomContext.js';
import { prepareScUpload } from '../utils/prepareScUpload.js';
import { logger } from '../utils/logger.js';

const DEFAULT_MAX_BYTES = 25 * 1024 * 1024;

function getMaxUploadBytes() {
  const raw = process.env.SC_UPLOAD_MAX_BYTES;
  if (raw == null || raw === '') return DEFAULT_MAX_BYTES;
  const n = Number(raw);
  return Number.isFinite(n) && n > 0 ? n : DEFAULT_MAX_BYTES;
}

async function resolveFileUrls(botClient, trigger) {
  let files = trigger.message?.files;
  if (Array.isArray(files) && files.length > 0) return files;

  const messageId = trigger.message?.id;
  if (!messageId) return [];

  try {
    const msg = await botClient.getMessage(messageId);
    files = msg?.files;
    return Array.isArray(files) ? files : [];
  } catch (err) {
    logger('wo:upload', `Failed to refetch message ${messageId}: ${err.message}`, 'warn');
    return [];
  }
}

/**
 * @returns {Promise<
 *   | { ok: true, uploaded: Array<{ name: string, scAttachmentId: number|null }>, captionPosted: boolean }
 *   | { ok: false, error: string }
 * >}
 */
export async function uploadFilesFromTrigger({ db, botClient, trigger, caption = '' }) {
  const roomId = trigger.message?.roomId;
  const isGroup = trigger.message?.roomType === 'group';

  const ctx = await resolveWoRoomContext({ db, botClient, roomId, isGroup });
  if (!ctx.ok) {
    return { ok: false, error: ctx.error };
  }

  const messageId = trigger.message?.id;
  try {
    const claimed = await tryClaimBotMessage(db, messageId, 'attach');
    if (!claimed) {
      logger('wo:upload', `Skipped duplicate /attach for message ${messageId}`, 'info');
      return { ok: false, error: null };
    }
  } catch (err) {
    logger('wo:upload', `Dedup check failed: ${err.message}`, 'warn');
  }

  const fileUrls = await resolveFileUrls(botClient, trigger);
  if (!fileUrls.length) {
    return {
      ok: false,
      error: 'Attach a file to your message. Usage: `/attach [optional caption]` or `/upload [optional caption]` (WO space only).',
    };
  }

  const maxBytes = getMaxUploadBytes();
  const uploaded = [];

  for (let i = 0; i < fileUrls.length; i++) {
    const fileUrl = fileUrls[i];
    const { buffer, contentType, fileName } = await botClient.downloadMessageFile(fileUrl);

    if (buffer.length > maxBytes) {
      const limitMb = Math.round(maxBytes / (1024 * 1024));
      throw new Error(`File ${fileName} exceeds the ${limitMb} MB upload limit.`);
    }

    const prepared = await prepareScUpload(buffer, fileName, contentType);

    await registerUploadEchoSuppress(db, ctx.workOrderId, {
      fileName: prepared.fileName,
    });

    const result = await uploadWorkOrderAttachment(
      ctx.workOrderId,
      prepared.buffer,
      prepared.fileName,
      prepared.contentType
    );

    uploaded.push({
      name: result.name || prepared.fileName,
      scAttachmentId: result.id ?? null,
    });

    if (result.id != null) {
      await registerUploadEchoSuppress(db, ctx.workOrderId, {
        attachmentId: result.id,
        fileName: result.name || prepared.fileName,
      });
      await markAttachmentPosted(db, ctx.workOrderId, result.id);
    }
  }

  let captionPosted = false;
  const trimmedCaption = String(caption || '').trim();
  if (trimmedCaption) {
    const displayName = await resolveDisplayName(botClient, trigger.personId);
    const scNote = `${displayName}: ${trimmedCaption}`;
    await registerUploadEchoSuppress(db, ctx.workOrderId, { noteText: scNote });
    await addWorkOrderNote(ctx.workOrderId, scNote);
    captionPosted = true;
    logger('wo:upload', `Posted caption note to SC WO ${ctx.workOrderId}`);
  }

  logger(
    'wo:upload',
    `Uploaded ${uploaded.length} file(s) to SC WO ${ctx.workOrderId} by ${trigger.personId || 'unknown'}`
  );

  return { ok: true, uploaded, captionPosted };
}

export default { uploadFilesFromTrigger };
