/**
 * Utilidades compartidas para handlers de comandos (Etapa 1).
 * Aún no se usan desde CommandService; servirán en etapas siguientes.
 */

import { TaskService } from '../../tasks/service';
import { GroupSyncService } from '../group-sync';

export const ACTION_ALIASES: Record<string, string> = {
  'n': 'nueva',
  'nueva': 'nueva',
  'crear': 'nueva',
  '+': 'nueva',
  'ver': 'ver',
  'mostrar': 'ver',
  'listar': 'ver',
  'ls': 'ver',
  'mias': 'ver',
  'mías': 'ver',
  'todas': 'ver',
  'todos': 'ver',
  'x': 'completar',
  'hecho': 'completar',
  'completar': 'completar',
  'done': 'completar',
  'tomar': 'tomar',
  'claim': 'tomar',
  'asumir': 'tomar',
  'asumo': 'tomar',
  'soltar': 'soltar',
  'unassign': 'soltar',
  'dejar': 'soltar',
  'liberar': 'soltar',
  'renunciar': 'soltar',
  'ayuda': 'ayuda',
  'help': 'ayuda',
  'info': 'ayuda',
  '?': 'ayuda',
  'config': 'configurar',
  'configurar': 'configurar',
  'web': 'web'
};

export const SCOPE_ALIASES: Record<string, 'mis' | 'todos'> = {
  'todo': 'todos',
  'todos': 'todos',
  'todas': 'todos',
  'mis': 'mis',
  'mias': 'mis',
  'mías': 'mis',
  'yo': 'mis'
};

export const CTA_HELP = 'ℹ️ Tus tareas: `/t mias` · Todas: `/t todas` · Info: `/t info` · Web: `/t web`';

/**
 * Formatea un Date a YYYY-MM-DD respetando TZ (por defecto Europe/Madrid).
 */
export function ymdInTZ(d: Date, tz?: string): string {
  const TZ = (tz && tz.trim()) || (process.env.TZ && process.env.TZ.trim()) || 'Europe/Madrid';
  const parts = new Intl.DateTimeFormat('en-GB', {
    timeZone: TZ,
    year: 'numeric',
    month: '2-digit',
    day: '2-digit'
  }).formatToParts(d);
  const get = (t: string) => parts.find(p => p.type === t)?.value || '';
  return `${get('year')}-${get('month')}-${get('day')}`;
}

export function todayYMD(tz?: string): string {
  return ymdInTZ(new Date(), tz);
}

/**
 * Parsea múltiples IDs desde tokens, deduplica, y aplica límite.
 */
export function parseMultipleIds(tokens: string[], max: number = 10): { ids: number[]; truncated: boolean } {
  const raw = (tokens || []).join(' ').trim();
  const all = raw
    ? raw
        .split(/[,\s]+/)
        .map(t => t.trim())
        .filter(Boolean)
        .map(t => parseInt(t, 10))
        .filter(n => Number.isFinite(n) && n > 0)
    : [];
  const dedup: number[] = [];
  const seen = new Set<number>();
  for (const n of all) {
    if (!seen.has(n)) {
      seen.add(n);
      dedup.push(n);
    }
  }
  const truncated = dedup.length > max;
  const ids = dedup.slice(0, max);
  return { ids, truncated };
}

/**
 * Resuelve un ID de entrada (display_code) a task.id si está activa.
 */
export function resolveTaskIdFromInput(n: number): number | null {
  const byCode = TaskService.getActiveTaskByDisplayCode(n);
  return byCode ? byCode.id : null;
}

/**
 * Aplica la política de membresía para acciones sobre una tarea.
 * Devuelve true si el usuario está permitido según flags/env.
 */
export function enforceMembership(sender: string, task: { group_id?: string | null }, enforceFlag?: boolean): boolean {
  const enforce =
    typeof enforceFlag === 'boolean'
      ? enforceFlag
      : String(process.env.GROUP_MEMBERS_ENFORCE || '').toLowerCase() === 'true';

  const gid = task?.group_id || null;
  if (!gid) return true; // tareas personales no requieren membresía
  if (!enforce) return true;
  if (!GroupSyncService.isSnapshotFresh(gid)) return true;

  return GroupSyncService.isUserActiveInGroup(sender, gid);
}
