'use strict';

const os = require('os');
const { getAgentConfig, isConfigured } = require('../../agent/agentConfig');
const { loadState } = require('../../agent/agentState');
const operationalQueue = require('../../agent/syncQueue');
const operationalScheduler = require('../../agent/syncScheduler');
const offlineSync = require('../sync');
const multibranch = require('../multibranch-sync');
const multibranchStorage = require('../multibranch-sync/storage');
const deadLetters = require('../multibranch-sync/dead-letter');
const realtime = require('../../agent/cloudRealtimeClient');

let billingCache = { at: 0, value: null };
const SYNC_MONITOR_TIMEOUT_MS = Math.max(250, Number(process.env.ARKHON_SYNC_MONITOR_TIMEOUT_MS) || 1500);

function withTimeout(operation, label, timeoutMs = SYNC_MONITOR_TIMEOUT_MS) {
  let timer;
  return Promise.race([
    Promise.resolve().then(operation),
    new Promise((_, reject) => {
      timer = setTimeout(() => reject(new Error(`${label}_timeout`)), timeoutMs);
      timer.unref?.();
    }),
  ]).finally(() => clearTimeout(timer));
}

function billingConnectorStatus() {
  if (billingCache.value && Date.now() - billingCache.at < 10000) return billingCache.value;
  try {
    const status = require('../billing-print').bootstrap.buildStatus();
    const readiness = status.runtimeContext?.readiness || {};
    billingCache = {
      at: Date.now(),
      value: {
        available: true,
        enabled: status.moduleEnabled === true,
        status: status.status || 'unknown',
        watcher_running: status.watcherRunning === true,
        capture_printer_ready: status.capturePrinterReady === true,
        output_printer: status.outputPrinterName || null,
        output_printer_ready: status.outputPrinterAvailable === true,
        autofactura_ready: status.canPrintQr === true,
        qr_production_ready: status.qrProductionReady === true,
        pac_configured: readiness.pacConfigured === true,
        csd_configured: readiness.csdConfigured === true,
        portal_enabled: readiness.portalEnabled === true,
        billing_environment: readiness.billingEnvironment || readiness.pacEnvironment || null,
        last_ticket_at: status.lastTicketCapturedAt || null,
        last_qr_printed_at: status.lastQrPrintedAt || null,
        blocked_cause: status.qrBlockedCause || status.basePrintBlockedCause || null,
        recommended_action: status.recommendedAction || null,
      },
    };
    return billingCache.value;
  } catch (error) {
    return {
      available: false,
      enabled: false,
      status: 'unavailable',
      blocked_cause: 'BILLING_CONNECTOR_UNAVAILABLE',
      recommended_action: String(error.message || error).slice(0, 240),
    };
  }
}

function safeIdentity(config) {
  return {
    tenant_id: config.tenantId || null,
    branch_id: config.branchId || null,
    branch_name: config.branchName || null,
    branch_code: config.branchCode || null,
    agent_id: config.agentId || null,
    agent_key_id: config.agentKeyId || null,
    source_system: config.sourceSystem || 'softrestaurant',
    version: config.agentVersion || null,
  };
}

function redactEvent(event) {
  return {
    event_id: event.event_id || null,
    entity_type: event.entity_type || null,
    entity_id: event.entity_id || null,
    operation: event.operation || null,
    status: event.status || null,
    retries: Number(event.retries || event.attempts || 0),
    created_at: event.created_at || event.createdAt || null,
    updated_at: event.updated_at || event.updatedAt || null,
    last_error: event.last_error ? String(event.last_error).slice(0, 300) : null,
  };
}

function deferredDiagnostic(name) {
  return {
    deferred: true,
    status: 'available_on_demand',
    diagnostic: name,
  };
}

async function summary(options = {}) {
  const config = getAgentConfig();
  const state = loadState();
  const includeDiagnostics = options.includeDiagnostics === true;
  const [batchQueue, generalSync] = includeDiagnostics
    ? await Promise.all([
      withTimeout(() => operationalQueue.stats(), 'operational_queue')
        .catch((error) => ({ unavailable: true, error: error.message })),
      withTimeout(() => offlineSync.service.getStatus(), 'offline_first')
        .catch((error) => ({ unavailable: true, error: error.message })),
    ])
    : [deferredDiagnostic('operational_queue'), deferredDiagnostic('offline_first')];
  const mbEnabled = includeDiagnostics
    ? multibranch.enabled()
    : (config.multibranchEnabled === true || config.multiBranchEnabled === true);
  return {
    ok: true,
    generated_at: new Date().toISOString(),
    observational: true,
    service: {
      hostname: os.hostname(),
      platform: os.platform(),
      uptime_seconds: Math.floor(process.uptime()),
      configured: isConfigured(config),
      enabled: config.enabled === true,
      mode: config.mode,
      dry_run: config.dryRun === true,
    },
    identity: safeIdentity(config),
    cloud: {
      configured: Boolean(config.cloudUrl),
      base_url: config.cloudUrl || null,
      last_heartbeat_at: state.lastHeartbeatAt || null,
      realtime: includeDiagnostics
        ? realtime.getRealtimeState()
        : deferredDiagnostic('cloud_realtime'),
    },
    operational_sync: {
      last_sync_at: state.lastSyncAt || null,
      runtime: state.syncRuntime || { status: 'unknown' },
      watermarks: state.watermarks || {},
      queue: batchQueue,
      interval_seconds: config.syncIntervalSeconds,
      batch_size: config.syncBatchSize,
    },
    offline_first: generalSync,
    multibranch: includeDiagnostics ? {
      enabled: mbEnabled,
      outbox: multibranch.outbox.stats(),
      inbox: multibranch.inbox.stats(),
      cursors: multibranchStorage.read('cursors', {}),
      dead_letters: deadLetters.list().length,
    } : {
      enabled: mbEnabled,
      ...deferredDiagnostic('multibranch_queues'),
    },
    modules: {
      softrestaurant_sync: {
        enabled: config.enabled === true,
        status: state.syncRuntime?.status || 'unknown',
        last_sync_at: state.lastSyncAt || null,
      },
      autofactura: includeDiagnostics
        ? billingConnectorStatus()
        : (billingCache.value || deferredDiagnostic('autofactura')),
    },
  };
}

async function events(options = {}) {
  const limit = Math.min(Math.max(Number(options.limit) || 100, 1), 500);
  const status = options.status ? String(options.status) : null;
  const rows = await offlineSync.queue.listEvents(status ? { status } : {});
  return {
    ok: true,
    observational: true,
    events: rows.slice(0, limit).map(redactEvent),
    dead_letters: deadLetters.list().slice(-limit),
  };
}

async function preview(entityType, limit) {
  return { ok: true, preview: await operationalScheduler.previewEntity(entityType, limit) };
}

async function retryQueues(target = 'all') {
  const config = getAgentConfig();
  if (!isConfigured(config)) {
    const error = new Error('El conector no está configurado');
    error.status = 409;
    throw error;
  }
  const result = {};
  if (target === 'all' || target === 'operational') {
    await operationalScheduler.flushQueue(config);
    result.operational = 'processed';
  }
  if (target === 'all' || target === 'offline_first') {
    result.offline_first = await offlineSync.service.flushOnce();
  }
  return { ok: true, action: 'retry', target, result, status: await summary() };
}

module.exports = { summary, events, preview, retryQueues, billingConnectorStatus, safeIdentity, redactEvent };
