'use client';

import { useQuery } from '@tanstack/react-query';
import { useMemo, useState } from 'react';
import type { StoreSite, StoreSiteBlock, StorefrontShell } from '@alqove/api-client';
import { api } from '@/lib/api';
import { BlockRenderer } from '@/components/storefront/block-renderer';
import { blockKey } from '@/components/storefront/block-key';
import { productLimit, type StorefrontProduct } from '@/components/storefront/products';
import { themeToCssVars } from '@/components/storefront/theme';
import type { StorefrontRenderContext } from '@/components/storefront/links';

type Viewport = 'desktop' | 'mobile';

interface PreviewPanelProps {
  storeId: string;
  site: StoreSite;
  /** Live editor state, so unsaved edits show up immediately. */
  blocks: StoreSiteBlock[];
}

/**
 * Renders the seller's unsaved page with the same components the public site
 * uses. This is the only way to see a draft — the public route serves
 * published sites only, so a draft has no URL to visit.
 */
export function PreviewPanel({ storeId, site, blocks }: PreviewPanelProps) {
  const [viewport, setViewport] = useState<Viewport>('desktop');

  // The store record carries the address the map block renders; the site
  // record only knows about presentation.
  const storeQ = useQuery({
    queryKey: ['seller-store', storeId],
    enabled: !!storeId,
    queryFn: () => api.stores.get(storeId),
  });

  // One fetch of recent stock stands in for every product grid. It is an
  // approximation of the live query on purpose — the preview is about layout,
  // and the public page resolves each block's real query on the server.
  const itemsQ = useQuery({
    queryKey: ['site-preview-items', storeId],
    enabled: !!storeId,
    queryFn: () => api.items.browse({ store_id: [storeId], per_page: 24, sort: 'newest' }),
  });

  const shell = useMemo<StorefrontShell>(
    () => buildPreviewShell(site, storeQ.data?.data as Record<string, unknown> | undefined),
    [site, storeQ.data],
  );

  const ctx: StorefrontRenderContext = useMemo(
    () => ({ shell, slug: site.store_slug ?? '', basePath: `/s/${site.store_slug ?? ''}` }),
    [shell, site.store_slug],
  );

  const products: StorefrontProduct[] = useMemo(
    () =>
      (itemsQ.data?.data ?? []).map((item) => ({
        id: item.id ?? '',
        title: item.title ?? '',
        brand: item.brand ?? null,
        price: item.price ?? 0,
        condition: item.condition ?? null,
        imageUrl: item.thumbnail_url ?? null,
      })),
    [itemsQ.data],
  );

  const productsByBlock = useMemo(() => {
    const map: Record<string, StorefrontProduct[]> = {};
    blocks.forEach((block, index) => {
      if (block.type === 'products') {
        map[blockKey(block, index)] = products.slice(0, productLimit(block));
      }
    });
    return map;
  }, [blocks, products]);

  return (
    <section className="rounded-md border border-forest/20 bg-white">
      <header className="flex items-center justify-between gap-3 border-b border-forest/10 px-4 py-3">
        <div>
          <h2 className="text-sm font-semibold text-ink">Preview</h2>
          <p className="text-xs text-ink/60">Includes unsaved changes.</p>
        </div>
        <div className="flex gap-1" role="group" aria-label="Preview width">
          {(['desktop', 'mobile'] as const).map((v) => (
            <button
              key={v}
              type="button"
              onClick={() => setViewport(v)}
              aria-pressed={viewport === v}
              className={`rounded px-3 py-1.5 text-xs font-medium capitalize ${
                viewport === v ? 'bg-forest text-white' : 'border border-forest/20 hover:bg-bone'
              }`}
            >
              {v}
            </button>
          ))}
        </div>
      </header>

      <div className="max-h-[36rem] overflow-y-auto bg-bone/40 p-4">
        <div
          className={`mx-auto overflow-hidden rounded border border-forest/10 shadow-sm ${
            viewport === 'mobile' ? 'max-w-[24rem]' : 'w-full'
          }`}
          style={themeToCssVars(site.theme)}
        >
          <BlockRenderer blocks={blocks} ctx={ctx} productsByBlock={productsByBlock} />
        </div>
      </div>
    </section>
  );
}

/**
 * The editor holds a `StoreSite` (presentation) and, separately, the store
 * record (identity + address). The renderer expects the public `StorefrontShell`
 * shape, so assemble one.
 */
function buildPreviewShell(
  site: StoreSite,
  store: Record<string, unknown> | undefined,
): StorefrontShell {
  return {
    store: {
      id: site.store_id ?? '',
      slug: site.store_slug ?? null,
      name: site.store_name ?? (store?.name as string) ?? '',
      description: (store?.description as string) ?? null,
      logo_image: (store?.logo_image as string) ?? null,
      street1: (store?.street1 as string) ?? null,
      street2: (store?.street2 as string) ?? null,
      city: (store?.city as string) ?? null,
      state: (store?.state as string) ?? null,
      zip: (store?.zip as string) ?? null,
      country: (store?.country as string) ?? null,
      is_verified: Boolean(store?.is_verified),
    },
    theme: site.theme ?? {},
    logo_url: site.logo_url ?? null,
    favicon_url: site.favicon_url ?? null,
    tagline: site.tagline ?? null,
    hours: site.hours ?? [],
    social_links: site.social_links ?? [],
    contact_email: site.contact_email ?? null,
    contact_phone: site.contact_phone ?? null,
    directions_note: site.directions_note ?? null,
    seo: {
      title: site.seo_title ?? null,
      description: site.seo_description ?? null,
      og_image_url: site.og_image_url ?? null,
    },
    canonical_url: site.public_url ?? '',
    nav: (site.pages ?? [])
      .filter((page) => page.show_in_nav && page.is_published)
      .map((page) => ({
        slug: page.slug ?? '',
        label: page.nav_label || page.title || '',
        is_home: page.is_home ?? false,
      })),
  };
}
