import type { AdminViewServerProps } from "payload";
import { getAdminCalendarItems, type AdminCalendarItem } from "@/lib/booking/adminCalendar";
import styles from "./AdminCalendarView.module.css";

const WEEKDAY_LABELS = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"];
const STATUS_LABEL: Record<string, string> = {
  pending: "Anfrage",
  confirmed: "Bestätigt",
  rejected: "Abgelehnt",
  cancelled: "Storniert",
  public: "Öffentlich",
};
const DOT_CLASS: Record<string, string> = {
  pending: styles.dotPending,
  confirmed: styles.dotConfirmed,
  rejected: styles.dotRejected,
  cancelled: styles.dotCancelled,
  public: styles.dotPublic,
};
const BADGE_CLASS: Record<string, string> = {
  pending: styles.badgePending,
  confirmed: styles.badgeConfirmed,
  rejected: styles.badgeRejected,
  cancelled: styles.badgeCancelled,
  public: styles.badgePublic,
};

function dateKey(d: Date) {
  return d.toISOString().slice(0, 10);
}
function parseMonthParam(value: string | null): Date {
  if (value && /^\d{4}-\d{2}$/.test(value)) {
    const [y, m] = value.split("-").map(Number);
    return new Date(y, m - 1, 1);
  }
  return new Date(new Date().getFullYear(), new Date().getMonth(), 1);
}
function monthParam(d: Date) {
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`;
}
function fmtTime(iso: string) {
  return new Date(iso).toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit" });
}

export async function AdminCalendarView({ initPageResult }: AdminViewServerProps) {
  const req = initPageResult.req;
  const searchParams = req.searchParams;
  const month = parseMonthParam(searchParams.get("month"));
  const selectedDayParam = searchParams.get("day");
  const selectedDay = selectedDayParam ? new Date(`${selectedDayParam}T00:00:00`) : null;

  const gridStart = new Date(month.getFullYear(), month.getMonth(), 1);
  const firstWeekday = (gridStart.getDay() + 6) % 7;
  const rangeStart = new Date(gridStart);
  rangeStart.setDate(rangeStart.getDate() - firstWeekday);
  const daysInMonth = new Date(month.getFullYear(), month.getMonth() + 1, 0).getDate();
  const rangeEnd = new Date(rangeStart);
  rangeEnd.setDate(rangeEnd.getDate() + 41); // 6 full weeks

  const items = await getAdminCalendarItems(req.payload, { from: rangeStart, to: rangeEnd });
  const itemsByDay = new Map<string, AdminCalendarItem[]>();
  for (const item of items) {
    const key = dateKey(new Date(item.date));
    itemsByDay.set(key, [...(itemsByDay.get(key) ?? []), item]);
  }

  const cells: (Date | null)[] = [];
  for (let i = 0; i < firstWeekday; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(month.getFullYear(), month.getMonth(), d));
  while (cells.length % 7 !== 0) cells.push(null);

  const prevMonth = new Date(month.getFullYear(), month.getMonth() - 1, 1);
  const nextMonth = new Date(month.getFullYear(), month.getMonth() + 1, 1);
  const today = dateKey(new Date());
  const monthLabel = month.toLocaleDateString("de-DE", { month: "long", year: "numeric" });

  const dayItems = selectedDay ? (itemsByDay.get(dateKey(selectedDay)) ?? []) : [];
  const hours = Array.from({ length: 13 }, (_, i) => i + 8); // 08:00–20:00

  return (
    <div className={styles.page}>
      <h1 className={styles.title}>Kalender</h1>
      <p className={styles.subtitle}>
        Alle bestätigten und vorgeschlagenen Termine, private Einzelbuchungen und öffentliche Veranstaltungen.
      </p>

      <div className={styles.layout}>
        <div>
          <div className={styles.monthNav}>
            <a href={`?month=${monthParam(prevMonth)}`} aria-label="Vorheriger Monat">
              ‹
            </a>
            <span className={styles.monthLabel}>{monthLabel}</span>
            <a href={`?month=${monthParam(nextMonth)}`} aria-label="Nächster Monat">
              ›
            </a>
          </div>

          <div className={styles.grid}>
            {WEEKDAY_LABELS.map((d) => (
              <div key={d} className={styles.weekdayLabel}>
                {d}
              </div>
            ))}
            {cells.map((day, i) => {
              if (!day) return <div key={i} className={`${styles.dayCell} ${styles.dayCellEmpty}`} />;
              const key = dateKey(day);
              const dayEntries = itemsByDay.get(key) ?? [];
              const isSelected = selectedDayParam === key;
              return (
                <a
                  key={i}
                  href={`?month=${monthParam(month)}&day=${key}`}
                  className={`${styles.dayCell} ${isSelected ? styles.dayCellSelected : ""} ${key === today ? styles.dayCellToday : ""}`}
                >
                  <span>{day.getDate()}</span>
                  {dayEntries.length > 0 && (
                    <span className={styles.dots}>
                      {dayEntries.slice(0, 4).map((entry, j) => (
                        <span key={j} className={`${styles.dot} ${DOT_CLASS[entry.status] ?? ""}`} />
                      ))}
                    </span>
                  )}
                </a>
              );
            })}
          </div>

          <div className={styles.legend}>
            {Object.entries(STATUS_LABEL).map(([status, label]) => (
              <span key={status} className={styles.legendItem}>
                <span className={`${styles.dot} ${DOT_CLASS[status]}`} />
                {label}
              </span>
            ))}
          </div>
        </div>

        <div className={styles.schedule}>
          <div className={styles.scheduleHeader}>
            {selectedDay
              ? selectedDay.toLocaleDateString("de-DE", { weekday: "long", day: "2-digit", month: "long", year: "numeric" })
              : "Wähle einen Tag im Kalender"}
          </div>
          {!selectedDay && <p className={styles.empty}>Klicke auf einen Tag, um die Tagesübersicht zu sehen.</p>}
          {selectedDay && dayItems.length === 0 && <p className={styles.empty}>An diesem Tag ist nichts eingetragen.</p>}
          {selectedDay &&
            dayItems.length > 0 &&
            hours.map((hour) => {
              const hourEntries = dayItems.filter((item) => new Date(item.startTime).getHours() === hour);
              return (
                <div key={hour} className={styles.hourRow}>
                  <div className={styles.hourLabel}>{String(hour).padStart(2, "0")}:00</div>
                  <div className={styles.hourContent}>
                    {hourEntries.map((entry) => (
                      <a key={entry.id} href={entry.href} className={styles.entry}>
                        <span className={`${styles.badge} ${BADGE_CLASS[entry.status] ?? ""}`}>
                          {STATUS_LABEL[entry.status] ?? entry.status}
                        </span>
                        <strong>{entry.title}</strong>
                        <span>
                          {fmtTime(entry.startTime)}–{fmtTime(entry.endTime)}
                        </span>
                        {entry.subtitle && <span>· {entry.subtitle}</span>}
                        {entry.appointmentType && <span>· {entry.appointmentType === "online" ? "Online" : "Vor Ort"}</span>}
                      </a>
                    ))}
                  </div>
                </div>
              );
            })}
        </div>
      </div>
    </div>
  );
}
