import { normalizeImageUrl } from "./image-url";
import type { WeekDay } from "./week-calendar";

export type PublicTruckEvent = {
  id: string;
  eventDate: string;
  timeLabel: string;
  location: string;
  note: string;
  imageUrl: string | null;
};

export type PublicTruckRecurrence = {
  id: string;
  dayOfWeek: number;
  timeLabel: string;
  location: string;
  note: string;
  imageUrl: string | null;
  active: boolean;
};

export const WEEKDAY_LABELS = [
  "Lundi",
  "Mardi",
  "Mercredi",
  "Jeudi",
  "Vendredi",
  "Samedi",
  "Dimanche",
] as const;

const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;

export function isValidEventDate(value: string): boolean {
  if (!ISO_DATE.test(value)) return false;
  const [y, m, d] = value.split("-").map(Number);
  const date = new Date(y, m - 1, d);
  return (
    date.getFullYear() === y &&
    date.getMonth() === m - 1 &&
    date.getDate() === d
  );
}

/** 0 = lundi … 6 = dimanche (aligné sur getWeekDays). */
export function dayOfWeekMonday0(iso: string): number {
  const [y, m, d] = iso.split("-").map(Number);
  const js = new Date(y, m - 1, d).getDay();
  return js === 0 ? 6 : js - 1;
}

export function parseTruckEventPayload(
  body: Record<string, unknown>
): {
  eventDate: string;
  timeLabel: string;
  location: string;
  note: string;
  imageUrl: string | null;
} | null {
  const eventDate = String(body.eventDate ?? "").trim();
  const location = String(body.location ?? "").trim();
  const timeLabel = String(body.timeLabel ?? "").trim();
  const note = String(body.note ?? "").trim();
  const imageUrl = normalizeImageUrl(String(body.imageUrl ?? ""));

  if (!isValidEventDate(eventDate) || !location) return null;

  return { eventDate, timeLabel, location, note, imageUrl };
}

export function parseTruckRecurrencePayload(
  body: Record<string, unknown>
): {
  dayOfWeek: number;
  timeLabel: string;
  location: string;
  note: string;
  imageUrl: string | null;
  active: boolean;
} | null {
  const raw =
    typeof body.dayOfWeek === "number"
      ? body.dayOfWeek
      : Number(String(body.dayOfWeek ?? ""));
  const dayOfWeek = Number.isFinite(raw) ? Math.trunc(raw) : -1;
  const location = String(body.location ?? "").trim();
  const timeLabel = String(body.timeLabel ?? "").trim();
  const note = String(body.note ?? "").trim();
  const imageUrl = normalizeImageUrl(String(body.imageUrl ?? ""));
  const active = body.active !== false;

  if (dayOfWeek < 0 || dayOfWeek > 6 || !location) return null;

  return { dayOfWeek, timeLabel, location, note, imageUrl, active };
}

/** Fusionne événements ponctuels et occurrences récurrentes pour les jours affichés. */
export function mergeScheduleForDays(
  oneOff: PublicTruckEvent[],
  recurrences: PublicTruckRecurrence[],
  days: WeekDay[]
): PublicTruckEvent[] {
  const daySet = new Set(days.map((d) => d.date));
  const merged = oneOff.filter((e) => daySet.has(e.eventDate));

  for (const day of days) {
    const dow = dayOfWeekMonday0(day.date);
    for (const r of recurrences) {
      if (!r.active || r.dayOfWeek !== dow) continue;
      merged.push({
        id: `recur-${r.id}-${day.date}`,
        eventDate: day.date,
        timeLabel: r.timeLabel,
        location: r.location,
        note: r.note,
        imageUrl: r.imageUrl,
      });
    }
  }

  merged.sort((a, b) => {
    if (a.eventDate !== b.eventDate) return a.eventDate.localeCompare(b.eventDate);
    return a.location.localeCompare(b.location);
  });

  return merged;
}
