export function parseNueva(message: string, _mentionsNormalized: string[]): {
  action: string;
  description: string;
  dueDate: string | null;
  selfAssign: boolean;
} {
  const parts = (message || '').trim().split(/\s+/);
  const action = (parts[1] || '').toLowerCase();

  // Zona horaria configurable (por defecto Europe/Madrid)
  const TZ = process.env.TZ && process.env.TZ.trim() ? process.env.TZ : 'Europe/Madrid';

  // Utilidades locales para operar con fechas en la TZ elegida sin depender del huso del host
  const ymdFromDateInTZ = (d: Date): string => {
    const fmt = new Intl.DateTimeFormat('es-ES', {
      timeZone: TZ,
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
    }).formatToParts(d);
    const get = (t: string) => fmt.find(p => p.type === t)?.value || '';
    return `${get('year')}-${get('month')}-${get('day')}`;
  };

  const addDaysToYMD = (ymd: string, days: number): string => {
    const [Y, M, D] = ymd.split('-').map(n => parseInt(n, 10));
    const base = new Date(Date.UTC(Y, (M || 1) - 1, D || 1));
    base.setUTCDate(base.getUTCDate() + days);
    return ymdFromDateInTZ(base);
  };

  const todayYMD = ymdFromDateInTZ(new Date());

  // Helpers para validar y normalizar fechas explícitas
  const isLeap = (y: number) => (y % 4 === 0 && y % 100 !== 0) || (y % 400 === 0);
  const daysInMonth = (y: number, m: number) => {
    if (m === 2) return isLeap(y) ? 29 : 28;
    return [31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m - 1];
  };
  const isValidYMD = (ymd: string): boolean => {
    const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(ymd);
    if (!m) return false;
    const Y = parseInt(m[1], 10);
    const MM = parseInt(m[2], 10);
    const DD = parseInt(m[3], 10);
    if (MM < 1 || MM > 12) return false;
    const dim = daysInMonth(Y, MM);
    if (!dim || DD < 1 || DD > dim) return false;
    return true;
  };
  const normalizeDateToken = (t: string): string | null => {
    // YYYY-MM-DD
    if (/^\d{4}-\d{2}-\d{2}$/.test(t)) {
      return isValidYMD(t) ? t : null;
    }
    // YY-MM-DD -> 20YY-MM-DD
    const m = /^(\d{2})-(\d{2})-(\d{2})$/.exec(t);
    if (m) {
      const yy = parseInt(m[1], 10);
      const mm = m[2];
      const dd = m[3];
      const yyyy = 2000 + yy;
      const ymd = `${String(yyyy)}-${mm}-${dd}`;
      return isValidYMD(ymd) ? ymd : null;
    }
    return null;
  };

  type DateCandidate = { index: number; ymd: string };
  const dateCandidates: DateCandidate[] = [];
  const dateTokenIndexes = new Set<number>();
  const selfTokenIndexes = new Set<number>();
  let selfAssign = false;

  for (let i = 2; i < parts.length; i++) {
    // Normalizar token: minúsculas y sin puntuación adyacente simple
    const raw = parts[i];
    const low = raw.toLowerCase().replace(/^[([{¿¡"']+/, '').replace(/[.,;:!?)\]}¿¡"'']+$/, '');

    // Fecha explícita en formatos permitidos: YYYY-MM-DD o YY-MM-DD (expandido a 20YY)
    {
      const norm = normalizeDateToken(low);
      if (norm && norm >= todayYMD) {
        dateCandidates.push({ index: i, ymd: norm });
        dateTokenIndexes.add(i);
        continue;
      }
    }

    // Tokens naturales "hoy"/"mañana" (con o sin acento)
    if (low === 'hoy') {
      dateCandidates.push({ index: i, ymd: todayYMD });
      dateTokenIndexes.add(i);
      continue;
    }
    if (low === 'mañana' || low === 'manana') {
      dateCandidates.push({ index: i, ymd: addDaysToYMD(todayYMD, 1) });
      dateTokenIndexes.add(i);
      continue;
    }

    // Autoasignación: detectar 'yo' o '@yo' como palabra aislada (insensible a mayúsculas; ignora puntuación simple)
    if (low === 'yo' || low === '@yo') {
      selfAssign = true;
      selfTokenIndexes.add(i);
      continue;
    }
  }

  const dueDate = dateCandidates.length > 0
    ? dateCandidates[dateCandidates.length - 1].ymd
    : null;

  const isMentionToken = (token: string) => token.startsWith('@');

  const descriptionTokens: string[] = [];
  for (let i = 2; i < parts.length; i++) {
    if (dateTokenIndexes.has(i)) continue;
    if (selfTokenIndexes.has(i)) continue;
    const token = parts[i];
    if (isMentionToken(token)) continue;
    descriptionTokens.push(token);
  }

  const description = descriptionTokens.join(' ').trim();

  return { action, description, dueDate, selfAssign };
}
