---
import { env } from '@/server/env';
export const prerender = false;

import BaseLayout from '@/layouts/BaseLayout.astro';
import PublicAppShell from '@/layouts/PublicAppShell.astro';
import type { PreloadImageEntry } from '@/components/ui/primitives/Image';
import { DealDetail, loadDeal } from '@/features/deal-detail';
import type { DealDetailData } from '@/features/deal-detail';
import { DealsBrowserIsland } from '@/features/deals-browser/DealsBrowserIsland';
import type { DealBrowseRow } from '@/components/ui/domain/DealsBrowser/types';
import { he } from '@/lib/i18n/he';
import { en } from '@/lib/i18n/en';
import { parseDealsPath } from '@/server/routing/parseDealsPath';
import { resolveCategorySlug, resolveTagSlugs } from '@/server/db/queries/slug-resolve';
import { buildDealsPath } from '@/lib/url/buildDealsPath';
import { listActiveFiltered } from '@/server/catalog/public/browse';
import { queryHotDealIds } from '@/server/catalog/public/hot';
import { findLocaleSlugPairsForDeal } from '@/server/catalog/public/translations';
import { getDealWithSkus } from '@/server/domain/variants/read';
import type { DealWithSkus } from '@/server/domain/variants/read';
import { queryRelatedDeals } from '@/server/catalog/related';
import type { RelatedDeals } from '@/server/catalog/related';
import { captureCaught } from '@/server/observability/capture.server';
import { inArray, and, eq } from 'drizzle-orm';
import { dealTranslations } from '@/server/db/schema';
import {
  getDealsFacetCounts,
  type DealsFacetCounts,
  HISTO_BUCKETS,
} from '@/server/db/queries/deals-facets';
import { getFilterData } from '@/server/db/queries/filter-data';
import { dehydrateForIsland } from '@/lib/query/ssr';
import { buildFacetKey } from '@/lib/deals/facet-key';
import { makeDealsCodec } from '@/lib/url/codecs/dealsCodec';

const PAGE_SIZE = 12;

const locale = Astro.props.locale ?? Astro.locals.locale ?? 'he';
const dict = locale === 'en' ? en : he;
const BASE_URL = env.PUBLIC_SITE_URL;

const db = Astro.locals.services.db;

// ── Deal detail branch ────────────────────────────────────────────────────────
const hit = Astro.locals.dealHit;

// Variables for deal detail (only populated when hit)
let detailTitle = '';
let detailDescription = '';
let detailCanonical = '';
let detailJsonLd: Record<string, unknown> | undefined;
let detailOgImage: string | undefined;
let detailLocaleAlternates: Array<{ locale: string; url: string }> = [];
let detailPreloadImages: PreloadImageEntry[] = [];
let dealData: DealDetailData | null = null;
let dealSlug = '';
let variantData: DealWithSkus = { dealId: '', axes: [], skus: [] };
let relatedSections: RelatedDeals = { moreFromVendor: [], similar: [], alsoBought: [] };
const isGuest = !Astro.locals.user;
const isAdmin = !!Astro.locals.user?.isAdmin;
const isVendor = (Astro.locals.isVendor as boolean | undefined) ?? false;
const userName = Astro.locals.user?.displayName ?? undefined;
const csrfToken = Astro.locals.session?.csrfToken ?? null;

if (hit) {
  const { deal: hitDeal, translation } = hit;
  dealSlug = translation.slug;

  Astro.response.headers.set(
    'Cache-Control',
    'public, max-age=0, s-maxage=3600, stale-while-revalidate=3600',
  );

  if (db) {
    try {
      dealData = await loadDeal(db, hitDeal.id);
    } catch (err) {
      captureCaught(err, {
        scope: 'page.deals.loadDeal',
        severity: 'error',
        extra: { dealId: hitDeal.id },
      });
    }
  }
  if (!dealData) return new Response('Not Found', { status: 404 });

  const deal = dealData;

  const [vd, rs] = db
    ? await Promise.all([
        getDealWithSkus(db, deal.id),
        queryRelatedDeals(
          db,
          {
            id: deal.id,
            vendorId: deal.vendor.id,
            categoryId: deal.categoryId,
            tagIds: deal.tags.map((t) => t.id),
          },
          {},
        ),
      ])
    : [
        { dealId: deal.id, axes: [], skus: [] } as DealWithSkus,
        { moreFromVendor: [], similar: [], alsoBought: [] } as RelatedDeals,
      ];
  variantData = vd;
  relatedSections = rs;

  const origin = Astro.site?.origin ?? Astro.url.origin;
  const pairs = await findLocaleSlugPairsForDeal(hitDeal.id);

  detailLocaleAlternates = pairs.map((p) => ({
    locale: p.locale,
    url: p.locale === 'he' ? `${origin}/deals/${p.slug}` : `${origin}/${p.locale}/deals/${p.slug}`,
  }));
  const sourcePair = pairs.find((p) => p.locale === hitDeal.sourceLanguage);
  if (sourcePair) {
    detailLocaleAlternates.push({
      locale: 'x-default',
      url:
        sourcePair.locale === 'he'
          ? `${origin}/deals/${sourcePair.slug}`
          : `${origin}/${sourcePair.locale}/deals/${sourcePair.slug}`,
    });
  }

  detailCanonical =
    locale === 'he'
      ? `${origin}/deals/${translation.slug}`
      : `${origin}/${locale}/deals/${translation.slug}`;
  detailTitle = `${deal.title}${dict.deals_browse.brand_suffix}`;
  detailDescription = deal.description.slice(0, 160);

  const heroImage =
    deal.images.dealMain.find((i) => i.isPrimary)?.url ?? deal.images.dealMain[0]?.url ?? null;
  detailOgImage = heroImage ?? undefined;
  if (heroImage)
    detailPreloadImages.push({ src: heroImage, variant: 'hero', fetchpriority: 'high' });
  if (deal.vendor.logoUrl) detailPreloadImages.push({ src: deal.vendor.logoUrl, variant: 'thumb' });

  const activeSkus = variantData.skus.filter((s) => s.isActive);
  const productJsonLd = {
    '@type': 'Product',
    name: deal.title,
    description: deal.description,
    url: detailCanonical,
    offers:
      activeSkus.length > 0
        ? activeSkus.map((s) => ({
            '@type': 'Offer',
            sku: s.id,
            price: s.discountedPrice,
            priceCurrency: 'ILS',
            availability:
              s.quantityTotal - s.quantitySold > 0
                ? 'https://schema.org/InStock'
                : 'https://schema.org/OutOfStock',
            seller: { '@type': 'LocalBusiness', name: deal.vendor.displayName },
          }))
        : {
            '@type': 'Offer',
            priceCurrency: 'ILS',
            price: deal.discountedPrice,
            availability:
              deal.dealState === 'ACTIVE'
                ? 'https://schema.org/InStock'
                : 'https://schema.org/SoldOut',
            seller: { '@type': 'LocalBusiness', name: deal.vendor.displayName },
          },
  };
  const timeslotAxis = variantData.axes.find((a) => a.kind === 'TIMESLOT' && a.isActive);
  const eventJsonLdItems = timeslotAxis
    ? timeslotAxis.options
        .filter((o) => o.isActive && o.slotStart)
        .map((o) => ({
          '@type': 'Event',
          name: `${deal.title} — ${locale === 'he' ? o.labelHe : o.labelEn}`,
          startDate: o.slotStart!.toISOString(),
          endDate: o.slotEnd?.toISOString(),
          location: {
            '@type': 'Place',
            name: deal.vendor.displayName,
            address: deal.vendor.city ?? '',
          },
        }))
    : [];

  detailJsonLd = {
    '@context': 'https://schema.org',
    '@graph': [
      { ...productJsonLd, inLanguage: locale === 'he' ? 'he-IL' : 'en-IL' },
      ...eventJsonLdItems,
    ],
  };
}

// ── Browse branch (skip entirely when hit) ────────────────────────────────────
let parsed: ReturnType<typeof parseDealsPath> = null;
let resolvedCatId: string | undefined;
let resolvedCatSlug: string | undefined;
let resolvedCatNameHe = '';
let resolvedCatNameEn = '';
let resolvedTagIds: string[] = [];
let resolvedTagSlugs: string[] = [];
let resolvedTagNamesHe: string[] = [];
let resolvedTagNamesEn: string[] = [];
let rows: Awaited<ReturnType<typeof listActiveFiltered>>['rows'] = [];
let total = 0;
let deals: DealBrowseRow[] = [];
let heading: string = dict.deals_browse.page_heading;
let pageTitle = '';
let pageDescription: string = dict.seo_pages.deals_desc;
let canonicalPath = '';
let canonicalFull = '';
let isNoindex = true;
let jsonLd: Record<string, unknown> | undefined;
let initialPriceMin: number | undefined;
let initialPriceMax: number | undefined;
let initialFacets: DealsFacetCounts | undefined;
let priceCeiling = 2000;
let priceFloor = 0;

if (!hit) {
  // ── 1. Parse path ───────────────────────────────────────────────────────────
  const rawPath = Astro.props.path ?? Astro.params.path ?? '';
  parsed = parseDealsPath(rawPath);
  if (!parsed) return new Response('Not Found', { status: 404 });

  // ── 1b. Price + sort query params (not slug-routed — continuous values) ─────
  const _priceMinRaw = Astro.url.searchParams.get('priceMin');
  const _priceMaxRaw = Astro.url.searchParams.get('priceMax');
  initialPriceMin = _priceMinRaw ? parseInt(_priceMinRaw, 10) : undefined;
  initialPriceMax = _priceMaxRaw ? parseInt(_priceMaxRaw, 10) : undefined;

  // ── 2a. ?page=N query param → 301 to canonical /page-N path ─────────────────
  const _queryPage = Astro.url.searchParams.get('page');
  if (_queryPage !== null) {
    const _pageNum = parseInt(_queryPage, 10);
    if (!isNaN(_pageNum) && _pageNum >= 1) {
      return Astro.redirect(
        buildDealsPath({
          locale,
          type: parsed.type,
          catSlug: parsed.catSlug,
          tagSlugs: parsed.tagSlugs,
          page: _pageNum,
        }),
        301,
      );
    }
  }

  // ── 2b. Canonical redirect (non-canonical order, page-1, sentinel, /all) ─────
  if (parsed.canonical !== rawPath) {
    return Astro.redirect(
      buildDealsPath({
        locale,
        type: parsed.type,
        catSlug: parsed.catSlug,
        tagSlugs: parsed.tagSlugs,
        page: parsed.page,
      }),
      301,
    );
  }

  // ── 3. Slug resolution + hot-ids (parallel — 1 wall-clock RTT) ──────────────
  let hotIds: string[] | undefined;

  if (db) {
    const [cat, tags, hot] = await Promise.all([
      parsed.catSlug ? resolveCategorySlug(db, parsed.catSlug) : Promise.resolve(undefined),
      parsed.tagSlugs.length > 0
        ? resolveTagSlugs(db, parsed.tagSlugs)
        : Promise.resolve(undefined),
      queryHotDealIds(db, '24h', 50),
    ]);

    if (parsed.catSlug) {
      if (!cat) return new Response('Not Found', { status: 404 });
      resolvedCatId = cat.id;
      resolvedCatSlug = cat.canonicalSlug;
      resolvedCatNameHe = cat.nameHe;
      resolvedCatNameEn = cat.nameEn;
    }
    if (parsed.tagSlugs.length > 0) {
      if (!tags) return new Response('Not Found', { status: 404 });
      resolvedTagIds = tags.ids;
      resolvedTagSlugs = tags.canonicalSlugs;
      resolvedTagNamesHe = tags.namesHe;
      resolvedTagNamesEn = tags.namesEn;
    } else {
      resolvedTagSlugs = parsed.tagSlugs;
    }

    // Redirects must run AFTER both resolves so canonical path includes both.
    if (cat?.redirected || tags?.redirected) {
      return Astro.redirect(
        buildDealsPath({
          locale,
          type: parsed.type,
          catSlug: cat?.redirected ? cat.canonicalSlug : resolvedCatSlug,
          tagSlugs: tags?.redirected ? tags.canonicalSlugs : parsed.tagSlugs,
          page: parsed.page,
        }),
        301,
      );
    }

    hotIds = hot;
  } else {
    resolvedTagSlugs = parsed.tagSlugs;
  }

  // ── 4. Fetch top-6 deals + facet counts (SSR seed for island + JSON-LD) ─────
  if (db) {
    const filterDataP = getFilterData(db, locale);
    const [filterData, r, facets] = await Promise.all([
      filterDataP,
      listActiveFiltered(db, {
        locale,
        type: parsed.type,
        categoryIds: resolvedCatId ? [resolvedCatId] : undefined,
        tagIds: resolvedTagIds.length > 0 ? resolvedTagIds : undefined,
        sort: 'hot',
        page: parsed.page,
        limit: 6,
        offset: (parsed.page - 1) * PAGE_SIZE,
        hotIds,
        withImages: true,
      }),
      filterDataP
        .then((fd) => {
          const ssrFacetPriceMin =
            (initialPriceMin ?? 0) > fd.otherFilters.priceFloor ? initialPriceMin : undefined;
          const ssrFacetPriceMax =
            (initialPriceMax ?? 0) > 0 && (initialPriceMax ?? 0) < fd.otherFilters.priceCeiling
              ? initialPriceMax
              : undefined;
          return getDealsFacetCounts(db!, {
            catId: resolvedCatId,
            type: parsed!.type || undefined,
            tagIds: resolvedTagIds.length > 0 ? resolvedTagIds : undefined,
            priceMin: ssrFacetPriceMin,
            priceMax: ssrFacetPriceMax,
            tagLimit: 30,
            histoMin: fd.otherFilters.priceFloor,
            histoMax: fd.otherFilters.priceCeiling,
            histoBuckets: HISTO_BUCKETS,
          });
        })
        .catch(() => undefined),
    ]);
    priceCeiling = filterData.otherFilters.priceCeiling;
    priceFloor = filterData.otherFilters.priceFloor;
    rows = r.rows;
    total = r.total;
    initialFacets = facets;
  }

  deals = rows.map((d) => ({
    id: d.id,
    title: d.title,
    originalPrice:
      locale === 'he' && d.maxDiscountPercent
        ? Math.round((parseFloat(d.minPrice ?? '0') / (1 - d.maxDiscountPercent / 100)) * 100) / 100
        : Number(d.minPrice ?? 0),
    discountedPrice: Number(d.minPrice ?? 0),
    discountPercent: d.maxDiscountPercent ?? null,
    imageUrl: d.primaryImageUrl ?? null,
    vendorId: d.vendorId,
    vendorName: d.vendorBusinessName ?? '',
    vendorAvatarUrl: d.vendorLogoUrl ?? null,
    city: '',
    dealType: d.dealType,
    windowEnd: d.windowEnd?.toISOString() ?? null,
    stockRemaining: d.stockRemaining ?? 0,
    stockTotal: d.stockRemaining ?? 0,
    isHotDeal: hotIds?.includes(d.id) ?? false,
    soldCount: 0,
    minPrice: d.minPrice ?? null,
    maxPrice: d.maxPrice ?? null,
    maxDiscountPercent: d.maxDiscountPercent ?? null,
    axesCount: d.axesCount,
    defaultSkuId: d.defaultSkuId,
    qtyTierTop: d.qtyTierTop ?? null,
    skuCount: d.skuCount ?? 1,
    heSlug: d.heSlug ?? undefined,
  }));

  // ── 5. SEO + heading ────────────────────────────────────────────────────────
  const brandSuffix = dict.deals_browse.brand_suffix;

  const isSingleFilter =
    (parsed.type && !resolvedCatSlug && parsed.tagSlugs.length === 0) ||
    (resolvedCatSlug && parsed.tagSlugs.length === 0) ||
    (!resolvedCatSlug && parsed.tagSlugs.length === 1);

  if (parsed.type === 'COUPON') heading = dict.deals_browse.type_coupon;
  else if (parsed.type === 'GROUP') heading = dict.deals_browse.type_group;

  if (resolvedCatSlug) {
    const catName = locale === 'en' ? resolvedCatNameEn : resolvedCatNameHe;
    heading = catName
      ? dict.deals_browse.cat_deals_heading.replace('{catName}', catName)
      : resolvedCatSlug;
  } else if (parsed.tagSlugs.length === 1) {
    const tagName = locale === 'en' ? (resolvedTagNamesEn[0] ?? '') : (resolvedTagNamesHe[0] ?? '');
    heading = tagName
      ? dict.deals_browse.tag_deals_heading.replace('{tagName}', tagName)
      : parsed.tagSlugs[0]!;
  }

  pageTitle = `${heading}${brandSuffix}`;

  if (resolvedCatSlug) {
    const catName = locale === 'en' ? resolvedCatNameEn : resolvedCatNameHe;
    if (catName) {
      pageDescription = dict.seo_pages.deals_cat_desc.replace('{cat}', catName);
    }
  } else if (parsed.tagSlugs.length === 1) {
    const tagName = locale === 'en' ? (resolvedTagNamesEn[0] ?? '') : (resolvedTagNamesHe[0] ?? '');
    if (tagName) {
      pageDescription = dict.seo_pages.deals_tag_desc.replace('{tag}', tagName);
    }
  }

  canonicalPath = buildDealsPath({
    locale,
    type: parsed.type,
    catSlug: resolvedCatSlug,
    tagSlugs: resolvedTagSlugs,
    page: parsed.page,
  });
  canonicalFull = `${BASE_URL}${canonicalPath}`;

  // noindex: page > 1, price/sort filter params, or multi-filter combinations
  const hasFilterParams =
    !!(initialPriceMin ?? initialPriceMax) || Astro.url.searchParams.get('sort') !== null;
  const isMultiFilter = !isSingleFilter && (resolvedCatSlug != null || parsed.tagSlugs.length > 0);
  isNoindex =
    locale === 'he' ? parsed.page > 1 || hasFilterParams || isMultiFilter : parsed.page > 1;

  // JSON-LD for single-filter p1 pages: BreadcrumbList + CollectionPage + ItemList (top-6)
  if (!isNoindex && isSingleFilter) {
    const dealIds = deals.slice(0, 6).map((d) => d.id);
    const dealSlugMap = new Map<string, string>();
    if (db && dealIds.length > 0) {
      try {
        const slugRows = await db
          .select({ dealId: dealTranslations.dealId, slug: dealTranslations.slug })
          .from(dealTranslations)
          .where(
            and(
              inArray(dealTranslations.dealId, dealIds),
              eq(dealTranslations.locale, locale),
              eq(dealTranslations.status, 'OK'),
            ),
          );
        for (const r of slugRows) dealSlugMap.set(r.dealId, r.slug);
      } catch {
        // Non-fatal: fall back to no URL on slugless deals
      }
    }

    jsonLd = {
      '@context': 'https://schema.org',
      '@graph': [
        {
          '@type': 'BreadcrumbList',
          itemListElement: [
            {
              '@type': 'ListItem',
              position: 1,
              name: dict.deals_browse.jsonld_breadcrumb_home,
              item: BASE_URL,
            },
            { '@type': 'ListItem', position: 2, name: heading, item: canonicalFull },
          ],
        },
        {
          '@type': 'CollectionPage',
          name: heading,
          url: canonicalFull,
          inLanguage: locale === 'he' ? 'he-IL' : 'en-IL',
        },
        ...(deals.length > 0
          ? [
              {
                '@type': 'ItemList',
                numberOfItems: total,
                itemListElement: deals
                  .slice(0, 6)
                  .map((d, idx) => {
                    const slug = dealSlugMap.get(d.id);
                    const dealUrl = slug
                      ? locale === 'he'
                        ? `${BASE_URL}/deals/${slug}`
                        : `${BASE_URL}/en/deals/${slug}`
                      : null;
                    if (!dealUrl) return null;
                    return {
                      '@type': 'ListItem',
                      position: idx + 1 + (parsed!.page - 1) * PAGE_SIZE,
                      url: dealUrl,
                      name: d.title,
                    };
                  })
                  .filter((item): item is NonNullable<typeof item> => item !== null),
              },
            ]
          : []),
      ],
    };
  }

  Astro.response.headers.set(
    'Cache-Control',
    isNoindex
      ? 'public, max-age=0, s-maxage=30, stale-while-revalidate=3600'
      : `public, max-age=0, s-maxage=${locale === 'he' ? 300 : 3600}, stale-while-revalidate=3600`,
  );
}

const facetKeyPriceMin = (initialPriceMin ?? 0) > priceFloor ? initialPriceMin : undefined;
const facetKeyPriceMax =
  (initialPriceMax ?? 0) > 0 && (initialPriceMax ?? 0) < priceCeiling ? initialPriceMax : undefined;

const { dehydratedState } = await dehydrateForIsland(
  initialFacets
    ? [
        async (qc) => {
          qc.setQueryData(
            buildFacetKey({
              catSlug: resolvedCatSlug,
              type: parsed?.type || undefined,
              tagSlugs: resolvedTagSlugs,
              priceMin: facetKeyPriceMin,
              priceMax: facetKeyPriceMax,
            }),
            initialFacets,
          );
        },
      ]
    : [],
);

// Above-fold preload
const browsePreloadImages: PreloadImageEntry[] = hit
  ? []
  : deals
      .filter((d) => d.imageUrl)
      .slice(0, 6)
      .map((d, idx) => ({
        src: d.imageUrl as string,
        variant: 'card',
        fetchpriority: idx === 0 ? 'high' : undefined,
      }));
---

{
  hit ? (
    <BaseLayout
      title={detailTitle}
      description={detailDescription}
      canonical={detailCanonical}
      locale={locale}
      ogType="product"
      ogImage={detailOgImage ?? `${BASE_URL}/brand/og-default.webp`}
      jsonLd={detailJsonLd}
      localeAlternates={detailLocaleAlternates}
      preloadImages={detailPreloadImages}
      geoRegion="IL"
    >
      <main id="main">
        <h1 class="sr-only">{dealData?.title}</h1>
        <DealDetail
          deal={dealData!}
          dealSlug={dealSlug}
          locale={locale}
          siteUrl={BASE_URL}
          isGuest={isGuest}
          isAdmin={isAdmin}
          isVendor={isVendor}
          userName={userName}
          csrfToken={csrfToken}
          buyerName={null}
          buyerEmail={null}
          variantData={variantData}
          relatedSections={relatedSections}
          client:idle
        />
      </main>
    </BaseLayout>
  ) : (
    <PublicAppShell
      title={pageTitle}
      description={pageDescription}
      canonical={canonicalFull}
      noindex={isNoindex}
      ogImage={`${BASE_URL}/brand/og-default.webp`}
      locale={locale}
      jsonLd={jsonLd}
      currentPath={canonicalPath}
      preloadImages={browsePreloadImages}
      geoRegion="IL"
      geoPosition="31.0461;34.8516"
    >
      <h1 class="sr-only" data-user-content={!!resolvedCatSlug || undefined}>
        {heading}
      </h1>
      <DealsBrowserIsland
        client:idle
        initialDeals={deals}
        initialTotal={total}
        initialUrlState={makeDealsCodec({ locale, priceCeiling }).parse({
          pathname: Astro.url.pathname,
          search: Astro.url.search,
        })}
        dehydratedState={dehydratedState}
        locale={locale as 'he' | 'en'}
        priceCeiling={priceCeiling}
        priceFloor={priceFloor}
      />
    </PublicAppShell>
  )
}
