"use client";

/**
 * وضعیت سمت کاربر (سبد، آدرس‌ها، جستجوهای اخیر).
 * فقط برای مرحله ۱ است؛ سبد و آدرس‌ها از مرحله ۳ در دیتابیس هستند و این‌جا فقط نسخه همگام‌شده با سرور نگه داشته می‌شود.
 */
import { useSyncExternalStore } from "react";
import { addToCartAction, clearCartAction, deleteAddressAction, saveAddressAction, setCartQtyAction } from "@/server/actions/store";

function createStore<T>(key: string, initial: T) {
  let state = initial;
  let loaded = false;
  const listeners = new Set<() => void>();

  function load() {
    if (loaded || typeof window === "undefined") return;
    loaded = true;
    try {
      const raw = window.localStorage.getItem(key);
      if (raw) state = JSON.parse(raw) as T;
    } catch {
      state = initial;
    }
  }

  return {
    get: () => {
      load();
      return state;
    },
    getServer: () => initial,
    set(updater: (prev: T) => T) {
      load();
      state = updater(state);
      try {
        window.localStorage.setItem(key, JSON.stringify(state));
      } catch {
        /* حالت خصوصی مرورگر: فقط در حافظه نگه می‌داریم */
      }
      listeners.forEach((l) => l());
    },
    subscribe(listener: () => void) {
      listeners.add(listener);
      // همگام‌سازی بین تب‌ها
      const onStorage = (e: StorageEvent) => {
        if (e.key !== key) return;
        loaded = false;
        load();
        listener();
      };
      window.addEventListener("storage", onStorage);
      return () => {
        listeners.delete(listener);
        window.removeEventListener("storage", onStorage);
      };
    },
  };
}

function useStore<T>(store: ReturnType<typeof createStore<T>>) {
  return useSyncExternalStore(store.subscribe, store.get, store.getServer);
}

/**
 * وضعیتی که منبع اصلی‌اش سرور است (سبد، آدرس‌ها): بار اول از API خوانده می‌شود
 * و بعد از هر Server Action با پاسخ سرور جایگزین می‌شود.
 */
function createServerStore<T>(url: string, initial: T) {
  let state = initial;
  let status: "idle" | "loading" | "ready" = "idle";
  const listeners = new Set<() => void>();
  const emit = () => listeners.forEach((l) => l());
  async function load() {
    status = "loading";
    try {
      const res = await fetch(url, { cache: "no-store" });
      state = res.ok ? ((await res.json()) as T) : initial;
    } catch {
      state = initial;
    }
    status = "ready";
    emit();
  }
  return {
    get: () => state,
    getServer: () => initial,
    isReady: () => status === "ready",
    set(next: T) {
      state = next;
      status = "ready";
      emit();
    },
    reload: load,
    subscribe(listener: () => void) {
      listeners.add(listener);
      if (status === "idle") void load();
      return () => listeners.delete(listener);
    },
  };
}

// ── سبد خرید (در دیتابیس؛ مهمان با کوکی) ─────────────────

export interface CartLine {
  productId: number;
  variantId: string;
  qty: number;
}

export const MAX_QTY_PER_ITEM = 10;
const cartStore = createServerStore<CartLine[]>("/api/cart", []);

export function useCart() {
  return useSyncExternalStore(cartStore.subscribe, cartStore.get, cartStore.getServer);
}

/** آیا سبد از سرور خوانده شده است؟ (برای جلوگیری از نمایش «سبد خالی» پیش از بارگذاری) */
export function useCartReady() {
  return useSyncExternalStore(cartStore.subscribe, cartStore.isReady, () => false);
}

export const cart = {
  async add(_productId: number, variantId: string, qty = 1) {
    cartStore.set(await addToCartAction(variantId, qty));
  },
  async setQty(variantId: string, qty: number) {
    cartStore.set(await setCartQtyAction(variantId, Math.max(0, qty)));
  },
  async remove(variantId: string) {
    cartStore.set(await setCartQtyAction(variantId, 0));
  },
  async clear() {
    cartStore.set(await clearCartAction());
  },
  /** بعد از ورود/خروج، سبد از سرور دوباره خوانده شود */
  reload: () => cartStore.reload(),
};

/** بعد از ورود یا خروج، همه وضعیت‌های وابسته به کاربر از سرور دوباره خوانده می‌شوند */
export async function reloadUserState() {
  await Promise.all([cartStore.reload(), addressStore.reload()]);
}

// ── آدرس‌ها (در دیتابیس، رمزگذاری‌شده) ───────────────────

export interface SavedAddress {
  id: string;
  title: string;
  receiver: string;
  phone: string;
  province: string;
  city: string;
  line: string;
  postalCode: string;
}

const addressStore = createServerStore<SavedAddress[]>("/api/addresses", []);

export function useAddresses() {
  return useSyncExternalStore(addressStore.subscribe, addressStore.get, addressStore.getServer);
}

export const addresses = {
  /** ذخیره در سرور؛ در صورت خطای اعتبارسنجی، خطاهای فیلدها برگردانده می‌شود */
  async save(address: SavedAddress): Promise<{ id?: string; errors?: Record<string, string> }> {
    const { id, ...input } = address;
    const res = await saveAddressAction(input, id || undefined);
    if (!res.ok) return { errors: res.errors };
    addressStore.set(res.list);
    return { id: res.id };
  },
  async remove(id: string) {
    addressStore.set(await deleteAddressAction(id));
  },
};

// ── جستجوهای اخیر ───────────────────────────────────────

const recentStore = createStore<string[]>("zahora.recent-searches", []);

export function useRecentSearches() {
  return useStore(recentStore);
}

export const recentSearches = {
  push: (q: string) => recentStore.set((list) => [q, ...list.filter((x) => x !== q)].slice(0, 6)),
  clear: () => recentStore.set(() => []),
};
