"use client";

import { useSyncExternalStore } from "react";

// Mirrors lib/cart.ts's exact pattern (localStorage + useSyncExternalStore)
// so an applied discount survives the /cart → /checkout transition the
// same way the cart itself does — Checkout only ever displays this, it
// has no input of its own (see CartContent.tsx for where a code gets
// applied via /api/discount/validate).
const DISCOUNT_KEY = "ep_discount";
const DISCOUNT_EVENT = "ep-discount-updated";

export type AppliedDiscount = { code: string; type: "percent" | "fixed"; value: number };

function writeDiscount(discount: AppliedDiscount | null) {
  if (discount) window.localStorage.setItem(DISCOUNT_KEY, JSON.stringify(discount));
  else window.localStorage.removeItem(DISCOUNT_KEY);
  window.dispatchEvent(new Event(DISCOUNT_EVENT));
}

export function applyDiscount(discount: AppliedDiscount) {
  writeDiscount(discount);
}

// Called after a completed purchase (order.ts's clearCart() sibling) and
// by the cart's own "Entfernen" affordance.
export function clearDiscount() {
  writeDiscount(null);
}

// Cached-by-raw-string, not a fresh JSON.parse() every call — same
// reasoning as lib/cart.ts's getCart(): useSyncExternalStore requires
// getSnapshot to return the same reference when nothing actually changed.
let cachedRaw: string | null | undefined;
let cachedDiscount: AppliedDiscount | null = null;

export function getDiscount(): AppliedDiscount | null {
  if (typeof window === "undefined") return null;
  const raw = window.localStorage.getItem(DISCOUNT_KEY);
  if (raw === cachedRaw) return cachedDiscount;
  cachedRaw = raw;
  try {
    cachedDiscount = raw ? JSON.parse(raw) : null;
  } catch {
    cachedDiscount = null;
  }
  return cachedDiscount;
}

function subscribe(onStoreChange: () => void) {
  window.addEventListener(DISCOUNT_EVENT, onStoreChange);
  window.addEventListener("storage", onStoreChange);
  return () => {
    window.removeEventListener(DISCOUNT_EVENT, onStoreChange);
    window.removeEventListener("storage", onStoreChange);
  };
}

export function useDiscount(): AppliedDiscount | null {
  return useSyncExternalStore(subscribe, getDiscount, () => null);
}
