// Lightweight text-to-schedule detector. Runs on agent replies (and user
// prompts) to surface a "Schedule this?" chip when the conversation has
// time-shaped language. Cheap regex pass, no LLM call. Returns the best
// matching preset or null. Conservative on purpose: a false positive
// shows a quietly-dismissable chip; a false negative just means the user
// uses the regular Schedule button.

import type { ScheduleConfig } from '@/shared/state/workflowsSlice';
import { defaultSchedule } from './scheduleUtils';

export interface DetectedSchedule {
  schedule: ScheduleConfig;
  presetLabel: string;
}

const HOUR_WORDS: Record<string, number> = {
  morning: 9, noon: 12, afternoon: 14, evening: 18, night: 21, midnight: 0,
};

// Match "9am" / "9 a.m." / "10:30 PM" / "at 7am" — but ONLY when there's
// either an explicit am/pm suffix or an "at " prefix. Plain digits with
// no time context ("3 new messages", "May 16", "$50 offer") used to slip
// through and we'd misread them as the schedule hour. Anchoring on
// `(am|pm)` OR `at ` blocks that.
const HOUR_RE = /\b(?:at\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm|a\.m\.|p\.m\.)?|(\d{1,2})(?::(\d{2}))?\s*(am|pm|a\.m\.|p\.m\.))\b/i;

const DAY_RE = /\b(sun|mon|tue|wed|thu|fri|sat)(?:day)?s?\b/gi;
const DAY_MAP: Record<string, number> = { sun: 0, mon: 1, tue: 2, wed: 3, thu: 4, fri: 5, sat: 6 };

export function detectSchedule(text: string): DetectedSchedule | null {
  if (!text) return null;
  const t = text.toLowerCase();
  // Require either an explicit frequency keyword or a clear weekday +
  // time pattern. Avoids false positives on stray "tomorrow at 9."
  const isDaily = /\b(every ?day|each day|daily)\b/.test(t);
  const isWeekdays = /\b(weekdays?|each weekday|every weekday|mon(?:day)?\s*(?:to|-|through|–)\s*fri(?:day)?)\b/.test(t);
  const isWeekly = /\b(every week|weekly|each week|once a week)\b/.test(t);
  const isMonthly = /\b(every month|monthly|each month|once a month)\b/.test(t);
  const dayMatches = Array.from(t.matchAll(DAY_RE)).map((m) => DAY_MAP[m[1].toLowerCase().slice(0, 3)]);
  const hasExplicitDays = dayMatches.length > 0;
  if (!isDaily && !isWeekdays && !isWeekly && !isMonthly && !hasExplicitDays) return null;

  // Extract hour:minute.
  let hour = 9;
  let minute = 0;
  let presetTimeWord: string | null = null;
  for (const word of Object.keys(HOUR_WORDS)) {
    if (t.includes(word)) { hour = HOUR_WORDS[word]; presetTimeWord = word; break; }
  }
  const hm = t.match(HOUR_RE);
  if (hm) {
    // The two branches of HOUR_RE give us hour/minute/ampm in either
    // capture group 1-3 (the "at H" branch) or 4-6 (the "Ham/pm" branch).
    const rawStr = hm[1] || hm[4];
    const minStr = hm[2] || hm[5];
    const ampm = (hm[3] || hm[6] || '').toLowerCase();
    const raw = rawStr ? parseInt(rawStr, 10) : NaN;
    const m = minStr ? parseInt(minStr, 10) : 0;
    let h = raw;
    if (ampm.startsWith('p') && h < 12) h += 12;
    if (ampm.startsWith('a') && h === 12) h = 0;
    if (Number.isFinite(h) && h >= 0 && h < 24) {
      if (!presetTimeWord) { hour = h; minute = m; }
    }
  }

  const base = defaultSchedule();
  if (isMonthly) {
    return {
      schedule: { ...base, enabled: true, repeat_unit: 'month', repeat_every: 1, hour, minute },
      presetLabel: `Every month at ${formatHour(hour, minute)}`,
    };
  }
  if (isWeekdays) {
    return {
      schedule: { ...base, enabled: true, repeat_unit: 'week', repeat_every: 1, on_days: [1, 2, 3, 4, 5], hour, minute },
      presetLabel: `Weekdays at ${formatHour(hour, minute)}`,
    };
  }
  if (isDaily) {
    return {
      schedule: { ...base, enabled: true, repeat_unit: 'day', repeat_every: 1, hour, minute },
      presetLabel: `Every day at ${formatHour(hour, minute)}`,
    };
  }
  if (hasExplicitDays || isWeekly) {
    const days = Array.from(new Set(dayMatches.length ? dayMatches : [new Date().getDay()]));
    days.sort();
    const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    const label = days.length === 1 ? `Every ${dayNames[days[0]]} at ${formatHour(hour, minute)}` : `${days.map((d) => dayNames[d]).join('/')} at ${formatHour(hour, minute)}`;
    return {
      schedule: { ...base, enabled: true, repeat_unit: 'week', repeat_every: 1, on_days: days, hour, minute },
      presetLabel: label,
    };
  }
  return null;
}

function formatHour(h: number, m: number): string {
  const suffix = h < 12 ? 'am' : 'pm';
  const h12 = ((h + 11) % 12) + 1;
  return m === 0 ? `${h12}${suffix}` : `${h12}:${String(m).padStart(2, '0')}${suffix}`;
}
