// 인기 메뉴 카드와 갤러리 사진이 화면에 들어올 때 차례로 표시
const revealTargets = document.querySelectorAll(".menu-card, .gallery-item");
const prefersReducedMotion = window.matchMedia(
  "(prefers-reduced-motion: reduce)"
).matches;

if (prefersReducedMotion || !("IntersectionObserver" in window)) {
  revealTargets.forEach(function (target) {
    target.classList.add("is-revealed");
  });
} else {
  revealTargets.forEach(function (target, index) {
    target.classList.add("reveal-on-scroll");
    target.style.setProperty("--reveal-delay", `${(index % 6) * 70}ms`);
  });

  const revealObserver = new IntersectionObserver(
    function (entries, observer) {
      entries.forEach(function (entry) {
        if (!entry.isIntersecting) {
          return;
        }

        entry.target.classList.add("is-revealed");
        observer.unobserve(entry.target);
      });
    },
    {
      threshold: 0.15
    }
  );

  revealTargets.forEach(function (target) {
    revealObserver.observe(target);
  });
}

// 모바일 메뉴 열기와 닫기
const mobileMenuButton = document.querySelector(".mobile-menu-button");
const mainNavigation = document.querySelector(".main-navigation");
const navigationLinks = document.querySelectorAll(".main-navigation a");

mobileMenuButton.addEventListener("click", function () {
  const isMenuOpen = mainNavigation.classList.toggle("is-open");

  mobileMenuButton.classList.toggle("is-open");
  mobileMenuButton.setAttribute("aria-expanded", isMenuOpen);
  mobileMenuButton.setAttribute(
    "aria-label",
    isMenuOpen ? "메뉴 닫기" : "메뉴 열기"
  );
});

// 메뉴 링크를 누르면 모바일 메뉴 닫기
navigationLinks.forEach(function (link) {
  link.addEventListener("click", function () {
    mainNavigation.classList.remove("is-open");
    mobileMenuButton.classList.remove("is-open");
    mobileMenuButton.setAttribute("aria-expanded", "false");
    mobileMenuButton.setAttribute("aria-label", "메뉴 열기");
  });
});

// 현재 보고 있는 영역의 상단 메뉴 강조와 맨 위로 이동
const sectionNavigationLinks = document.querySelectorAll(
  '.main-navigation a[href="#about"], .main-navigation a[href="#menu"], .main-navigation a[href="#gallery"], .main-navigation a[href="#reviews"], .main-navigation a[href="#faq"], .main-navigation a[href="#reservation"]'
);
const trackedSections = Array.from(sectionNavigationLinks).map(function (link) {
  return document.querySelector(link.getAttribute("href"));
});
const scrollTopButton = document.querySelector(".scroll-top-button");

function updateScrollNavigation() {
  const topClearPoint = 120;
  const currentPoint = window.scrollY + window.innerHeight * 0.35;
  let activeSectionId = "";

  if (window.scrollY > topClearPoint) {
    trackedSections.forEach(function (section) {
      if (
        section &&
        currentPoint >= section.offsetTop &&
        currentPoint < section.offsetTop + section.offsetHeight
      ) {
        activeSectionId = section.id;
      }
    });
  }

  sectionNavigationLinks.forEach(function (link) {
    const isActive = link.getAttribute("href") === `#${activeSectionId}`;

    link.classList.toggle("is-current", isActive);

    if (isActive) {
      link.setAttribute("aria-current", "true");
    } else {
      link.removeAttribute("aria-current");
    }
  });

  scrollTopButton.classList.toggle(
    "is-visible",
    window.scrollY >= window.innerHeight
  );
}

window.addEventListener("scroll", updateScrollNavigation, { passive: true });
window.addEventListener("resize", updateScrollNavigation);
window.addEventListener("load", updateScrollNavigation);

scrollTopButton.addEventListener("click", function () {
  window.scrollTo({
    top: 0,
    behavior: "smooth"
  });
});

updateScrollNavigation();

// 인기 메뉴 검색과 조건 필터
const menuSearchInput = document.querySelector("#menu-search");
const menuCards = document.querySelectorAll(".menu-card");
const menuNoResults = document.querySelector(".menu-no-results");
const menuFilterButtons = document.querySelectorAll(".menu-filter-button");
const menuFilterClearButton = document.querySelector(".menu-filter-clear");
const menuFavoritesFilterButton = document.querySelector(".menu-favorites-filter");
const menuFavoritesCount = document.querySelector(".menu-favorites-count");
const menuFavoritesClearButton = document.querySelector(".menu-favorites-clear");
const menuGrid = document.querySelector(".menu-grid");
const menuSliderDots = document.querySelectorAll(".menu-slider-dot");
const mobileMenuSliderMedia = window.matchMedia("(max-width: 560px)");
const favoriteToast = document.querySelector(".favorite-toast");
let favoriteToastTimer;
let menuSliderScrollFrame;
let menuSliderSnapTimer;

function showFavoriteToast(message) {
  window.clearTimeout(favoriteToastTimer);
  favoriteToast.textContent = message;
  favoriteToast.classList.add("is-visible");

  favoriteToastTimer = window.setTimeout(function () {
    favoriteToast.classList.remove("is-visible");
  }, 2000);
}

// 매장 주소와 전화번호 복사 및 기기 공유
const storeName = "멜로우 오븐";
const storeAddressText = document.querySelector(".store-address-text");
const storePhoneText = document.querySelector(".store-phone-text");
const storeAddressCopyButton = document.querySelector(".store-address-copy-button");
const storePhoneCopyButton = document.querySelector(".store-phone-copy-button");
const storeShareButton = document.querySelector(".store-share-button");

async function copyStoreInformation(copyText, successMessage) {
  try {
    if (navigator.clipboard && window.isSecureContext) {
      await navigator.clipboard.writeText(copyText);
    } else {
      const temporaryTextarea = document.createElement("textarea");
      temporaryTextarea.value = copyText;
      temporaryTextarea.setAttribute("readonly", "");
      temporaryTextarea.style.position = "fixed";
      temporaryTextarea.style.opacity = "0";
      document.body.appendChild(temporaryTextarea);
      temporaryTextarea.select();

      const copied = document.execCommand("copy");
      temporaryTextarea.remove();

      if (!copied) {
        throw new Error("복사 기능을 사용할 수 없습니다.");
      }
    }

    showFavoriteToast(successMessage);
  } catch (error) {
    showFavoriteToast("복사하지 못했습니다");
  }
}

storeAddressCopyButton.addEventListener("click", function () {
  copyStoreInformation(
    storeAddressText.textContent.trim(),
    "주소를 복사했습니다"
  );
});

storePhoneCopyButton.addEventListener("click", function () {
  copyStoreInformation(
    storePhoneText.textContent.replace(/\D/g, ""),
    "전화번호를 복사했습니다"
  );
});

if (typeof navigator.share === "function") {
  storeShareButton.hidden = false;

  storeShareButton.addEventListener("click", async function () {
    const storeAddress = storeAddressText.textContent.trim();
    const storePhone = storePhoneText.textContent.trim();

    try {
      await navigator.share({
        title: storeName,
        text: `${storeName}\n주소: ${storeAddress}\n전화번호: ${storePhone}`
      });
    } catch (error) {
      if (error.name !== "AbortError") {
        console.error("매장 정보를 공유하지 못했습니다.", error);
      }
    }
  });
}

const favoriteStorageKey = "mellow-favorites";
let selectedCategory = "전체";
let showFavoritesOnly = false;
const excludedIngredients = new Set();
let menuSearchTimer;
let favoriteMenuNames = loadFavoriteMenuNames();

function loadFavoriteMenuNames() {
  try {
    const savedFavorites = JSON.parse(window.localStorage.getItem(favoriteStorageKey) || "[]");
    return new Set(Array.isArray(savedFavorites) ? savedFavorites.filter(function (name) { return typeof name === "string"; }) : []);
  } catch (error) {
    return new Set();
  }
}

function saveFavoriteMenuNames() {
  window.localStorage.setItem(favoriteStorageKey, JSON.stringify(Array.from(favoriteMenuNames)));
}

function setMenuFilterButtonState(button, isSelected) {
  button.classList.toggle("is-selected", isSelected);
  button.setAttribute("aria-pressed", String(isSelected));
}

function updateCategoryButtons() {
  document.querySelectorAll('[data-filter-type="category"]').forEach(function (button) {
    setMenuFilterButtonState(button, button.dataset.filterValue === selectedCategory);
  });
}

function updateFavoriteButtons() {
  menuCards.forEach(function (card) {
    const menuName = card.querySelector("h3").textContent.trim();
    const favoriteButton = card.querySelector(".menu-favorite-button");
    const isFavorite = favoriteMenuNames.has(menuName);
    favoriteButton.classList.toggle("is-selected", isFavorite);
    favoriteButton.setAttribute("aria-pressed", String(isFavorite));
    favoriteButton.setAttribute("aria-label", isFavorite ? `${menuName} 즐겨찾기에서 빼기` : `${menuName} 즐겨찾기에 담기`);
    favoriteButton.textContent = isFavorite ? "♥" : "♡";
  });
  menuFavoritesCount.textContent = favoriteMenuNames.size;
  menuFavoritesClearButton.disabled = favoriteMenuNames.size === 0;
  setMenuFilterButtonState(menuFavoritesFilterButton, showFavoritesOnly);
}

function getVisibleMenuCards() {
  return Array.from(menuCards).filter(function (card) {
    return !card.hidden;
  });
}

function getMenuCardScrollLeft(card) {
  const gridRect = menuGrid.getBoundingClientRect();
  const cardRect = card.getBoundingClientRect();
  return menuGrid.scrollLeft + cardRect.left - gridRect.left;
}

function getNearestVisibleMenuCard() {
  const visibleCards = getVisibleMenuCards();

  if (visibleCards.length === 0) {
    return null;
  }

  return visibleCards.reduce(function (nearestCard, card) {
    const nearestDistance = Math.abs(
      getMenuCardScrollLeft(nearestCard) - menuGrid.scrollLeft
    );
    const cardDistance = Math.abs(
      getMenuCardScrollLeft(card) - menuGrid.scrollLeft
    );

    return cardDistance < nearestDistance ? card : nearestCard;
  });
}

function updateMenuSliderDots() {
  const nearestCard = mobileMenuSliderMedia.matches
    ? getNearestVisibleMenuCard()
    : getVisibleMenuCards()[0] || null;
  const activeCardIndex = nearestCard
    ? Array.from(menuCards).indexOf(nearestCard)
    : -1;

  menuSliderDots.forEach(function (dot, index) {
    const matchingCard = menuCards[index];
    const isAvailable = Boolean(matchingCard && !matchingCard.hidden);
    const isActive = isAvailable && index === activeCardIndex;

    dot.hidden = !isAvailable;
    dot.classList.toggle("is-active", isActive);

    if (isActive) {
      dot.setAttribute("aria-current", "true");
    } else {
      dot.removeAttribute("aria-current");
    }
  });
}

function requestMenuSliderDotUpdate() {
  window.cancelAnimationFrame(menuSliderScrollFrame);
  menuSliderScrollFrame = window.requestAnimationFrame(updateMenuSliderDots);
}

function snapMenuSliderToNearestCard() {
  if (!mobileMenuSliderMedia.matches) {
    return;
  }

  const nearestCard = getNearestVisibleMenuCard();

  if (!nearestCard) {
    updateMenuSliderDots();
    return;
  }

  const targetLeft = getMenuCardScrollLeft(nearestCard);

  if (Math.abs(targetLeft - menuGrid.scrollLeft) > 1) {
    menuGrid.scrollTo({
      left: targetLeft,
      behavior: prefersReducedMotion ? "auto" : "smooth"
    });
  }

  updateMenuSliderDots();
}

function resetMenuSliderAfterFilter() {
  if (mobileMenuSliderMedia.matches) {
    menuGrid.scrollTo({ left: 0, behavior: "auto" });
  } else {
    menuGrid.scrollLeft = 0;
  }

  window.requestAnimationFrame(updateMenuSliderDots);
}

menuGrid.addEventListener(
  "scroll",
  function () {
    requestMenuSliderDotUpdate();
    window.clearTimeout(menuSliderSnapTimer);
    menuSliderSnapTimer = window.setTimeout(snapMenuSliderToNearestCard, 140);
  },
  { passive: true }
);

if ("onscrollend" in window) {
  menuGrid.addEventListener("scrollend", snapMenuSliderToNearestCard);
}

menuSliderDots.forEach(function (dot) {
  dot.addEventListener("click", function () {
    if (!mobileMenuSliderMedia.matches) {
      return;
    }

    const card = menuCards[Number(dot.dataset.menuSlideIndex)];

    if (!card || card.hidden) {
      return;
    }

    menuGrid.scrollTo({
      left: getMenuCardScrollLeft(card),
      behavior: prefersReducedMotion ? "auto" : "smooth"
    });
  });
});

function handleMenuSliderBreakpointChange() {
  if (!mobileMenuSliderMedia.matches) {
    menuGrid.scrollLeft = 0;
  }

  window.requestAnimationFrame(updateMenuSliderDots);
}

if (typeof mobileMenuSliderMedia.addEventListener === "function") {
  mobileMenuSliderMedia.addEventListener("change", handleMenuSliderBreakpointChange);
} else {
  mobileMenuSliderMedia.addListener(handleMenuSliderBreakpointChange);
}

window.addEventListener("resize", requestMenuSliderDotUpdate);

function getActiveMenuConditions() {
  const conditions = [];
  const searchTerm = menuSearchInput.value.trim();
  if (searchTerm) conditions.push(`검색어 ‘${searchTerm}’`);
  if (selectedCategory !== "전체") conditions.push(`종류 ‘${selectedCategory}’`);
  excludedIngredients.forEach(function (ingredient) { conditions.push(`‘${ingredient} 없는 것’`); });
  if (showFavoritesOnly) conditions.push("내가 고른 메뉴");
  return conditions;
}

function applyMenuFilters() {
  const searchTerm = menuSearchInput.value.trim().toLowerCase();
  let visibleCardCount = 0;
  menuCards.forEach(function (card) {
    const menuName = card.querySelector("h3").textContent.trim();
    const menuDescription = card.querySelector(".menu-card-content > p").textContent;
    const searchableText = `${menuName} ${menuDescription}`.toLowerCase();
    const category = card.dataset.category || "";
    const ingredients = (card.dataset.ingredients || "").split(/\s+/).filter(Boolean);
    const matchesSearch = searchableText.includes(searchTerm);
    const matchesCategory = selectedCategory === "전체" || category === selectedCategory;
    const matchesIngredients = Array.from(excludedIngredients).every(function (ingredient) { return !ingredients.includes(ingredient); });
    const matchesFavorites = !showFavoritesOnly || favoriteMenuNames.has(menuName);
    const isMatch = matchesSearch && matchesCategory && matchesIngredients && matchesFavorites;
    card.hidden = !isMatch;
    if (isMatch) visibleCardCount += 1;
  });

  resetMenuSliderAfterFilter();

  const hasNoResults = visibleCardCount === 0;
  menuNoResults.classList.toggle("is-visible", hasNoResults);
  if (!hasNoResults) { menuNoResults.textContent = ""; return; }
  if (showFavoritesOnly && favoriteMenuNames.size === 0) {
    menuNoResults.textContent = "아직 고른 메뉴가 없습니다. 하트를 눌러 담아 보세요.";
    return;
  }
  const activeConditions = getActiveMenuConditions();
  const conditionText = activeConditions.length > 0 ? `현재 조건: ${activeConditions.join(", ")}. ` : "";
  menuNoResults.textContent = `${conditionText}조건에 맞는 메뉴가 없습니다. 조건을 하나 줄여 보세요.`;
}

menuSearchInput.addEventListener("input", function () {
  window.clearTimeout(menuSearchTimer);
  menuSearchTimer = window.setTimeout(applyMenuFilters, 300);
});

menuFilterButtons.forEach(function (button) {
  button.addEventListener("click", function () {
    const filterType = button.dataset.filterType;
    const filterValue = button.dataset.filterValue;
    if (filterType === "category") {
      if (filterValue === "전체") selectedCategory = "전체";
      else if (selectedCategory === filterValue) selectedCategory = "전체";
      else selectedCategory = filterValue;
      updateCategoryButtons();
    }
    if (filterType === "exclude") {
      if (excludedIngredients.has(filterValue)) {
        excludedIngredients.delete(filterValue);
        setMenuFilterButtonState(button, false);
      } else {
        excludedIngredients.add(filterValue);
        setMenuFilterButtonState(button, true);
      }
    }
    if (filterType === "favorites") {
      showFavoritesOnly = !showFavoritesOnly;
      setMenuFilterButtonState(button, showFavoritesOnly);
    }
    window.clearTimeout(menuSearchTimer);
    applyMenuFilters();
  });
});

document.querySelectorAll(".menu-favorite-button").forEach(function (button) {
  button.addEventListener("click", function (event) {
    event.preventDefault();
    event.stopPropagation();
    const card = button.closest(".menu-card");
    const menuName = card.querySelector("h3").textContent.trim();
    let favoriteMessage;

    if (favoriteMenuNames.has(menuName)) {
      favoriteMenuNames.delete(menuName);
      favoriteMessage = "즐겨찾기에서 뺐습니다";
    } else {
      favoriteMenuNames.add(menuName);
      favoriteMessage = "즐겨찾기에 담았습니다";
    }

    saveFavoriteMenuNames();
    updateFavoriteButtons();
    applyMenuFilters();
    showFavoriteToast(favoriteMessage);
  });
});

menuFavoritesClearButton.addEventListener("click", function () {
  if (favoriteMenuNames.size === 0) return;
  if (!window.confirm("고른 메뉴를 모두 지울까요?")) return;
  favoriteMenuNames.clear();
  saveFavoriteMenuNames();
  updateFavoriteButtons();
  applyMenuFilters();
});

menuFilterClearButton.addEventListener("click", function () {
  window.clearTimeout(menuSearchTimer);
  menuSearchInput.value = "";
  selectedCategory = "전체";
  showFavoritesOnly = false;
  excludedIngredients.clear();
  updateCategoryButtons();
  document.querySelectorAll('[data-filter-type="exclude"]').forEach(function (button) { setMenuFilterButtonState(button, false); });
  setMenuFilterButtonState(menuFavoritesFilterButton, false);
  applyMenuFilters();
  menuSearchInput.focus();
});

updateFavoriteButtons();
applyMenuFilters();

// FAQ 답변 열기와 닫기
const faqButtons = document.querySelectorAll(".faq-button");

faqButtons.forEach(function (button) {
  button.addEventListener("click", function () {
    const currentFaqItem = button.closest(".faq-item");
    const wasOpen = currentFaqItem.classList.contains("is-open");

    faqButtons.forEach(function (otherButton) {
      const otherFaqItem = otherButton.closest(".faq-item");

      otherFaqItem.classList.remove("is-open");
      otherButton.setAttribute("aria-expanded", "false");
    });

    if (!wasOpen) {
      currentFaqItem.classList.toggle("is-open");
      button.setAttribute("aria-expanded", "true");
    }
  });
});

// FAQ 질문과 답변 검색
const faqSearchInput = document.querySelector("#faq-search");
const faqItems = document.querySelectorAll(".faq-item");
const faqNoResults = document.querySelector(".faq-no-results");

faqSearchInput.addEventListener("input", function () {
  const searchTerm = faqSearchInput.value.trim().toLowerCase();
  let visibleItemCount = 0;

  faqItems.forEach(function (item) {
    const question = item.querySelector(".faq-button span:first-child").textContent;
    const answer = item.querySelector(".faq-answer").textContent;
    const faqText = `${question} ${answer}`.toLowerCase();
    const isMatch = faqText.includes(searchTerm);

    item.hidden = !isMatch;

    if (isMatch) {
      visibleItemCount += 1;
    } else {
      item.classList.remove("is-open");
      item.querySelector(".faq-button").setAttribute("aria-expanded", "false");
    }
  });

  faqNoResults.classList.toggle("is-visible", visibleItemCount === 0);
});

// 갤러리 이미지 확대 모달
const galleryItems = document.querySelectorAll(".gallery-item");
const galleryModal = document.querySelector(".gallery-modal");
const modalImage = document.querySelector(".modal-image");
const modalCloseButton = document.querySelector(".modal-close-button");
const modalPreviousButton = document.querySelector(".modal-previous-button");
const modalNextButton = document.querySelector(".modal-next-button");
const modalCounter = document.querySelector(".modal-counter");
const modalDescription = document.querySelector(".modal-description");
let currentGalleryIndex = 0;

function updateGalleryModal() {
  const currentItem = galleryItems[currentGalleryIndex];
  const currentImage = currentItem.querySelector("img");

  modalImage.src = currentItem.dataset.fullImage;
  modalImage.alt = currentImage.alt;
  modalCounter.textContent = `${currentGalleryIndex + 1} / ${galleryItems.length}`;
  modalDescription.textContent = currentImage.alt;

  const isFirstImage = currentGalleryIndex === 0;
  const isLastImage = currentGalleryIndex === galleryItems.length - 1;

  modalPreviousButton.disabled = isFirstImage;
  modalNextButton.disabled = isLastImage;
}

function openGalleryModal(imageIndex) {
  currentGalleryIndex = imageIndex;
  updateGalleryModal();
  galleryModal.classList.add("is-open");
  galleryModal.setAttribute("aria-hidden", "false");
  document.body.classList.add("modal-open");
  modalCloseButton.focus();
}

function closeGalleryModal() {
  galleryModal.classList.remove("is-open");
  galleryModal.setAttribute("aria-hidden", "true");
  document.body.classList.remove("modal-open");
  modalImage.src = "";
  modalImage.alt = "";
  modalCounter.textContent = "";
  modalDescription.textContent = "";
}

function showPreviousImage() {
  if (currentGalleryIndex > 0) {
    currentGalleryIndex -= 1;
    updateGalleryModal();
  }
}

function showNextImage() {
  if (currentGalleryIndex < galleryItems.length - 1) {
    currentGalleryIndex += 1;
    updateGalleryModal();
  }
}

galleryItems.forEach(function (item, index) {
  item.addEventListener("click", function () {
    openGalleryModal(index);
  });
});

modalPreviousButton.addEventListener("click", showPreviousImage);
modalNextButton.addEventListener("click", showNextImage);
modalCloseButton.addEventListener("click", closeGalleryModal);

galleryModal.addEventListener("click", function (event) {
  if (event.target === galleryModal) {
    closeGalleryModal();
  }
});

document.addEventListener("keydown", function (event) {
  if (!galleryModal.classList.contains("is-open")) {
    return;
  }

  if (event.key === "Escape") {
    closeGalleryModal();
  } else if (event.key === "ArrowLeft") {
    showPreviousImage();
  } else if (event.key === "ArrowRight") {
    showNextImage();
  }
});

// 예약 폼 칸별 검사와 필수 입력 상태 확인
const reservationForm = document.querySelector("#reservation-form");
const customerName = document.querySelector("#customer-name");
const customerPhone = document.querySelector("#customer-phone");
const visitDate = document.querySelector("#visit-date");
const visitTime = document.querySelector("#visit-time");
const visitDateNotice = document.querySelector("#visit-date-notice");
const guestCount = document.querySelector("#guest-count");
const inquiryMessage = document.querySelector("#inquiry-message");
const reservationProduct = document.querySelector("#reservation-product");
const reservationQuantity = document.querySelector("#reservation-quantity");
const cakeSizeFieldset = document.querySelector("#cake-size-fieldset");
const cakeOptionsFieldset = document.querySelector("#cake-options-fieldset");
const cakeSizeInputs = document.querySelectorAll('input[name="cakeSize"]');
const cakeOptionInputs = document.querySelectorAll('input[name="cakeOption"]');
const formSubmitButton = document.querySelector(".form-submit-button");
const formRequiredStatus = document.querySelector("#form-required-status");
const formSuccessMessage = document.querySelector("#form-success-message");
const reservationFormArea = document.querySelector(".reservation-form-area");
const reservationSummary = document.querySelector("#reservation-summary");
const reservationSubmissionResult = document.querySelector("#reservation-submission-result");
const newReservationButton = document.querySelector(".new-reservation-button");
const submittedCustomerName = document.querySelector("#submitted-customer-name");
const submittedCustomerPhone = document.querySelector("#submitted-customer-phone");
const submittedReservationDate = document.querySelector("#submitted-reservation-date");
const submittedReservationTime = document.querySelector("#submitted-reservation-time");
const submittedReservationGuests = document.querySelector("#submitted-reservation-guests");
const submittedReservationProduct = document.querySelector("#submitted-reservation-product");
const submittedReservationSize = document.querySelector("#submitted-reservation-size");
const submittedReservationOptions = document.querySelector("#submitted-reservation-options");
const submittedReservationQuantity = document.querySelector("#submitted-reservation-quantity");
const submittedInquiryMessage = document.querySelector("#submitted-inquiry-message");
const submittedReservationPrice = document.querySelector("#submitted-reservation-price");
const reservationDraftRestore = document.querySelector("#reservation-draft-restore");
const reservationDraftClearButton = document.querySelector(".reservation-draft-clear");
const reservationDraftSaveStatus = document.querySelector("#reservation-draft-save-status");

// 휴무일은 이곳에서 한 번에 수정
const reservationClosures = {
  weeklyDays: [2], // 0: 일요일, 1: 월요일, 2: 화요일
  annualDates: [
    { month: 8, day: 15, label: "8월 15일 휴무" },
    { month: 9, day: 16, label: "9월 16일 휴무" },
    { month: 9, day: 17, label: "9월 17일 휴무" },
    { month: 9, day: 18, label: "9월 18일 휴무" }
  ]
};

const reservationTimes = ["11:00", "13:00", "15:00", "17:00", "19:00"];

const productPrices = {
  아메리카노: 4500,
  카페라테: 5000,
  "바닐라빈 라테": 5500,
  "버터 크루아상": 4200,
  소금빵: 3500,
  "딸기 생크림 케이크": 7000
};

function isCakeProduct() {
  return reservationProduct.value === "딸기 생크림 케이크";
}

function getSelectedCakeSizeInput() {
  return document.querySelector('input[name="cakeSize"]:checked');
}

function getSelectedCakeSize() {
  const selectedInput = getSelectedCakeSizeInput();
  return selectedInput ? selectedInput.value : "";
}

function getSelectedCakeOptions() {
  return Array.from(cakeOptionInputs)
    .filter(function (input) {
      return input.checked;
    })
    .map(function (input) {
      return {
        name: input.value,
        price: Number(input.dataset.price) || 0
      };
    });
}

const reservationFields = [
  {
    input: customerName,
    errorSelector: "#customer-name-error",
    emptyMessage: "예약자 이름을 입력해 주세요.",
    validate: function () {
      return customerName.value.trim() !== "";
    }
  },
  {
    input: customerPhone,
    errorSelector: "#customer-phone-error",
    emptyMessage: "연락받을 전화번호를 입력해 주세요.",
    invalidMessage: "휴대전화 또는 02로 시작하는 전화번호를 입력해 주세요.",
    validate: function () {
      return isValidPhoneNumber(customerPhone.value);
    }
  },
  {
    input: visitDate,
    errorSelector: "#visit-date-error",
    emptyMessage: "방문할 날짜를 선택해 주세요.",
    invalidMessage: "오늘 이후의 날짜를 선택해 주세요.",
    validate: function () {
      return isSelectableDate(visitDate.value);
    }
  },
  {
    input: visitTime,
    errorSelector: "#visit-time-error",
    emptyMessage: "방문할 시간을 선택해 주세요.",
    invalidMessage: "선택할 수 있는 방문 시간을 다시 골라 주세요.",
    validate: function () {
      return isSelectedTimeAvailable();
    }
  },
  {
    input: guestCount,
    errorSelector: "#guest-count-error",
    emptyMessage: "방문 인원을 선택해 주세요.",
    validate: function () {
      return guestCount.value !== "";
    }
  },
  {
    input: inquiryMessage,
    errorSelector: "#inquiry-message-error",
    emptyMessage: "예약 목적이나 문의 내용을 입력해 주세요.",
    validate: function () {
      return inquiryMessage.value.trim() !== "";
    }
  },
  {
    input: reservationProduct,
    errorSelector: "#reservation-product-error",
    emptyMessage: "예약할 제품 또는 제품 예약 없음을 선택해 주세요.",
    validate: function () {
      return reservationProduct.value !== "";
    }
  },
  {
    input: reservationQuantity,
    errorSelector: "#reservation-quantity-error",
    emptyMessage: "예약할 수량을 선택해 주세요.",
    validate: function () {
      if (reservationProduct.value === "제품 예약 없음") {
        return true;
      }

      return reservationProduct.value !== "" && reservationQuantity.value !== "";
    }
  },
  {
    input: cakeSizeFieldset,
    errorSelector: "#cake-size-error",
    emptyMessage: "케이크 크기를 선택해 주세요.",
    validate: function () {
      return !isCakeProduct() || getSelectedCakeSize() !== "";
    }
  }
];

function padDateNumber(value) {
  return String(value).padStart(2, "0");
}

function formatLocalDate(date) {
  return [
    date.getFullYear(),
    padDateNumber(date.getMonth() + 1),
    padDateNumber(date.getDate())
  ].join("-");
}

function parseLocalDate(value) {
  if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
    return null;
  }

  const parts = value.split("-").map(Number);
  return new Date(parts[0], parts[1] - 1, parts[2]);
}

function getTodayAtMidnight() {
  const now = new Date();
  return new Date(now.getFullYear(), now.getMonth(), now.getDate());
}

function isSelectableDate(value) {
  const selectedDate = parseLocalDate(value);

  if (!selectedDate) {
    return false;
  }

  return selectedDate >= getTodayAtMidnight();
}

function getClosureReason(date) {
  if (reservationClosures.weeklyDays.includes(date.getDay())) {
    return "매주 화요일은 휴무입니다.";
  }

  const annualClosure = reservationClosures.annualDates.find(function (closure) {
    return (
      closure.month === date.getMonth() + 1 &&
      closure.day === date.getDate()
    );
  });

  return annualClosure ? `${annualClosure.label}입니다.` : "";
}

function getClosingHour(date) {
  return date.getDay() === 0 ? 15 : 19;
}

function isToday(date) {
  return formatLocalDate(date) === formatLocalDate(new Date());
}

function getTimeOption(value) {
  return Array.from(visitTime.options).find(function (option) {
    return option.value === value;
  });
}

function isTimeAvailableForDate(timeValue, selectedDate) {
  if (!selectedDate || getClosureReason(selectedDate)) {
    return false;
  }

  const hour = Number(timeValue.split(":")[0]);

  if (hour > getClosingHour(selectedDate)) {
    return false;
  }

  if (isToday(selectedDate)) {
    const earliestReservationTime = new Date(Date.now() + 2 * 60 * 60 * 1000);
    const slotDateTime = new Date(
      selectedDate.getFullYear(),
      selectedDate.getMonth(),
      selectedDate.getDate(),
      hour,
      0,
      0,
      0
    );

    if (slotDateTime < earliestReservationTime) {
      return false;
    }
  }

  return true;
}

function updateTimeOptions(options) {
  const settings = options || {};
  const selectedDate = parseLocalDate(visitDate.value);
  const previousTime = visitTime.value;
  const closureReason = selectedDate ? getClosureReason(selectedDate) : "";
  const dateCanBeUsed = Boolean(selectedDate && isSelectableDate(visitDate.value));
  let previousTimeBecameUnavailable = false;

  visitDateNotice.textContent = "";

  reservationTimes.forEach(function (timeValue) {
    const option = getTimeOption(timeValue);
    const isAvailable =
      dateCanBeUsed &&
      !closureReason &&
      isTimeAvailableForDate(timeValue, selectedDate);

    option.disabled = !isAvailable;
    option.textContent = isAvailable ? timeValue : `${timeValue} (마감)`;
  });

  visitTime.disabled = !dateCanBeUsed || Boolean(closureReason);

  if (!selectedDate) {
    visitDateNotice.textContent = "날짜를 고르면 예약 가능한 시간이 표시됩니다.";
  } else if (!dateCanBeUsed) {
    visitDateNotice.textContent = "오늘 이후의 날짜만 예약할 수 있습니다.";
  } else if (closureReason) {
    visitDateNotice.textContent = closureReason;
  } else if (selectedDate.getDay() === 0) {
    visitDateNotice.textContent = "일요일은 15시까지 예약할 수 있습니다.";
  } else if (isToday(selectedDate)) {
    visitDateNotice.textContent = "오늘은 현재 시각에서 두 시간 뒤의 시간부터 예약할 수 있습니다.";
  } else {
    visitDateNotice.textContent = "평일과 토요일은 19시까지 예약할 수 있습니다.";
  }

  if (previousTime) {
    const previousOption = getTimeOption(previousTime);
    previousTimeBecameUnavailable = !previousOption || previousOption.disabled;

    if (previousTimeBecameUnavailable) {
      visitTime.value = "";

      if (settings.showChangedTimeMessage) {
        showError(
          reservationFields[3],
          "날짜에 맞는 방문 시간을 다시 골라 주세요."
        );
      }
    }
  }

  if (!previousTimeBecameUnavailable && visitTime.dataset.hadError === "true") {
    validateField(reservationFields[3], true);
  }

  updateRequiredStatus();
}

function isSelectedTimeAvailable() {
  if (!visitTime.value || visitTime.disabled) {
    return false;
  }

  const selectedOption = getTimeOption(visitTime.value);
  return Boolean(selectedOption && !selectedOption.disabled);
}

function getPhoneDigits(value) {
  return value.replace(/\D/g, "");
}

function isValidPhoneNumber(value) {
  const digits = getPhoneDigits(value);
  const isMobilePhone = /^010\d{8}$/.test(digits);
  const isSeoulPhone = /^02\d{7}$/.test(digits) || /^02\d{8}$/.test(digits);

  return isMobilePhone || isSeoulPhone;
}

function formatPhoneNumber(value) {
  const digits = getPhoneDigits(value);

  if (/^010\d{8}$/.test(digits)) {
    return `${digits.slice(0, 3)}-${digits.slice(3, 7)}-${digits.slice(7)}`;
  }

  if (/^02\d{7}$/.test(digits)) {
    return `${digits.slice(0, 2)}-${digits.slice(2, 5)}-${digits.slice(5)}`;
  }

  if (/^02\d{8}$/.test(digits)) {
    return `${digits.slice(0, 2)}-${digits.slice(2, 6)}-${digits.slice(6)}`;
  }

  return value.trim();
}

function showError(field, message) {
  const errorElement = document.querySelector(field.errorSelector);

  field.input.classList.add("input-error");
  field.input.setAttribute("aria-invalid", "true");
  field.input.dataset.hadError = "true";
  errorElement.textContent = message;
}

function clearError(field) {
  const errorElement = document.querySelector(field.errorSelector);

  field.input.classList.remove("input-error");
  field.input.removeAttribute("aria-invalid");
  field.input.dataset.hadError = "false";
  errorElement.textContent = "";
}

function getFieldErrorMessage(field) {
  if (field.input === cakeSizeFieldset) {
    return field.emptyMessage;
  }

  const value = field.input.value.trim();

  if (value === "") {
    return field.emptyMessage;
  }

  return field.invalidMessage || field.emptyMessage;
}

function validateField(field, showMessage) {
  const isValid = field.validate();

  if (isValid) {
    clearError(field);
  } else if (showMessage) {
    showError(field, getFieldErrorMessage(field));
  }

  return isValid;
}

function focusReservationField(field) {
  if (field.input === cakeSizeFieldset) {
    const firstEnabledSize = Array.from(cakeSizeInputs).find(function (input) {
      return !input.disabled;
    });

    if (firstEnabledSize) {
      firstEnabledSize.focus();
    }
    return;
  }

  field.input.focus();
}

function updateRequiredStatus() {
  const remainingCount = reservationFields.filter(function (field) {
    return !field.validate();
  }).length;
  const isComplete = remainingCount === 0;

  formSubmitButton.disabled = !isComplete;
  formSubmitButton.setAttribute("aria-disabled", String(!isComplete));

  if (isComplete) {
    formRequiredStatus.textContent = "필수 입력이 모두 완료되었습니다.";
  } else {
    formRequiredStatus.textContent = `필수 입력 ${remainingCount}칸이 남았습니다.`;
  }
}

reservationFields.forEach(function (field) {
  field.input.dataset.hadError = "false";

  if (field.input === cakeSizeFieldset) {
    return;
  }

  field.input.addEventListener("blur", function () {
    if (field.input === customerPhone && isValidPhoneNumber(customerPhone.value)) {
      customerPhone.value = formatPhoneNumber(customerPhone.value);
    }

    validateField(field, true);
    updateRequiredStatus();
  });

  const eventName = field.input.tagName === "SELECT" ? "change" : "input";

  field.input.addEventListener(eventName, function () {
    formSuccessMessage.textContent = "";

    if (field.input.dataset.hadError === "true") {
      validateField(field, true);
    }

    updateRequiredStatus();
  });
});

visitDate.addEventListener("change", function () {
  updateTimeOptions({ showChangedTimeMessage: true });

  if (visitDate.dataset.hadError === "true") {
    validateField(reservationFields[2], true);
  }
});

function resetCakeChoices() {
  cakeSizeInputs.forEach(function (input) {
    input.checked = false;
  });

  cakeOptionInputs.forEach(function (input) {
    input.checked = false;
  });
}

function updateProductDependentFields(resetChoices) {
  const hasProduct = reservationProduct.value !== "";
  const hasNoProductReservation = reservationProduct.value === "제품 예약 없음";
  const cakeSelected = isCakeProduct();

  if (resetChoices) {
    resetCakeChoices();
    clearError(reservationFields[8]);
  }

  cakeSizeFieldset.disabled = !cakeSelected;
  cakeOptionsFieldset.disabled = !cakeSelected;
  cakeSizeFieldset.classList.toggle("is-disabled-group", !cakeSelected);
  cakeOptionsFieldset.classList.toggle("is-disabled-group", !cakeSelected);

  reservationQuantity.disabled = !hasProduct || hasNoProductReservation;
  reservationQuantity.classList.toggle(
    "is-disabled-select",
    !hasProduct || hasNoProductReservation
  );

  if (!hasProduct || hasNoProductReservation) {
    reservationQuantity.value = "";
  }

  if (!cakeSelected) {
    clearError(reservationFields[8]);
  }

  if (!hasProduct || hasNoProductReservation) {
    clearError(reservationFields[7]);
  }
}

reservationForm.addEventListener("submit", function (event) {
  event.preventDefault();
  formSuccessMessage.textContent = "";

  updateTimeOptions();

  let firstInvalidField = null;

  reservationFields.forEach(function (field) {
    if (field.input === customerPhone && isValidPhoneNumber(customerPhone.value)) {
      customerPhone.value = formatPhoneNumber(customerPhone.value);
    }

    const isValid = validateField(field, true);

    if (!isValid && firstInvalidField === null) {
      firstInvalidField = field;
    }
  });

  updateRequiredStatus();

  if (firstInvalidField) {
    focusReservationField(firstInvalidField);
    return;
  }

  openReservationConfirmModal(event.submitter || formSubmitButton);
});

visitDate.min = formatLocalDate(new Date());
updateTimeOptions();

// 예약 요약과 예상 금액
const summaryElements = {
  date: document.querySelector("#summary-date"),
  time: document.querySelector("#summary-time"),
  guests: document.querySelector("#summary-guests"),
  product: document.querySelector("#summary-product"),
  size: document.querySelector("#summary-size"),
  options: document.querySelector("#summary-options"),
  quantity: document.querySelector("#summary-quantity")
};

const mobileSummaryElements = {
  date: document.querySelector("#mobile-summary-date"),
  time: document.querySelector("#mobile-summary-time"),
  guests: document.querySelector("#mobile-summary-guests"),
  product: document.querySelector("#mobile-summary-product"),
  size: document.querySelector("#mobile-summary-size"),
  options: document.querySelector("#mobile-summary-options"),
  quantity: document.querySelector("#mobile-summary-quantity")
};

const reservationSummaryCount = document.querySelector("#reservation-summary-count");
const mobileSummaryCount = document.querySelector("#mobile-summary-count");
const reservationSummaryLive = document.querySelector("#reservation-summary-live");
const mobileSummaryToggle = document.querySelector("#mobile-summary-toggle");
const mobileSummaryPanel = document.querySelector("#mobile-summary-panel");
const priceBreakdown = document.querySelector("#price-breakdown");
const mobilePriceBreakdown = document.querySelector("#mobile-price-breakdown");
const estimatedTotal = document.querySelector("#estimated-total");
const mobileEstimatedTotal = document.querySelector("#mobile-estimated-total");

const koreanWeekdays = ["일", "월", "화", "수", "목", "금", "토"];
const wonFormatter = new Intl.NumberFormat("ko-KR");

function formatWon(value) {
  return `${wonFormatter.format(value)}원`;
}

function formatSignedWon(value) {
  return `+${wonFormatter.format(value)}원`;
}

function formatSummaryDate(value) {
  if (!value) return "";

  const parts = value.split("-").map(Number);
  const date = new Date(parts[0], parts[1] - 1, parts[2]);

  return `${parts[1]}월 ${parts[2]}일 (${koreanWeekdays[date.getDay()]})`;
}

function formatSummaryTime(value) {
  if (!value) return "";

  const hour = Number(value.split(":")[0]);

  if (hour === 12) return "오후 12시";
  if (hour < 12) return `오전 ${hour}시`;

  return `오후 ${hour - 12}시`;
}

function getGuestSummary() {
  if (!guestCount.value) return "";

  const selectedOption = guestCount.options[guestCount.selectedIndex];
  return selectedOption ? selectedOption.textContent.trim() : "";
}

function setSummaryValue(key, value) {
  const desktopElement = summaryElements[key];
  const mobileElement = mobileSummaryElements[key];
  const displayValue = value || "아직 고르지 않음";
  const isEmpty = value === "";

  desktopElement.textContent = displayValue;
  mobileElement.textContent = displayValue;
  desktopElement.classList.toggle("is-empty", isEmpty);
  mobileElement.classList.toggle("is-empty", isEmpty);
}

function calculateEstimatedPrice() {
  const productName = reservationProduct.value;
  const hasNoProductReservation = productName === "제품 예약 없음";
  const basePrice = productPrices[productName] || 0;
  const selectedSizeInput = getSelectedCakeSizeInput();
  const sizeName = isCakeProduct() && selectedSizeInput ? selectedSizeInput.value : "";
  const sizePrice = isCakeProduct() && selectedSizeInput
    ? Number(selectedSizeInput.dataset.price) || 0
    : 0;
  const options = isCakeProduct() ? getSelectedCakeOptions() : [];
  const optionsPrice = options.reduce(function (sum, option) {
    return sum + option.price;
  }, 0);
  const quantity = hasNoProductReservation
    ? 0
    : Number(reservationQuantity.value) || 0;
  const unitPrice = basePrice + sizePrice + optionsPrice;
  const total = unitPrice * quantity;

  return {
    productName,
    hasNoProductReservation,
    basePrice,
    sizeName,
    sizePrice,
    options,
    optionsPrice,
    quantity,
    unitPrice,
    total
  };
}

function createPriceLine(label, value, className) {
  const row = document.createElement("p");
  const labelSpan = document.createElement("span");
  const valueSpan = document.createElement("span");

  row.className = className || "";
  labelSpan.textContent = label;
  valueSpan.textContent = value;
  row.append(labelSpan, valueSpan);

  return row;
}

function renderPriceBreakdown(container, calculation) {
  container.replaceChildren();

  if (!calculation.productName) {
    const emptyMessage = document.createElement("p");
    emptyMessage.className = "price-breakdown-empty";
    emptyMessage.textContent = "제품을 선택하면 금액 내역이 표시됩니다.";
    container.append(emptyMessage);
    return;
  }

  if (calculation.hasNoProductReservation) {
    container.append(createPriceLine("제품 예약 없음", formatWon(0)));
    return;
  }

  container.append(
    createPriceLine(
      `기본 가격 · ${calculation.productName}`,
      formatWon(calculation.basePrice)
    )
  );

  if (isCakeProduct() && calculation.sizeName) {
    container.append(
      createPriceLine(
        `크기 · ${calculation.sizeName}`,
        formatSignedWon(calculation.sizePrice)
      )
    );
  }

  calculation.options.forEach(function (option) {
    container.append(
      createPriceLine(`옵션 · ${option.name}`, formatSignedWon(option.price))
    );
  });

  container.append(
    createPriceLine("1개 예상 금액", formatWon(calculation.unitPrice), "price-subtotal-line")
  );

  container.append(
    createPriceLine(
      "수량",
      calculation.quantity ? `× ${calculation.quantity}` : "아직 고르지 않음",
      "price-quantity-line"
    )
  );
}

function updateEstimatedPrice() {
  const calculation = calculateEstimatedPrice();

  renderPriceBreakdown(priceBreakdown, calculation);
  renderPriceBreakdown(mobilePriceBreakdown, calculation);
  estimatedTotal.textContent = formatWon(calculation.total);
  mobileEstimatedTotal.textContent = formatWon(calculation.total);

  return calculation;
}

function updateReservationSummary(changedLabel) {
  const productName = reservationProduct.value;
  const cakeSelected = isCakeProduct();
  const hasNoProductReservation = productName === "제품 예약 없음";
  const selectedOptions = getSelectedCakeOptions();
  let sizeSummary = "";
  let optionsSummary = "";

  if (productName) {
    if (cakeSelected) {
      sizeSummary = getSelectedCakeSize();
      optionsSummary = selectedOptions.length
        ? selectedOptions.map(function (option) { return option.name; }).join(", ")
        : "선택 안 함";
    } else {
      sizeSummary = "해당 없음";
      optionsSummary = "해당 없음";
    }
  }

  const summaryValues = {
    date: formatSummaryDate(visitDate.value),
    time: formatSummaryTime(visitTime.value),
    guests: getGuestSummary(),
    product: productName,
    size: sizeSummary,
    options: optionsSummary,
    quantity: hasNoProductReservation
      ? "해당 없음"
      : reservationQuantity.value
        ? `${reservationQuantity.value}개`
        : ""
  };

  Object.keys(summaryValues).forEach(function (key) {
    setSummaryValue(key, summaryValues[key]);
  });

  const selectedCount = [
    summaryValues.date,
    summaryValues.time,
    summaryValues.guests,
    summaryValues.product,
    summaryValues.quantity
  ].filter(Boolean).length;

  const countText = `${selectedCount} / 5 선택`;
  reservationSummaryCount.textContent = countText;
  mobileSummaryCount.textContent = countText;

  const calculation = updateEstimatedPrice();

  if (changedLabel) {
    const changedText = {
      날짜: summaryValues.date || "아직 고르지 않음",
      시간: summaryValues.time || "아직 고르지 않음",
      인원: summaryValues.guests || "아직 고르지 않음",
      제품: summaryValues.product || "아직 고르지 않음",
      크기: summaryValues.size || "아직 고르지 않음",
      "추가 옵션": summaryValues.options || "아직 고르지 않음",
      수량: summaryValues.quantity || "아직 고르지 않음"
    }[changedLabel];

    reservationSummaryLive.textContent =
      `${changedLabel} 요약이 ${changedText}(으)로 바뀌었습니다. ` +
      `예상 금액은 ${formatWon(calculation.total)}입니다.`;
  }
}

reservationProduct.addEventListener("change", function () {
  updateProductDependentFields(true);
  updateReservationSummary("제품");
  updateRequiredStatus();
});

reservationQuantity.addEventListener("change", function () {
  updateReservationSummary("수량");
});

cakeSizeInputs.forEach(function (input) {
  input.addEventListener("change", function () {
    formSuccessMessage.textContent = "";

    if (cakeSizeFieldset.dataset.hadError === "true") {
      validateField(reservationFields[8], true);
    }

    updateReservationSummary("크기");
    updateRequiredStatus();
  });
});

cakeOptionInputs.forEach(function (input) {
  input.addEventListener("change", function () {
    formSuccessMessage.textContent = "";
    updateReservationSummary("추가 옵션");
  });
});

visitDate.addEventListener("change", function () {
  updateReservationSummary("날짜");
  updateReservationSummary("시간");
});

visitTime.addEventListener("change", function () {
  updateReservationSummary("시간");
});

guestCount.addEventListener("change", function () {
  updateReservationSummary("인원");
});

mobileSummaryToggle.addEventListener("click", function () {
  const isOpen = mobileSummaryToggle.getAttribute("aria-expanded") === "true";

  mobileSummaryToggle.setAttribute("aria-expanded", String(!isOpen));
  mobileSummaryPanel.hidden = isOpen;
});

reservationForm.addEventListener("reset", function () {
  window.setTimeout(function () {
    updateProductDependentFields(false);
    updateReservationSummary();
    updateRequiredStatus();
  }, 0);
});

// 예약 폼 작성 내용 자동 저장
const reservationDraftStorageKey = "mellow-reservation-draft";
const reservationDraftMaxAge = 3 * 24 * 60 * 60 * 1000;
const reservationDraftSaveDelay = 1000;
const reservationDraftFields = [
  visitDate,
  visitTime,
  guestCount,
  reservationProduct,
  reservationQuantity,
  inquiryMessage
];
let reservationDraftSaveTimer;
let reservationDraftStatusTimer;
let isRestoringReservationDraft = false;

function getReservationDraftValues() {
  return {
    visitDate: visitDate.value,
    visitTime: visitTime.value,
    guestCount: guestCount.value,
    reservationProduct: reservationProduct.value,
    reservationQuantity: reservationQuantity.value,
    inquiryMessage: inquiryMessage.value
  };
}

function hasReservationDraftValues(values) {
  return Object.values(values).some(function (value) {
    return String(value || "").trim() !== "";
  });
}

function hideReservationDraftSavedStatus() {
  window.clearTimeout(reservationDraftStatusTimer);
  reservationDraftSaveStatus.classList.remove("is-visible");
}

function showReservationDraftSavedStatus() {
  window.clearTimeout(reservationDraftStatusTimer);
  reservationDraftSaveStatus.textContent = "작성 중인 내용이 저장되었습니다";
  reservationDraftSaveStatus.classList.add("is-visible");

  reservationDraftStatusTimer = window.setTimeout(function () {
    reservationDraftSaveStatus.classList.remove("is-visible");
  }, 2800);
}

function clearReservationDraft() {
  window.clearTimeout(reservationDraftSaveTimer);
  reservationDraftSaveTimer = undefined;

  try {
    window.localStorage.removeItem(reservationDraftStorageKey);
  } catch (error) {
    // 저장소를 사용할 수 없는 환경에서는 화면 기능만 유지합니다.
  }

  reservationDraftRestore.hidden = true;
  hideReservationDraftSavedStatus();
}

function saveReservationDraft() {
  reservationDraftSaveTimer = undefined;

  if (isRestoringReservationDraft || reservationForm.hidden) {
    return;
  }

  const values = getReservationDraftValues();

  if (!hasReservationDraftValues(values)) {
    clearReservationDraft();
    return;
  }

  try {
    window.localStorage.setItem(
      reservationDraftStorageKey,
      JSON.stringify({
        savedAt: Date.now(),
        values: values
      })
    );
    showReservationDraftSavedStatus();
  } catch (error) {
    // 저장 공간이 차단되거나 부족하면 별도 알림 없이 입력 기능을 유지합니다.
  }
}

function scheduleReservationDraftSave() {
  if (isRestoringReservationDraft || reservationForm.hidden) {
    return;
  }

  window.clearTimeout(reservationDraftSaveTimer);
  reservationDraftSaveTimer = window.setTimeout(
    saveReservationDraft,
    reservationDraftSaveDelay
  );
}

function getStoredReservationDraft() {
  let savedDraft;

  try {
    savedDraft = JSON.parse(
      window.localStorage.getItem(reservationDraftStorageKey) || "null"
    );
  } catch (error) {
    clearReservationDraft();
    return null;
  }

  if (
    !savedDraft ||
    typeof savedDraft.savedAt !== "number" ||
    !savedDraft.values ||
    typeof savedDraft.values !== "object"
  ) {
    clearReservationDraft();
    return null;
  }

  const draftAge = Date.now() - savedDraft.savedAt;

  if (draftAge < 0 || draftAge > reservationDraftMaxAge) {
    clearReservationDraft();
    return null;
  }

  return savedDraft.values;
}

function restoreReservationDraft() {
  const savedValues = getStoredReservationDraft();

  if (!savedValues || !hasReservationDraftValues(savedValues)) {
    return;
  }

  isRestoringReservationDraft = true;

  visitDate.value = typeof savedValues.visitDate === "string"
    ? savedValues.visitDate
    : "";
  guestCount.value = typeof savedValues.guestCount === "string"
    ? savedValues.guestCount
    : "";
  inquiryMessage.value = typeof savedValues.inquiryMessage === "string"
    ? savedValues.inquiryMessage
    : "";
  reservationProduct.value = typeof savedValues.reservationProduct === "string"
    ? savedValues.reservationProduct
    : "";

  updateTimeOptions();

  if (
    typeof savedValues.visitTime === "string" &&
    savedValues.visitTime &&
    !getTimeOption(savedValues.visitTime)?.disabled
  ) {
    visitTime.value = savedValues.visitTime;
  }

  updateProductDependentFields(false);

  if (
    !reservationQuantity.disabled &&
    typeof savedValues.reservationQuantity === "string"
  ) {
    reservationQuantity.value = savedValues.reservationQuantity;
  }

  updateReservationSummary();
  updateRequiredStatus();
  reservationDraftRestore.hidden = false;
  isRestoringReservationDraft = false;
}

reservationDraftFields.forEach(function (field) {
  const eventName = field === inquiryMessage ? "input" : "change";
  field.addEventListener(eventName, scheduleReservationDraftSave);
});

reservationDraftClearButton.addEventListener("click", function () {
  isRestoringReservationDraft = true;
  clearReservationDraft();
  reservationForm.reset();

  reservationFields.forEach(function (field) {
    clearError(field);
  });

  formSuccessMessage.textContent = "";
  updateTimeOptions();
  updateProductDependentFields(false);
  updateReservationSummary();
  updateRequiredStatus();
  isRestoringReservationDraft = false;

  window.requestAnimationFrame(function () {
    customerName.focus();
  });
});

updateProductDependentFields(false);
updateReservationSummary();
updateRequiredStatus();
restoreReservationDraft();

// 예약 문의를 실제로 보내기 전 내용 확인 모달
const reservationConfirmModal = document.querySelector("#reservation-confirm-modal");
const reservationConfirmEditButton = document.querySelector(".reservation-confirm-edit");
const reservationConfirmSendButton = document.querySelector(".reservation-confirm-send");
const confirmReservationDate = document.querySelector("#confirm-reservation-date");
const confirmReservationTime = document.querySelector("#confirm-reservation-time");
const confirmReservationGuests = document.querySelector("#confirm-reservation-guests");
const confirmReservationProduct = document.querySelector("#confirm-reservation-product");
const confirmReservationQuantity = document.querySelector("#confirm-reservation-quantity");
const confirmReservationPrice = document.querySelector("#confirm-reservation-price");
let reservationConfirmReturnFocus = formSubmitButton;

function updateReservationConfirmContent() {
  const productName = reservationProduct.value;
  const hasNoProductReservation = productName === "제품 예약 없음";
  const calculation = calculateEstimatedPrice();

  confirmReservationDate.textContent = formatSummaryDate(visitDate.value);
  confirmReservationTime.textContent = formatSummaryTime(visitTime.value);
  confirmReservationGuests.textContent = getGuestSummary();
  confirmReservationProduct.textContent = productName;
  confirmReservationQuantity.textContent = hasNoProductReservation
    ? "해당 없음"
    : `${reservationQuantity.value}개`;
  confirmReservationPrice.textContent = formatWon(calculation.total);
}

function openReservationConfirmModal(triggerButton) {
  reservationConfirmReturnFocus = triggerButton || formSubmitButton;
  updateReservationConfirmContent();
  reservationConfirmModal.classList.add("is-open");
  reservationConfirmModal.setAttribute("aria-hidden", "false");
  document.body.classList.add("modal-open");

  window.requestAnimationFrame(function () {
    reservationConfirmEditButton.focus();
  });
}

function closeReservationConfirmModal(restoreFocus) {
  reservationConfirmModal.classList.remove("is-open");
  reservationConfirmModal.setAttribute("aria-hidden", "true");
  document.body.classList.remove("modal-open");

  if (
    restoreFocus &&
    reservationConfirmReturnFocus &&
    typeof reservationConfirmReturnFocus.focus === "function"
  ) {
    reservationConfirmReturnFocus.focus();
  }
}

function getSubmittedReservationData() {
  const productName = reservationProduct.value;
  const cakeSelected = isCakeProduct();
  const hasNoProductReservation = productName === "제품 예약 없음";
  const selectedOptions = getSelectedCakeOptions();
  const calculation = calculateEstimatedPrice();

  return {
    customerName: customerName.value.trim(),
    customerPhone: customerPhone.value.trim(),
    date: formatSummaryDate(visitDate.value),
    time: formatSummaryTime(visitTime.value),
    guests: getGuestSummary(),
    product: productName,
    size: cakeSelected ? getSelectedCakeSize() : "해당 없음",
    options: cakeSelected
      ? selectedOptions.length
        ? selectedOptions.map(function (option) { return option.name; }).join(", ")
        : "선택 안 함"
      : "해당 없음",
    quantity: hasNoProductReservation ? "해당 없음" : `${reservationQuantity.value}개`,
    inquiry: inquiryMessage.value.trim(),
    price: formatWon(calculation.total)
  };
}

function showReservationSubmissionResult(data) {
  submittedCustomerName.textContent = data.customerName;
  submittedCustomerPhone.textContent = data.customerPhone;
  submittedReservationDate.textContent = data.date;
  submittedReservationTime.textContent = data.time;
  submittedReservationGuests.textContent = data.guests;
  submittedReservationProduct.textContent = data.product;
  submittedReservationSize.textContent = data.size;
  submittedReservationOptions.textContent = data.options;
  submittedReservationQuantity.textContent = data.quantity;
  submittedInquiryMessage.textContent = data.inquiry;
  submittedReservationPrice.textContent = data.price;

  reservationForm.hidden = true;
  reservationSummary.hidden = true;
  mobileSummaryToggle.hidden = true;
  mobileSummaryPanel.hidden = true;
  mobileSummaryToggle.setAttribute("aria-expanded", "false");
  reservationSubmissionResult.hidden = false;
  reservationFormArea.classList.add("is-submitted");

  window.requestAnimationFrame(function () {
    reservationSubmissionResult.focus({ preventScroll: true });
    reservationSubmissionResult.scrollIntoView({ block: "start" });
  });
}

function completeReservationSubmission() {
  const submittedData = getSubmittedReservationData();

  clearReservationDraft();
  closeReservationConfirmModal(false);
  showReservationSubmissionResult(submittedData);
}

function startNewReservation() {
  reservationForm.reset();

  reservationFields.forEach(function (field) {
    clearError(field);
  });

  formSuccessMessage.textContent = "";
  reservationSubmissionResult.hidden = true;
  reservationForm.hidden = false;
  reservationSummary.hidden = false;
  mobileSummaryToggle.hidden = false;
  reservationFormArea.classList.remove("is-submitted");
  updateTimeOptions();
  updateRequiredStatus();

  window.requestAnimationFrame(function () {
    customerName.focus();
  });
}

reservationConfirmEditButton.addEventListener("click", function () {
  closeReservationConfirmModal(true);
});

reservationConfirmSendButton.addEventListener("click", function () {
  completeReservationSubmission();
});

newReservationButton.addEventListener("click", function () {
  startNewReservation();
});

document.addEventListener("keydown", function (event) {
  if (!reservationConfirmModal.classList.contains("is-open")) {
    return;
  }

  if (event.key === "Escape") {
    event.preventDefault();
    closeReservationConfirmModal(true);
    return;
  }

  if (event.key !== "Tab") {
    return;
  }

  const focusableButtons = [
    reservationConfirmEditButton,
    reservationConfirmSendButton
  ].filter(function (button) {
    return !button.disabled;
  });
  const firstButton = focusableButtons[0];
  const lastButton = focusableButtons[focusableButtons.length - 1];

  if (!focusableButtons.includes(document.activeElement)) {
    event.preventDefault();
    firstButton.focus();
    return;
  }

  if (event.shiftKey && document.activeElement === firstButton) {
    event.preventDefault();
    lastButton.focus();
  } else if (!event.shiftKey && document.activeElement === lastButton) {
    event.preventDefault();
    firstButton.focus();
  }
});

