<script>"use strict";
import Button from "./Button.svelte";
import Icon from "./Icon.svelte";
let calendarElement;
export let label = null;
export let value = null;
export let leftValue = null;
export let rightValue = null;
export let placeholder = "Select date";
export let minDate = null;
export let maxDate = null;
export let disabled = false;
export let readonly = false;
export let startOfWeek = "Sunday";
export let calendarType = "single";
export let showCalendar = false;
let currentDate = value ? new Date(value) : /* @__PURE__ */ new Date();
let view = "date";
let leftCurrentDate = leftValue ? new Date(leftValue) : /* @__PURE__ */ new Date();
let rightCurrentDate = rightValue ? new Date(rightValue) : new Date(leftCurrentDate.getFullYear(), leftCurrentDate.getMonth() + 1, 1);
let leftView = "date";
let rightView = "date";
const daysInMonth = (month, year) => new Date(year, month + 1, 0).getDate();
const firstDayOfMonth = (month, year) => new Date(year, month, 1).getDay();
const getDateOfPrevMonth = () => {
  const firstDayOfCurrentMonth = new Date(
    currentDate.getFullYear(),
    currentDate.getMonth(),
    1
  ).getDay();
  const lastDateOfPreviousMonth = new Date(
    currentDate.getFullYear(),
    currentDate.getMonth(),
    0
  ).getDate();
  if (startOfWeek === "Monday" && firstDayOfCurrentMonth === 0) {
    return lastDateOfPreviousMonth - 5;
  } else if (startOfWeek === "Monday" && firstDayOfCurrentMonth === 2) {
    return lastDateOfPreviousMonth;
  }
  return lastDateOfPreviousMonth - firstDayOfCurrentMonth + 1;
};
const isDateDisabled = (date) => {
  if (minDate && date < minDate) return true;
  if (maxDate && date > maxDate) return true;
  return false;
};
const formatDate = (date) => date ? date.toLocaleDateString() : placeholder;
const changeMonth = (increment) => {
  currentDate.setMonth(currentDate.getMonth() + increment);
  currentDate = new Date(currentDate);
};
const changeYear = (increment) => {
  currentDate.setFullYear(currentDate.getFullYear() + increment);
  currentDate = new Date(currentDate);
};
const selectDate = (day, month = currentDate.getMonth(), year = currentDate.getFullYear()) => {
  const selected = new Date(year, month, day);
  if (!isDateDisabled(selected)) {
    value = new Date(selected);
  }
};
const selectMonth = (month) => {
  currentDate.setMonth(month);
  view = "date";
};
const selectYear = (year) => {
  currentDate.setFullYear(year);
  view = "month";
};
const getYearsInDecade = (_currentDate) => {
  const startYear = Math.floor(_currentDate.getFullYear() / 10) * 10;
  return Array.from({ length: 10 }, (_, i) => startYear + i);
};
const getOffset = (day) => startOfWeek === "Monday" ? day === 0 ? 6 : day - 1 : day;
const isToday = (d, day) => {
  const today = /* @__PURE__ */ new Date();
  return today.getDate() === day && today.getMonth() === d.getMonth() && today.getFullYear() === d.getFullYear();
};
$: isSelectedSingle = (d, day) => value && value.getDate() === day && value.getMonth() === d.getMonth() && value.getFullYear() === d.getFullYear();
const changeLeftMonth = (increment) => {
  leftCurrentDate.setMonth(leftCurrentDate.getMonth() + increment);
  leftCurrentDate = new Date(leftCurrentDate);
};
const changeLeftYear = (increment) => {
  leftCurrentDate.setFullYear(leftCurrentDate.getFullYear() + increment);
  leftCurrentDate = new Date(leftCurrentDate);
};
const changeRightMonth = (increment) => {
  rightCurrentDate.setMonth(rightCurrentDate.getMonth() + increment);
  rightCurrentDate = new Date(rightCurrentDate);
};
const changeRightYear = (increment) => {
  rightCurrentDate.setFullYear(rightCurrentDate.getFullYear() + increment);
  rightCurrentDate = new Date(rightCurrentDate);
};
const selectLeftDate = (day) => {
  const selected = new Date(leftCurrentDate.getFullYear(), leftCurrentDate.getMonth(), day);
  if (!isDateDisabled(selected)) {
    leftValue = selected;
    if (rightValue && leftValue > rightValue) {
      rightValue = null;
    }
    if (leftValue && rightValue) showCalendar = false;
  }
};
const selectRightDate = (day) => {
  const selected = new Date(rightCurrentDate.getFullYear(), rightCurrentDate.getMonth(), day);
  if (!isDateDisabled(selected)) {
    rightValue = selected;
    if (leftValue && rightValue < leftValue) {
      const temp = rightValue;
      rightValue = leftValue;
      leftValue = temp;
    }
    if (leftValue && rightValue) showCalendar = false;
  }
};
const selectLeftMonth = (month) => {
  leftCurrentDate.setMonth(month);
  leftView = "date";
};
const selectRightMonth = (month) => {
  rightCurrentDate.setMonth(month);
  rightView = "date";
};
const selectLeftYear = (year) => {
  leftCurrentDate.setFullYear(year);
  leftView = "month";
};
const selectRightYear = (year) => {
  rightCurrentDate.setFullYear(year);
  rightView = "month";
};
const getYearsInDecadeForLeft = () => getYearsInDecade(leftCurrentDate);
const getYearsInDecadeForRight = () => getYearsInDecade(rightCurrentDate);
$: startDate = leftValue && rightValue ? leftValue < rightValue ? leftValue : rightValue : leftValue;
$: endDate = leftValue && rightValue ? leftValue < rightValue ? rightValue : leftValue : rightValue;
const inRange = (date) => {
  if (leftValue && !rightValue) {
    return date > leftValue;
  } else if (leftValue && rightValue) {
    const start = leftValue < rightValue ? leftValue : rightValue;
    const end = leftValue < rightValue ? rightValue : leftValue;
    return date >= start && date <= end;
  }
  return false;
};
$: formattedRange = leftValue && rightValue ? `${formatDate(leftValue)} - ${formatDate(rightValue)}` : placeholder;
$: getRangeCellClasses = (date) => {
  const disabled2 = isDateDisabled(date);
  const today = isToday(date, date.getDate());
  const in_selected_range = inRange(date);
  let classes = "text-md w-full h-8 py-1 hover:rounded";
  if (disabled2) {
    classes += " text-gray-300 cursor-not-allowed";
    return classes;
  }
  if (in_selected_range) {
    if (startDate && date.getTime() === startDate.getTime()) {
      classes += " rounded-l bg-blue-600 text-white";
      if (today) classes += " border border-blue-500";
      return classes;
    }
    if (endDate && date.getTime() === endDate.getTime()) {
      classes += " rounded-r bg-blue-600 text-white";
      if (today) classes += " border border-blue-500";
      return classes;
    }
    classes += " bg-base-200";
    if (today) classes += " border border-blue-500";
    return classes;
  }
  if (today) classes += " border border-blue-500";
  classes += " primary-text-950 hover:bg-blue-600 hover:text-white";
  return classes;
};
$: getSingleCellClasses = (d, day) => {
  const disabled2 = isDateDisabled(new Date(d.getFullYear(), d.getMonth(), day));
  const selected = isSelectedSingle(d, day);
  const today_ = isToday(d, day);
  let classes = "text-md w-full h-8 py-1";
  if (disabled2) {
    classes += " text-gray-300 cursor-not-allowed";
    return classes;
  }
  if (selected) {
    classes += " bg-blue-600 text-white rounded";
    if (today_) classes += " border border-blue-500";
    return classes;
  }
  if (today_) {
    classes += " border border-blue-500";
  }
  classes += " primary-text-950 hover:bg-blue-600 hover:text-white rounded";
  return classes;
};
function getLastDayOfMonth(year, month) {
  const lastDate = new Date(year, month + 1, 0);
  const offsetNum = startOfWeek === "Monday" ? 7 : 6;
  const numOfDays = offsetNum - lastDate.getDay();
  return numOfDays;
}
function handleClickOutside(event) {
  if (calendarElement && !calendarElement.contains(event.target)) {
    showCalendar = false;
  }
}
$: if (showCalendar) {
  document.addEventListener("click", handleClickOutside);
} else {
  document.removeEventListener("click", handleClickOutside);
}
</script>

<div class="relative w-full" class:disabled>
	{#if label}
		<div class="font-medium text-4xl mb-2">
			{label}
		</div>
	{/if}

	<!-- Single Calendar -->
	<div bind:this={calendarElement}>
		{#if calendarType === 'single'}
			<div class="relative">
				<!-- Dropdown -->
				<input
					type="text"
					class="w-full py-2.5 pl-12 pr-4.5 text-2xl text-stone-400 ray-50 border border-gray-300 cursor-pointer rounded-lg shadow-sm focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-200 disabled:cursor-not-allowed"
					{placeholder}
					readonly={readonly || disabled}
					value={formatDate(value)}
					on:click={() => !disabled && (showCalendar = !showCalendar)}
				/>
				<Icon
					iconName="calendar"
					className="absolute inset-y-2.5 left-4 flex items-center text-gray-500 cursor-pointer"
				/>
			</div>

			{#if showCalendar}
				<div class="absolute mt-2 w-80 bg-white border border-gray-200 rounded-lg shadow z-10">
					<div class="flex justify-between items-center py-2 px-4">
						<button
							type="button"
							class="text-gray-600 hover:text-blue-500"
							on:click={() =>
								view === 'date'
									? changeMonth(-1)
									: view === 'month'
										? changeYear(-1)
										: changeYear(-10)}
						>
							<Icon iconName="chevron-left" size="sm" />
						</button>
						{#if view === 'date'}
							<button
								type="button"
								class="text-md font-medium cursor-pointer"
								on:click|stopPropagation={() => (view = 'month')}
							>
								{currentDate.toLocaleString('default', { month: 'long' })}{' '}
								{currentDate.getFullYear()}
							</button>
						{:else if view === 'month'}
							<button
								type="button"
								class="text-md font-medium cursor-pointer"
								on:click|stopPropagation={() => (view = 'year')}
							>
								{currentDate.getFullYear()}
							</button>
						{:else if view === 'year'}
							<span class="text-md font-medium">
								{Math.floor(currentDate.getFullYear() / 10) * 10} -{' '}
								{Math.floor(currentDate.getFullYear() / 10) * 10 + 9}
							</span>
						{/if}
						<button
							type="button"
							class="text-gray-600 hover:text-blue-500"
							on:click={() =>
								view === 'date'
									? changeMonth(1)
									: view === 'month'
										? changeYear(1)
										: changeYear(10)}
						>
							<Icon iconName="chevron-right" size="sm" />
						</button>
					</div>

					{#if view === 'date'}
						<!-- Days of the week -->
						<div
							class="grid grid-cols-7 gap-1 px-4 text-center text-md font-semibold text-stone-400"
						>
							{#if startOfWeek === 'Monday'}
								<div>Mon</div>
								<div>Tue</div>
								<div>Wed</div>
								<div>Thu</div>
								<div>Fri</div>
								<div>Sat</div>
								<div>Sun</div>
							{:else}
								<div>Sun</div>
								<div>Mon</div>
								<div>Tue</div>
								<div>Wed</div>
								<div>Thu</div>
								<div>Fri</div>
								<div>Sat</div>
							{/if}
						</div>

						<!-- Days -->
						<div class="grid grid-cols-7 gap-y-0.5 px-4 py-2 text-center">
							{#each Array(getOffset(firstDayOfMonth(currentDate.getMonth(), currentDate.getFullYear())))
								.fill('')
								.map((_, i) => {
									return getDateOfPrevMonth() + i;
								}) as day}
								<button
									type="button"
									class="text-md w-full h-8 py-1 text-gray-400 hover:bg-slate-600 hover:text-white rounded"
									on:click|stopPropagation={() => {
										const prevMonth =
											currentDate.getMonth() === 0 ? 11 : currentDate.getMonth() - 1;
										const prevYear =
											currentDate.getMonth() === 0
												? currentDate.getFullYear() - 1
												: currentDate.getFullYear();
										selectDate(day, prevMonth, prevYear);
									}}
									disabled={isDateDisabled(
										new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, day)
									)}
								>
									{day}
								</button>
							{/each}

							<!-- Days of the current month -->
							{#each Array(daysInMonth(currentDate.getMonth(), currentDate.getFullYear()))
								.fill('')
								.map((_, i) => i + 1) as day}
								<button
									type="button"
									class={getSingleCellClasses(currentDate, day)}
									on:click|stopPropagation={() => selectDate(day)}
									disabled={isDateDisabled(
										new Date(currentDate.getFullYear(), currentDate.getMonth(), day)
									)}
								>
									{day}
								</button>
							{/each}

							<!-- Days from the next month to fill the remaining space -->
							{#each Array(getLastDayOfMonth(currentDate.getFullYear(), currentDate.getMonth()))
								.fill('')
								.map((_, i) => i + 1) as day}
								<button
									type="button"
									class="text-md w-full h-8 py-1 text-gray-400 hover:bg-blue-600 hover:text-white rounded"
									on:click|stopPropagation={() => {
										const nextMonth =
											currentDate.getMonth() === 11 ? 0 : currentDate.getMonth() + 1;
										const nextYear =
											currentDate.getMonth() === 11
												? currentDate.getFullYear() + 1
												: currentDate.getFullYear();
										selectDate(day, nextMonth, nextYear);
									}}
								>
									{day}
								</button>
							{/each}
						</div>
					{:else if view === 'month'}
						<!-- Month Selection -->
						<div class="grid grid-cols-3 gap-1 px-4 py-2 text-center">
							{#each Array.from({ length: 12 }).map((_, i) => i) as month}
								<button
									type="button"
									class="py-1 text-md h-8 rounded hover:bg-blue-600 hover:text-white"
									on:click|stopPropagation={() => selectMonth(month)}
								>
									{new Date(0, month).toLocaleString('default', { month: 'long' })}
								</button>
							{/each}
						</div>
					{:else if view === 'year'}
						<!-- Year Selection -->
						<div class="grid grid-cols-3 gap-1 px-4 py-2 text-center">
							{#each getYearsInDecade(currentDate) as year}
								<button
									type="button"
									class="py-1 text-md rounded hover:bg-blue-600 hover:text-white"
									on:click|stopPropagation={() => selectYear(year)}
								>
									{year}
								</button>
							{/each}
						</div>
					{/if}
					<div class="w-full flex px-4 pb-4 gap-2">
						<Button
							type="button"
							on:click={() => (showCalendar = false)}
							size="sm"
							appearance="flat"
							color="base"
							className="w-full justify-center"
						>
							Cancel
						</Button>
						<Button
							type="button"
							on:click={() => {
								if (value) {
									// Trigger parent binding update
									value = new Date(value);
								}
								showCalendar = false;
							}}
							size="sm"
							appearance="flat"
							color="blue"
							className="w-full justify-center"
						>
							Apply
						</Button>
					</div>
				</div>
			{/if}

			<!-- Range Calendar -->
		{:else if calendarType === 'range'}
			<div class="relative">
				<input
					type="text"
					class="w-full py-2.5 pl-12 pr-4.5 text-2xl text-stone-400 ray-50 border border-gray-300 rounded-lg shadow-sm focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-200 disabled:cursor-not-allowed"
					{placeholder}
					readonly={readonly || disabled}
					value={formattedRange}
					on:click={() => !disabled && (showCalendar = !showCalendar)}
				/>
				<Icon
					iconName="calendar"
					className="absolute inset-y-2.5 left-4 flex items-center text-gray-500 cursor-pointer"
				/>
			</div>

			{#if showCalendar}
				<div class="mt-2 grid absolute rounded-lg border border-gray-200 shadow z-10 bg-white">
					<div class="flex">
						<div class="w-80 bg-white">
							<div class="flex justify-between items-center py-2 px-4">
								<button
									type="button"
									class="text-gray-600 hover:text-blue-500"
									on:click={() =>
										leftView === 'date'
											? changeLeftMonth(-1)
											: leftView === 'month'
												? changeLeftYear(-1)
												: changeLeftYear(-10)}
								>
									<Icon iconName="chevron-left" size="sm" />
								</button>
								{#if leftView === 'date'}
									<button
										type="button"
										class="text-md font-medium cursor-pointer"
										on:click|stopPropagation={() => (leftView = 'month')}
									>
										{leftCurrentDate.toLocaleString('default', { month: 'long' })}
										{leftCurrentDate.getFullYear()}
									</button>
								{:else if leftView === 'month'}
									<button
										type="button"
										class="text-md font-medium cursor-pointer"
										on:click|stopPropagation={() => (leftView = 'year')}
									>
										{leftCurrentDate.getFullYear()}
									</button>
								{:else if leftView === 'year'}
									<span class="text-md font-medium">
										{Math.floor(leftCurrentDate.getFullYear() / 10) * 10} - {Math.floor(
											leftCurrentDate.getFullYear() / 10
										) *
											10 +
											9}
									</span>
								{/if}
								<button
									type="button"
									class="text-gray-600 hover:text-blue-500"
									on:click={() =>
										leftView === 'date'
											? changeLeftMonth(1)
											: leftView === 'month'
												? changeLeftYear(1)
												: changeLeftYear(10)}
								>
									<Icon iconName="chevron-right" size="sm" />
								</button>
							</div>

							<!-- Left Calendar Views -->
							{#if leftView === 'date'}
								<!-- Days of the week -->
								<div
									class="grid grid-cols-7 gap-1 px-4 text-center text-md font-semibold text-stone-400"
								>
									{#if startOfWeek === 'Monday'}
										<div>Mon</div>
										<div>Tue</div>
										<div>Wed</div>
										<div>Thu</div>
										<div>Fri</div>
										<div>Sat</div>
										<div>Sun</div>
									{:else}
										<div>Sun</div>
										<div>Mon</div>
										<div>Tue</div>
										<div>Wed</div>
										<div>Thu</div>
										<div>Fri</div>
										<div>Sat</div>
									{/if}
								</div>

								<!-- Days -->
								<div class="grid grid-cols-7 gap-y-0.5 px-4 py-2 text-center">
									{#each Array(getOffset(firstDayOfMonth(leftCurrentDate.getMonth(), leftCurrentDate.getFullYear()))).fill('') as _}
										<div class="text-transparent">{_}</div>
									{/each}

									{#each Array(daysInMonth(leftCurrentDate.getMonth(), leftCurrentDate.getFullYear()))
										.fill('')
										.map((_, i) => i + 1) as day}
										{@const date = new Date(
											leftCurrentDate.getFullYear(),
											leftCurrentDate.getMonth(),
											day
										)}
										<button
											type="button"
											class={getRangeCellClasses(date)}
											on:click|stopPropagation={() => selectLeftDate(day)}
											disabled={isDateDisabled(date)}
										>
											{day}
										</button>
									{/each}
								</div>
							{:else if leftView === 'month'}
								<!-- Month Selection -->
								<div class="grid grid-cols-3 gap-1 px-4 py-2 text-center">
									{#each Array.from({ length: 12 }).map((_, i) => i) as month}
										<button
											type="button"
											class="py-1 text-md h-8 rounded hover:bg-blue-600 hover:text-white"
											on:click|stopPropagation={() => selectLeftMonth(month)}
										>
											{new Date(0, month).toLocaleString('default', { month: 'long' })}
										</button>
									{/each}
								</div>
							{:else if leftView === 'year'}
								<!-- Year Selection -->
								<div class="grid grid-cols-3 gap-1 px-4 py-2 text-center">
									{#each getYearsInDecadeForLeft() as year}
										<button
											type="button"
											class="py-1 text-md rounded hover:bg-blue-600 hover:text-white"
											on:click|stopPropagation={() => selectLeftYear(year)}
										>
											{year}
										</button>
									{/each}
								</div>
							{/if}
						</div>
						<div class="w-80 bg-white">
							<div class="flex justify-between items-center py-2 px-4">
								<button
									type="button"
									class="text-gray-600 hover:text-blue-500"
									on:click={() =>
										rightView === 'date'
											? changeRightMonth(-1)
											: rightView === 'month'
												? changeRightYear(-1)
												: changeRightYear(-10)}
								>
									<Icon iconName="chevron-left" size="sm" />
								</button>
								{#if rightView === 'date'}
									<button
										type="button"
										class="text-md font-medium cursor-pointer"
										on:click|stopPropagation={() => (rightView = 'month')}
									>
										{rightCurrentDate.toLocaleString('default', { month: 'long' })}
										{rightCurrentDate.getFullYear()}
									</button>
								{:else if rightView === 'month'}
									<button
										type="button"
										class="text-md font-medium cursor-pointer"
										on:click|stopPropagation={() => (rightView = 'year')}
									>
										{rightCurrentDate.getFullYear()}
									</button>
								{:else if rightView === 'year'}
									<span class="text-md font-medium">
										{Math.floor(rightCurrentDate.getFullYear() / 10) * 10} - {Math.floor(
											rightCurrentDate.getFullYear() / 10
										) *
											10 +
											9}
									</span>
								{/if}
								<button
									type="button"
									class="text-gray-600 hover:text-blue-500"
									on:click={() =>
										rightView === 'date'
											? changeRightMonth(1)
											: rightView === 'month'
												? changeRightYear(1)
												: changeRightYear(10)}
								>
									<Icon iconName="chevron-right" size="sm" />
								</button>
							</div>

							<!-- Right Calendar Views -->
							{#if rightView === 'date'}
								<!-- Days of the week -->
								<div
									class="grid grid-cols-7 gap-1 px-4 text-center text-md font-semibold text-stone-400"
								>
									{#if startOfWeek === 'Monday'}
										<div>Mon</div>
										<div>Tue</div>
										<div>Wed</div>
										<div>Thu</div>
										<div>Fri</div>
										<div>Sat</div>
										<div>Sun</div>
									{:else}
										<div>Sun</div>
										<div>Mon</div>
										<div>Tue</div>
										<div>Wed</div>
										<div>Thu</div>
										<div>Fri</div>
										<div>Sat</div>
									{/if}
								</div>

								<!-- Days -->
								<div class="grid grid-cols-7 gap-y-0.5 px-4 py-2 text-center">
									{#each Array(getOffset(firstDayOfMonth(rightCurrentDate.getMonth(), rightCurrentDate.getFullYear()))).fill('') as _}
										<div class="text-transparent">{_}</div>
									{/each}

									{#each Array(daysInMonth(rightCurrentDate.getMonth(), rightCurrentDate.getFullYear()))
										.fill('')
										.map((_, i) => i + 1) as day}
										{@const date = new Date(
											rightCurrentDate.getFullYear(),
											rightCurrentDate.getMonth(),
											day
										)}
										<button
											type="button"
											class={getRangeCellClasses(date)}
											on:click|stopPropagation={() => selectRightDate(day)}
											disabled={isDateDisabled(date)}
										>
											{day}
										</button>
									{/each}
								</div>
							{:else if rightView === 'month'}
								<!-- Month Selection -->
								<div class="grid grid-cols-3 gap-1 px-4 py-2 text-center">
									{#each Array.from({ length: 12 }).map((_, i) => i) as month}
										<button
											type="button"
											class="py-1 text-md h-8 rounded hover:bg-blue-600 hover:text-white"
											on:click|stopPropagation={() => selectRightMonth(month)}
										>
											{new Date(0, month).toLocaleString('default', { month: 'long' })}
										</button>
									{/each}
								</div>
							{:else if rightView === 'year'}
								<!-- Year Selection -->
								<div class="grid grid-cols-3 gap-1 px-4 py-2 text-center">
									{#each getYearsInDecadeForRight() as year}
										<button
											type="button"
											class="py-1 text-md rounded hover:bg-blue-600 hover:text-white"
											on:click|stopPropagation={() => selectRightYear(year)}
										>
											{year}
										</button>
									{/each}
								</div>
							{/if}
						</div>
					</div>
					<div class="w-full flex px-4 pb-4 gap-2">
						<Button
							type="button"
							on:click={() => (showCalendar = false)}
							size="sm"
							appearance="flat"
							color="base"
							className="w-full justify-center"
						>
							Cancel
						</Button>
						<Button
							type="button"
							on:click={() => {
								if (leftValue && rightValue) {
									// Trigger parent binding updates
									leftValue = new Date(leftValue);
									rightValue = new Date(rightValue);
								}
								showCalendar = false;
							}}
							size="sm"
							appearance="flat"
							color="blue"
							className="w-full justify-center"
						>
							Apply
						</Button>
					</div>
				</div>
			{/if}
		{/if}
	</div>
</div>

<style>
	.disabled {
		pointer-events: none;
		opacity: 0.6;
	}
</style>
