import type { DeskId, DeskReservation } from "../types";
import { DESKS } from "../types";

/** Maximum number of days in advance a reservation can be made */
export const MAX_ADVANCE_DAYS = 14;

/**
 * Check if a date string falls on a weekday (Mon-Fri).
 */
export function isWeekday(dateStr: string): boolean {
  const day = new Date(dateStr).getDay();
  return day >= 1 && day <= 5;
}

/**
 * Format a date as YYYY-MM-DD.
 */
export function toDateKey(date: Date): string {
  const y = date.getFullYear();
  const m = String(date.getMonth() + 1).padStart(2, "0");
  const d = String(date.getDate()).padStart(2, "0");
  return `${y}-${m}-${d}`;
}

/**
 * Get the Monday of the week containing `date`.
 */
export function getMonday(date: Date): Date {
  const d = new Date(date);
  const day = d.getDay();
  const diff = day === 0 ? -6 : 1 - day;
  d.setDate(d.getDate() + diff);
  d.setHours(0, 0, 0, 0);
  return d;
}

/**
 * Build an array of weekday date keys for the week containing `date`.
 */
export function getWeekDays(date: Date): string[] {
  const monday = getMonday(date);
  const days: string[] = [];
  for (let i = 0; i < 5; i++) {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    days.push(toDateKey(d));
  }
  return days;
}

/**
 * Build all bookable date keys: today + up to MAX_ADVANCE_DAYS, weekdays only.
 */
export function getBookableDates(): string[] {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const dates: string[] = [];
  for (let i = 0; i <= MAX_ADVANCE_DAYS; i++) {
    const d = new Date(today);
    d.setDate(today.getDate() + i);
    const key = toDateKey(d);
    if (isWeekday(key)) {
      dates.push(key);
    }
  }
  return dates;
}

/**
 * Check if a desk is available on a specific date.
 */
export function isDeskAvailable(
  deskId: DeskId,
  dateKey: string,
  reservations: DeskReservation[],
): boolean {
  return !reservations.some((r) => r.deskId === deskId && r.date === dateKey);
}

/**
 * Check if a specific date can be booked (not in the past, within 2-week window, is a weekday).
 */
export function isDateBookable(dateKey: string): boolean {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const target = new Date(dateKey);
  target.setHours(0, 0, 0, 0);

  if (target < today) return false;

  const diffMs = target.getTime() - today.getTime();
  const diffDays = Math.round(diffMs / (1000 * 60 * 60 * 24));
  if (diffDays > MAX_ADVANCE_DAYS) return false;

  return isWeekday(dateKey);
}

/**
 * Get reservations for a specific date.
 */
export function getReservationsForDate(
  dateKey: string,
  reservations: DeskReservation[],
): DeskReservation[] {
  return reservations.filter((r) => r.date === dateKey);
}

/**
 * Get reservations for a specific desk on a date.
 */
export function getReservationForDesk(
  deskId: DeskId,
  dateKey: string,
  reservations: DeskReservation[],
): DeskReservation | undefined {
  return reservations.find((r) => r.deskId === deskId && r.date === dateKey);
}

/**
 * Detect workdays in the current week that have zero reservations.
 * Returns date keys that need attention.
 */
export function getUnbookedCurrentWeekDays(
  reservations: DeskReservation[],
): string[] {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const weekDays = getWeekDays(today);
  const todayKey = toDateKey(today);

  return weekDays.filter((dateKey) => {
    // Only check today and future days in the current week
    if (dateKey < todayKey) return false;
    const dayReservations = getReservationsForDate(dateKey, reservations);
    return dayReservations.length === 0;
  });
}

/**
 * Count available desks for a date.
 */
export function countAvailableDesks(
  dateKey: string,
  reservations: DeskReservation[],
): number {
  const booked = reservations.filter((r) => r.date === dateKey).length;
  return DESKS.length - booked;
}

/**
 * Format a date key to a human-friendly Romanian string.
 */
export function formatDateRo(dateKey: string): string {
  const date = new Date(dateKey);
  const days = [
    "Duminică",
    "Luni",
    "Marți",
    "Miercuri",
    "Joi",
    "Vineri",
    "Sâmbătă",
  ];
  const months = [
    "ianuarie",
    "februarie",
    "martie",
    "aprilie",
    "mai",
    "iunie",
    "iulie",
    "august",
    "septembrie",
    "octombrie",
    "noiembrie",
    "decembrie",
  ];
  const dayName = days[date.getDay()] ?? "";
  const monthName = months[date.getMonth()] ?? "";
  return `${dayName}, ${date.getDate()} ${monthName}`;
}

/**
 * Short format: "Lun 19 feb"
 */
export function formatDateShort(dateKey: string): string {
  const date = new Date(dateKey);
  const days = ["Dum", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm"];
  const months = [
    "ian",
    "feb",
    "mar",
    "apr",
    "mai",
    "iun",
    "iul",
    "aug",
    "sep",
    "oct",
    "noi",
    "dec",
  ];
  const dayName = days[date.getDay()] ?? "";
  const monthName = months[date.getMonth()] ?? "";
  return `${dayName} ${date.getDate()} ${monthName}`;
}
