import type { Database } from 'bun:sqlite';
import { isGroupId } from '../utils/whatsapp';
import { toIsoUTC } from '../utils/datetime';
import { AllowedGroups } from '../services/allowed-groups';
import { ResponseQueue } from '../services/response-queue';

// ── Env helpers ──────────────────────────────────────────────

const DEFAULT_TTL_DAYS = 14;

function isEnvFlagEnabled(envKey: string, defaultVal = false): boolean {
  const raw = String(process.env[envKey] || String(defaultVal)).toLowerCase();
  return ['true', '1', 'yes', 'on'].includes(raw);
}

function envNumber(envKey: string, fallback: number): number {
  const n = Number(process.env[envKey]);
  return Number.isFinite(n) && n > 0 ? n : fallback;
}

function envString(envKey: string, fallback: string): string {
  const v = (process.env[envKey] ?? '').trim();
  return v || fallback;
}

// ── DB helpers ───────────────────────────────────────────────

interface TaskOrigin {
  chat_id?: string;
  message_id?: string;
  created_at?: string;
  participant?: string | null;
  from_me?: number | boolean | null;
}

/** Query con fallback: si la columna participant/from_me no existe aún (schema antiguo), reintenta sin ellas. */
function getTaskOrigin(db: Database, taskId: number): TaskOrigin | null {
  try {
    const row = db.prepare(`
      SELECT chat_id, message_id, created_at, participant, from_me
      FROM task_origins WHERE task_id = ?
    `).get(taskId) as TaskOrigin | undefined;
    return row ?? null;
  } catch {
    const row = db.prepare(`
      SELECT chat_id, message_id, created_at
      FROM task_origins WHERE task_id = ?
    `).get(taskId) as TaskOrigin | undefined;
    return row ?? null;
  }
}

// ── Eligibility checks ───────────────────────────────────────

function isScopeEligible(chatId: string): boolean {
  const scope = envString('REACTIONS_SCOPE', 'groups').toLowerCase();
  return scope === 'all' || isGroupId(chatId);
}

function isWithinTtl(origin: TaskOrigin): boolean {
  const ttlDays = envNumber('REACTIONS_TTL_DAYS', DEFAULT_TTL_DAYS);
  const maxAgeMs = ttlDays * 24 * 60 * 60 * 1000;

  const createdMs = Date.parse(toIsoUTC(String(origin.created_at || '')));
  return Number.isFinite(createdMs) && (Date.now() - createdMs <= maxAgeMs);
}

function isGatingAllowed(chatId: string): boolean {
  if (!isGroupId(chatId)) return true;
  const mode = envString('GROUP_GATING_MODE', 'off').toLowerCase();
  if (mode !== 'enforce') return true;
  try {
    return AllowedGroups.isAllowed(chatId);
  } catch {
    return true; // fail open
  }
}

// ── Reaction options builder ─────────────────────────────────

function buildReactionOpts(origin: TaskOrigin): { participant?: string; fromMe?: boolean } {
  const participant = origin.participant ? String(origin.participant) : undefined;
  const fromMe = (origin.from_me === 1 || origin.from_me === true) ? true : undefined;

  const opts: { participant?: string; fromMe?: boolean } = {};
  if (participant !== undefined) opts.participant = participant;
  if (typeof fromMe === 'boolean') opts.fromMe = fromMe;
  return Object.keys(opts).length > 0 ? opts : {};
}

// ── Public API ───────────────────────────────────────────────

/**
 * Publica una reacción ✅ al mensaje origen de la tarea si:
 * - REACTIONS_ENABLED está activado,
 * - scope permite (all o solo grupos),
 * - está dentro del TTL configurado (por defecto 14 días),
 * - y pasa el gating de grupos en modo 'enforce'.
 *
 * No lanza errores (no debe bloquear el flujo de completado).
 */
export function enqueueCompletionReactionIfEligible(db: Database, taskId: number): void {
  try {
    if (!isEnvFlagEnabled('REACTIONS_ENABLED')) return;

    const origin = getTaskOrigin(db, taskId);
    if (!origin?.chat_id || !origin.message_id) return;

    const chatId = String(origin.chat_id);
    if (!isScopeEligible(chatId)) return;
    if (!isWithinTtl(origin)) return;
    if (!isGatingAllowed(chatId)) return;

    ResponseQueue.enqueueReaction(
      chatId,
      String(origin.message_id),
      '✅',
      buildReactionOpts(origin),
    ).catch(() => {});
  } catch {
    // no-op: nunca bloquear el flujo de completado
  }
}
