import type { Messages } from "@/shared/i18n/config";
import type { Locale } from "@/shared/i18n/config";
import type { TicketLastMessage, TicketMessage } from "@/domain/entities/ticket";

const BCP47: Record<Locale, string> = { fr: "fr-FR", en: "en-US" };

// Consecutive messages from the same author within this window share one group.
const GROUP_WINDOW_MS = 5 * 60 * 1000;

/** The API mixes ISO dates and "Y-m-d H:i": parse both the same way in every browser. */
export function parseDate(value: string): Date {
  return new Date(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}/.test(value) ? value.replace(" ", "T") : value);
}

const startOfDay = (date: Date) => new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();

export function isSameDay(a: string, b: string): boolean {
  return startOfDay(parseDate(a)) === startOfDay(parseDate(b));
}

export function formatClock(iso: string, locale: Locale): string {
  return parseDate(iso).toLocaleTimeString(BCP47[locale], { hour: "2-digit", minute: "2-digit" });
}

/** Compact time for the conversation list: 14:32, Hier, lun., 12/09. */
export function formatListTime(iso: string, t: Messages, locale: Locale): string {
  const date = parseDate(iso);
  const days = Math.round((startOfDay(new Date()) - startOfDay(date)) / 86_400_000);
  if (days === 0) return formatClock(iso, locale);
  if (days === 1) return t.support.thread.yesterday;
  if (days < 7) return date.toLocaleDateString(BCP47[locale], { weekday: "short" });
  return date.toLocaleDateString(BCP47[locale], { day: "2-digit", month: "2-digit" });
}

export function formatDayLabel(iso: string, t: Messages, locale: Locale): string {
  const date = parseDate(iso);
  const days = Math.round((startOfDay(new Date()) - startOfDay(date)) / 86_400_000);
  if (days === 0) return t.support.thread.today;
  if (days === 1) return t.support.thread.yesterday;
  const label = date.toLocaleDateString(BCP47[locale], {
    weekday: "long",
    day: "numeric",
    month: "long",
    ...(date.getFullYear() === new Date().getFullYear() ? {} : { year: "numeric" }),
  });
  return label.charAt(0).toUpperCase() + label.slice(1);
}

/** "2 min", "3 h", "2 j" since a date, for "awaiting reply" badges. */
export function formatWaiting(iso: string, locale: Locale): string {
  const minutes = Math.max(1, Math.round((Date.now() - parseDate(iso).getTime()) / 60_000));
  const format = (value: number, unit: Intl.NumberFormatOptions["unit"]) =>
    new Intl.NumberFormat(BCP47[locale], { style: "unit", unit, unitDisplay: "narrow" }).format(value);
  if (minutes < 60) return format(minutes, "minute");
  if (minutes < 60 * 24) return format(Math.round(minutes / 60), "hour");
  return format(Math.round(minutes / (60 * 24)), "day");
}

export function lastMessagePreview(message: TicketLastMessage | null, currentUserId: number | undefined, t: Messages): string {
  if (!message) return "";
  const content =
    message.body?.trim() ||
    (message.attachment_type === "audio"
      ? `🎤 ${t.support.voiceMessage}`
      : message.attachment_type === "image"
        ? `📷 ${t.support.image}`
        : message.attachment_type
          ? `📎 ${t.support.file}`
          : "");

  if (message.kind === "internal") return `${t.support.note} · ${content}`;
  if (message.from_dadycar) {
    const who = message.author_id === currentUserId ? t.support.you : message.author_name;
    return who ? t.support.previewFrom(who, content) : content;
  }
  return content;
}

export function isSameGroup(a: TicketMessage | undefined, b: TicketMessage | undefined): boolean {
  return (
    !!a && !!b &&
    a.author?.id === b.author?.id &&
    a.kind === b.kind &&
    isSameDay(a.created_at, b.created_at) &&
    Math.abs(parseDate(b.created_at).getTime() - parseDate(a.created_at).getTime()) < GROUP_WINDOW_MS
  );
}

export function formatDuration(seconds: number): string {
  const safe = Number.isFinite(seconds) && seconds > 0 ? Math.floor(seconds) : 0;
  return `${Math.floor(safe / 60)}:${String(safe % 60).padStart(2, "0")}`;
}

/** Voice messages recorded in the apps carry their length: voice-message-<time>-<seconds>s[-w<levels>].<ext> */
export function durationFromFileName(name?: string | null): number {
  return Number(name?.match(/-(\d+)s(?:-w[0-9a-z]+)?\.[a-z0-9]+$/i)?.[1] ?? 0);
}

export function isAudioAttachment(attachment: { is_audio?: boolean; mime_type?: string | null; uploaded_file_name?: string | null }): boolean {
  if (attachment.is_audio) return true;
  if (attachment.mime_type?.startsWith("audio/")) return true;
  return /^voice-message.*\.(weba|webm|ogg|oga|opus|m4a|mp3|wav)$/i.test(attachment.uploaded_file_name ?? "");
}
