/**
 * خواندن و ساختن پارامترهای آدرس صفحه لیست محصولات.
 * همه ورودی‌های آدرس با Zod اعتبارسنجی می‌شوند و مقادیر نامعتبر نادیده گرفته می‌شوند.
 */
import { z } from "zod";
import { toLatinDigits } from "./persian";

export const SORT_OPTIONS = [
  { value: "popular", label: "پرفروش‌ترین" },
  { value: "newest", label: "جدیدترین" },
  { value: "rating", label: "بیشترین امتیاز" },
  { value: "price-asc", label: "ارزان‌ترین" },
  { value: "price-desc", label: "گران‌ترین" },
] as const;

export type SortKey = (typeof SORT_OPTIONS)[number]["value"];

export interface ListingFilters {
  q?: string;
  categoryId?: string;
  brands: string[];
  skin: string[];
  min?: number;
  max?: number;
  rating?: number;
  inStock: boolean;
  sort: SortKey;
  page: number;
}

type RawParams = Record<string, string | string[] | undefined>;

const list = z
  .string()
  .max(300)
  .transform((s) => s.split(",").map((x) => x.trim()).filter((x) => /^[a-z0-9-]{1,40}$/.test(x)))
  .catch([]);

const money = z
  .string()
  .transform((s) => Number(toLatinDigits(s)))
  .pipe(z.number().int().min(0).max(1_000_000_000))
  .optional()
  .catch(undefined);

const schema = z.object({
  q: z.string().trim().max(80).optional().catch(undefined),
  brand: list.optional(),
  skin: list.optional(),
  min: money,
  max: money,
  rating: z.coerce.number().int().min(1).max(5).optional().catch(undefined),
  stock: z.literal("1").optional().catch(undefined),
  sort: z.enum(SORT_OPTIONS.map((o) => o.value) as [SortKey, ...SortKey[]]).optional().catch(undefined),
  page: z.coerce.number().int().min(1).max(500).optional().catch(undefined),
});

function first(v: string | string[] | undefined) {
  return Array.isArray(v) ? v[0] : v;
}

export function parseListingParams(raw: RawParams, defaults: Partial<ListingFilters> = {}): ListingFilters {
  const flat = Object.fromEntries(Object.entries(raw).map(([k, v]) => [k, first(v)]));
  const p = schema.parse(flat);
  return {
    q: p.q || undefined,
    categoryId: defaults.categoryId,
    brands: defaults.brands ?? p.brand ?? [],
    skin: p.skin ?? [],
    min: p.min,
    max: p.max,
    rating: p.rating,
    inStock: p.stock === "1",
    sort: p.sort ?? defaults.sort ?? "popular",
    page: p.page ?? 1,
  };
}

/** تعداد فیلترهای فعال (برای نمایش روی دکمه فیلتر) */
export function activeFilterCount(f: ListingFilters, lockedBrand = false): number {
  return (
    (lockedBrand ? 0 : f.brands.length) +
    f.skin.length +
    (f.min !== undefined || f.max !== undefined ? 1 : 0) +
    (f.rating ? 1 : 0) +
    (f.inStock ? 1 : 0)
  );
}

/**
 * سئوی صفحه‌های لیست (دسته، برند، همه محصولات):
 * - با فیلتر یا مرتب‌سازی غیرپیش‌فرض ← canonical همان صفحه اصلی لیست (ترکیب‌های فیلتر محتوای تکراری‌اند)
 * - فقط صفحه‌بندی ← canonical خود همان صفحه (?page=N) و عنوان «– صفحه N» تا عنوان‌ها تکراری نباشند
 */
export function listingSeo(base: string, f: ListingFilters, lockedBrand = false) {
  const filtered = activeFilterCount(f, lockedBrand) > 0 || f.sort !== "popular" || !!f.q;
  const paged = !filtered && f.page > 1;
  return {
    path: paged ? `${base}?page=${f.page}` : base,
    titleSuffix: f.page > 1 ? ` – صفحه ${f.page.toLocaleString("fa-IR")}` : "",
  };
}

/**
 * ساخت آدرس لیست با فیلترهای جدید.
 * هر تغییر فیلتر صفحه را به ۱ برمی‌گرداند (مگر اینکه page صراحتاً داده شود).
 */
export function listingHref(
  basePath: string,
  current: ListingFilters,
  patch: Partial<ListingFilters> = {},
  opts: { lockedBrand?: boolean } = {},
): string {
  const f = { ...current, page: 1, ...patch };
  const sp = new URLSearchParams();
  if (f.q) sp.set("q", f.q);
  if (!opts.lockedBrand && f.brands.length) sp.set("brand", f.brands.join(","));
  if (f.skin.length) sp.set("skin", f.skin.join(","));
  if (f.min !== undefined) sp.set("min", String(f.min));
  if (f.max !== undefined) sp.set("max", String(f.max));
  if (f.rating) sp.set("rating", String(f.rating));
  if (f.inStock) sp.set("stock", "1");
  if (f.sort !== "popular") sp.set("sort", f.sort);
  if (f.page > 1) sp.set("page", String(f.page));
  const qs = sp.toString();
  return qs ? `${basePath}?${qs}` : basePath;
}

/** بازه‌های آماده قیمت (تومان) */
export const PRICE_PRESETS: { label: string; min?: number; max?: number }[] = [
  { label: "زیر ۵۰۰ هزار", max: 500_000 },
  { label: "۵۰۰ هزار تا ۱ میلیون", min: 500_000, max: 1_000_000 },
  { label: "۱ تا ۲ میلیون", min: 1_000_000, max: 2_000_000 },
  { label: "بالای ۲ میلیون", min: 2_000_000 },
];
