"use client";
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { toZonedTime } from "date-fns-tz";
import { cn } from "@open-mercato/shared/lib/utils";
import { useT } from "@open-mercato/shared/lib/i18n/context";
import { readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("customers");
const USER_TIMEZONE = (() => {
  try {
    return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
  } catch {
    return "UTC";
  }
})();
function toLocalZonedDate(value) {
  return toZonedTime(value, USER_TIMEZONE);
}
const VISIBLE_DAYS = 5;
const BUSYNESS_SLOTS = 10;
const SLOT_START_HOUR = 7;
const SLOT_END_HOUR = 22;
const DAY_LABEL_KEYS = [
  [0, "customers.calendar.day.sun", "SUN"],
  [1, "customers.calendar.day.mon", "MON"],
  [2, "customers.calendar.day.tue", "TUE"],
  [3, "customers.calendar.day.wed", "WED"],
  [4, "customers.calendar.day.thu", "THU"],
  [5, "customers.calendar.day.fri", "FRI"],
  [6, "customers.calendar.day.sat", "SAT"]
];
const MONTH_KEYS = [
  [0, "customers.calendar.month.january", "January"],
  [1, "customers.calendar.month.february", "February"],
  [2, "customers.calendar.month.march", "March"],
  [3, "customers.calendar.month.april", "April"],
  [4, "customers.calendar.month.may", "May"],
  [5, "customers.calendar.month.june", "June"],
  [6, "customers.calendar.month.july", "July"],
  [7, "customers.calendar.month.august", "August"],
  [8, "customers.calendar.month.september", "September"],
  [9, "customers.calendar.month.october", "October"],
  [10, "customers.calendar.month.november", "November"],
  [11, "customers.calendar.month.december", "December"]
];
function startOfDay(date) {
  const next = new Date(date);
  next.setHours(0, 0, 0, 0);
  return next;
}
function endOfDay(date) {
  const next = new Date(date);
  next.setHours(23, 59, 59, 999);
  return next;
}
function isSameDay(a, b) {
  return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
}
function isWeekend(date) {
  const day = date.getDay();
  return day === 0 || day === 6;
}
function addDays(date, delta) {
  const next = new Date(date);
  next.setDate(date.getDate() + delta);
  return next;
}
function buildVisibleDays(anchor) {
  const start = startOfDay(anchor);
  return Array.from({ length: VISIBLE_DAYS }, (_, index) => addDays(start, index));
}
function anchorCenteredOn(focalDate) {
  return startOfDay(addDays(focalDate, -Math.floor(VISIBLE_DAYS / 2)));
}
function emptyBusyness() {
  return {
    totalMinutes: 0,
    eventCount: 0,
    slots: Array(BUSYNESS_SLOTS).fill("empty")
  };
}
function computeDayBusyness(events, day) {
  if (events.length === 0) return emptyBusyness();
  const dayStart = startOfDay(day).getTime();
  const slotMs = (SLOT_END_HOUR - SLOT_START_HOUR) * 60 * 60 * 1e3 / BUSYNESS_SLOTS;
  const slotMinutes = slotMs / 6e4;
  const slotCounts = Array(BUSYNESS_SLOTS).fill(0);
  const slotMinutesUsed = Array(BUSYNESS_SLOTS).fill(0);
  let totalMinutes = 0;
  let eventCount = 0;
  for (const event of events) {
    const startIso = event.scheduledAt ?? event.occurredAt ?? event.createdAt;
    if (!startIso) continue;
    const start = new Date(startIso);
    if (Number.isNaN(start.getTime())) continue;
    const localStart = toLocalZonedDate(startIso);
    if (!isSameDay(localStart, day)) continue;
    eventCount += 1;
    const durationMinutes = typeof event.duration === "number" && event.duration > 0 ? event.duration : 30;
    totalMinutes += durationMinutes;
    const eventStartMs = start.getTime();
    const eventEndMs = eventStartMs + durationMinutes * 6e4;
    const slotsStartMs = dayStart + SLOT_START_HOUR * 60 * 60 * 1e3;
    for (let slot = 0; slot < BUSYNESS_SLOTS; slot += 1) {
      const slotStart = slotsStartMs + slot * slotMs;
      const slotEnd = slotStart + slotMs;
      const overlapStart = Math.max(slotStart, eventStartMs);
      const overlapEnd = Math.min(slotEnd, eventEndMs);
      const overlapMinutes = Math.max(0, (overlapEnd - overlapStart) / 6e4);
      if (overlapMinutes <= 0) continue;
      slotCounts[slot] += 1;
      slotMinutesUsed[slot] += overlapMinutes;
    }
  }
  const slots = slotCounts.map((count, index) => {
    if (count === 0) return "empty";
    if (count > 1) return "conflict";
    const used = slotMinutesUsed[index];
    if (used >= slotMinutes * 0.5) return "full";
    return "partial";
  });
  return { totalMinutes, eventCount, slots };
}
function formatBusyLabel(busy, t) {
  if (busy.eventCount === 0) return "";
  const durationLabel = busy.totalMinutes < 60 ? t("customers.activities.calendar.minutesShort", "{minutes}m", { minutes: Math.max(Math.round(busy.totalMinutes), 1) }) : t("customers.activities.calendar.hoursShort", "{hours}h", { hours: Math.floor(busy.totalMinutes / 60) });
  return t("customers.activities.calendar.eventsSummary", "{count} {countLabel} \xB7 {duration}", {
    count: busy.eventCount,
    countLabel: busy.eventCount === 1 ? t("customers.activities.calendar.eventSingular", "event") : t("customers.activities.calendar.eventPlural", "events"),
    duration: durationLabel
  });
}
function formatMonthLabel(date, t) {
  const monthEntry = MONTH_KEYS.find(([index]) => index === date.getMonth());
  const monthName = monthEntry ? t(monthEntry[1], monthEntry[2]) : "";
  return t("customers.activities.calendar.monthYear", "{month} {year}", { month: monthName, year: date.getFullYear() });
}
function formatDayLabel(date, t) {
  const entry = DAY_LABEL_KEYS.find(([index]) => index === date.getDay());
  return entry ? t(entry[1], entry[2]) : "";
}
function ActivitiesDayStrip({ entityId, selectedDate, onSelectDate, refreshKey = 0, events: providedEvents }) {
  const t = useT();
  const [anchor, setAnchor] = React.useState(() => anchorCenteredOn(selectedDate));
  const [fetchedEvents, setFetchedEvents] = React.useState([]);
  const useProvidedEvents = providedEvents !== void 0;
  const events = useProvidedEvents ? providedEvents : fetchedEvents;
  React.useEffect(() => {
    setAnchor((current) => {
      const days = buildVisibleDays(current);
      const visible = days.some((day) => isSameDay(day, selectedDate));
      if (visible) return current;
      return anchorCenteredOn(selectedDate);
    });
  }, [selectedDate]);
  const visibleDays = React.useMemo(() => buildVisibleDays(anchor), [anchor]);
  const headerLabel = React.useMemo(() => formatMonthLabel(visibleDays[0], t), [visibleDays, t]);
  React.useEffect(() => {
    if (useProvidedEvents) return;
    if (!entityId || visibleDays.length === 0) return;
    const controller = new AbortController();
    const fromIso = startOfDay(visibleDays[0]).toISOString();
    const toIso = endOfDay(visibleDays[visibleDays.length - 1]).toISOString();
    const params = new URLSearchParams({
      entityId,
      from: fromIso,
      to: toIso,
      limit: "100",
      sortField: "scheduledAt",
      sortDir: "asc",
      excludeInteractionType: "task"
    });
    void (async () => {
      try {
        const payload = await readApiResultOrThrow(
          `/api/customers/interactions?${params.toString()}`,
          { signal: controller.signal }
        );
        setFetchedEvents(Array.isArray(payload?.items) ? payload.items : []);
      } catch (err) {
        if (err?.name !== "AbortError") {
          logger.warn("failed to load interactions", { component: "ActivitiesDayStrip", err });
        }
        setFetchedEvents([]);
      }
    })();
    return () => controller.abort();
  }, [entityId, visibleDays, refreshKey, useProvidedEvents]);
  const todayDate = React.useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
  const handlePrev = React.useCallback(() => {
    setAnchor((current) => addDays(current, -VISIBLE_DAYS));
  }, []);
  const handleNext = React.useCallback(() => {
    setAnchor((current) => addDays(current, VISIBLE_DAYS));
  }, []);
  const handleHeaderPrev = React.useCallback(() => {
    setAnchor((current) => {
      const next = new Date(current);
      next.setMonth(current.getMonth() - 1);
      return startOfDay(next);
    });
  }, []);
  const handleHeaderNext = React.useCallback(() => {
    setAnchor((current) => {
      const next = new Date(current);
      next.setMonth(current.getMonth() + 1);
      return startOfDay(next);
    });
  }, []);
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5 rounded-md px-3.5 py-3 w-full", children: [
    /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1.5 rounded-md bg-muted px-1.5 py-1.5", children: [
      /* @__PURE__ */ jsx(
        "button",
        {
          type: "button",
          onClick: handleHeaderPrev,
          "aria-label": t("customers.activities.calendar.prevMonth", "Previous month"),
          className: "flex size-6 items-center justify-center rounded-md border border-border bg-card shadow-xs hover:bg-accent/40",
          children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4 text-foreground" })
        }
      ),
      /* @__PURE__ */ jsx("span", { className: "flex-1 text-center text-sm font-medium leading-5 text-foreground", children: headerLabel }),
      /* @__PURE__ */ jsx(
        "button",
        {
          type: "button",
          onClick: handleHeaderNext,
          "aria-label": t("customers.activities.calendar.nextMonth", "Next month"),
          className: "flex size-6 items-center justify-center rounded-md border border-border bg-card shadow-xs hover:bg-accent/40",
          children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 text-foreground" })
        }
      )
    ] }),
    /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-2", children: [
      /* @__PURE__ */ jsx(
        "button",
        {
          type: "button",
          onClick: handlePrev,
          "aria-label": t("customers.activities.calendar.prevWindow", "Previous days"),
          className: "flex size-6 shrink-0 items-center justify-center rounded-md border border-border bg-card shadow-xs hover:bg-accent/40",
          children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4 text-foreground" })
        }
      ),
      /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-stretch justify-center gap-1", children: visibleDays.map((day) => {
        const busy = computeDayBusyness(events, day);
        const isSelected = isSameDay(day, selectedDate);
        const isToday = isSameDay(day, todayDate);
        const weekend = isWeekend(day);
        const busyLabel = busy.eventCount > 0 ? formatBusyLabel(busy, t) : weekend ? t("customers.activities.calendar.weekend", "Weekend") : "";
        return /* @__PURE__ */ jsx(
          DayCard,
          {
            day,
            isActive: isSelected,
            isToday,
            busyness: busy,
            label: busyLabel,
            dayName: formatDayLabel(day, t),
            onSelect: () => onSelectDate(day)
          },
          day.toISOString()
        );
      }) }),
      /* @__PURE__ */ jsx(
        "button",
        {
          type: "button",
          onClick: handleNext,
          "aria-label": t("customers.activities.calendar.nextWindow", "Next days"),
          className: "flex size-6 shrink-0 items-center justify-center rounded-md border border-border bg-card shadow-xs hover:bg-accent/40",
          children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 text-foreground" })
        }
      )
    ] })
  ] });
}
function DayCard({ day, isActive, isToday, busyness, label, dayName, onSelect }) {
  const dayNumber = String(day.getDate()).padStart(2, "0");
  return /* @__PURE__ */ jsxs(
    "button",
    {
      type: "button",
      onClick: onSelect,
      "aria-pressed": isActive,
      "aria-label": `${dayName} ${dayNumber}`,
      className: cn(
        "flex h-[104px] w-[101px] flex-col items-center gap-[6px] overflow-hidden rounded-[10px] border p-[12px] transition-colors",
        isActive ? "border-transparent bg-foreground" : "border-border bg-card hover:border-foreground/40"
      ),
      children: [
        /* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium leading-none tracking-[0.44px] text-muted-foreground", children: dayName }),
        /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[5px]", children: [
          /* @__PURE__ */ jsx(
            "span",
            {
              className: cn(
                "text-2xl font-semibold leading-7",
                isActive ? "text-background" : "text-foreground"
              ),
              children: dayNumber
            }
          ),
          isToday ? /* @__PURE__ */ jsx(
            "span",
            {
              className: "inline-block size-1.5 rounded-full bg-status-info-icon",
              "aria-hidden": true
            }
          ) : null
        ] }),
        /* @__PURE__ */ jsx("div", { className: "flex h-4 w-[82px] items-end gap-[1.5px]", children: busyness.slots.map((state, index) => /* @__PURE__ */ jsx(BusySlot, { state, active: isActive }, index)) }),
        /* @__PURE__ */ jsx("span", { className: "text-[11px] leading-[14px] font-normal whitespace-nowrap text-muted-foreground", children: label })
      ]
    }
  );
}
function BusySlot({ state, active }) {
  const heightClass = state === "empty" ? "h-0.5" : state === "partial" ? "h-2" : "h-3.5";
  let bgClass;
  if (state === "conflict") {
    bgClass = "bg-status-error-icon";
  } else if (active) {
    if (state === "empty") bgClass = "bg-background/30";
    else if (state === "partial") bgClass = "bg-background/60";
    else bgClass = "bg-background";
  } else {
    if (state === "empty") bgClass = "bg-border";
    else if (state === "partial") bgClass = "bg-muted-foreground";
    else bgClass = "bg-foreground";
  }
  return /* @__PURE__ */ jsx("div", { className: cn("w-[7px] shrink-0 rounded-[1.5px]", heightClass, bgClass), "aria-hidden": true });
}
var ActivitiesDayStrip_default = ActivitiesDayStrip;
export {
  ActivitiesDayStrip,
  ActivitiesDayStrip_default as default
};
//# sourceMappingURL=ActivitiesDayStrip.js.map
