← back to Wine Finder Next

lib/services/mockWineData.ts

166 lines

/**
 * Mock Wine Data Generator
 * Generates realistic auction and retail data for testing the arbitrage UI
 * until real API keys are obtained
 */

export interface MockWineListing {
  id: string;
  name: string;
  vintage?: number;
  region?: string;
  rating?: number;
  provider: 'auction' | 'retail';
  providerName: string;
  currentPrice: {
    amount: number;
    currency: string;
  };
  url: string;
  imageUrl?: string;
  availability?: string;
  bidCount?: number;
  closingDate?: string;
  lastUpdated: string;
  lastSale?: {
    price: number;
    source: string;
    date: string;
    daysAgo: number;
  };
}

const PREMIUM_WINES = [
  { name: 'Caymus Cabernet Sauvignon', vintage: 2021, region: 'Napa Valley, California' },
  { name: 'Opus One', vintage: 2019, region: 'Napa Valley, California' },
  { name: 'Silver Oak Cabernet Sauvignon', vintage: 2020, region: 'Alexander Valley, California' },
  { name: 'Screaming Eagle Cabernet Sauvignon', vintage: 2018, region: 'Napa Valley, California' },
  { name: 'Stags Leap Wine Cellars Artemis Cabernet', vintage: 2021, region: 'Napa Valley, California' },
  { name: 'Duckhorn Merlot', vintage: 2020, region: 'Napa Valley, California' },
  { name: 'Far Niente Chardonnay', vintage: 2022, region: 'Napa Valley, California' },
  { name: 'Shafer Hillside Select Cabernet', vintage: 2019, region: 'Napa Valley, California' },
  { name: 'Ridge Monte Bello', vintage: 2020, region: 'Santa Cruz Mountains, California' },
  { name: 'Joseph Phelps Insignia', vintage: 2019, region: 'Napa Valley, California' },
  { name: 'Dom Pérignon Champagne', vintage: 2013, region: 'Champagne, France' },
  { name: 'Château Margaux', vintage: 2016, region: 'Bordeaux, France' },
  { name: 'Château Lafite Rothschild', vintage: 2015, region: 'Pauillac, Bordeaux, France' },
  { name: 'Penfolds Grange', vintage: 2018, region: 'South Australia' },
  { name: 'Cloudy Bay Sauvignon Blanc', vintage: 2023, region: 'Marlborough, New Zealand' },
];

export function generateMockWineData(query: string): MockWineListing[] {
  const wines: MockWineListing[] = [];
  const now = new Date().toISOString();

  // Filter wines that match the query
  const matchingWines = PREMIUM_WINES.filter(wine =>
    wine.name.toLowerCase().includes(query.toLowerCase()) ||
    query.toLowerCase().split(' ').some(term => wine.name.toLowerCase().includes(term))
  );

  // If no matches, use first 5 wines
  const winesToUse = matchingWines.length > 0 ? matchingWines : PREMIUM_WINES.slice(0, 5);

  winesToUse.forEach((wine, idx) => {
    // Generate retail listing (lower price)
    const basePrice = 50 + (idx * 20);
    const retailPrice = basePrice + Math.random() * 50;

    wines.push({
      id: `vivino-${wine.name.toLowerCase().replace(/\s+/g, '-')}-${wine.vintage}`,
      name: wine.name,
      vintage: wine.vintage,
      region: wine.region,
      rating: 4.0 + Math.random() * 0.9,
      provider: 'retail',
      providerName: 'Vivino',
      currentPrice: {
        amount: parseFloat(retailPrice.toFixed(2)),
        currency: 'USD',
      },
      url: `https://www.vivino.com/wines/${idx + 1000}`,
      imageUrl: 'https://images.vivino.com/thumbs/placeholder_pl_480x640.png',
      availability: 'In Stock',
      lastUpdated: now,
    });

    // Generate Wine.com retail listing (slightly different price)
    wines.push({
      id: `winecom-${wine.name.toLowerCase().replace(/\s+/g, '-')}-${wine.vintage}`,
      name: wine.name,
      vintage: wine.vintage,
      region: wine.region,
      rating: 4.0 + Math.random() * 0.9,
      provider: 'retail',
      providerName: 'Wine.com',
      currentPrice: {
        amount: parseFloat((retailPrice + Math.random() * 20 - 10).toFixed(2)),
        currency: 'USD',
      },
      url: `https://www.wine.com/product/${idx + 5000}`,
      availability: 'In Stock',
      lastUpdated: now,
    });

    // Generate auction listings (higher prices for arbitrage opportunities)
    const auctionPrice = retailPrice + 50 + Math.random() * 100;
    const daysAgo = Math.floor(Math.random() * 90) + 1; // 1-90 days ago
    const lastSaleDate = new Date(Date.now() - (daysAgo * 24 * 60 * 60 * 1000));

    wines.push({
      id: `winebid-${wine.name.toLowerCase().replace(/\s+/g, '-')}-${wine.vintage}`,
      name: wine.name,
      vintage: wine.vintage,
      region: wine.region,
      provider: 'auction',
      providerName: 'WineBid',
      currentPrice: {
        amount: parseFloat(auctionPrice.toFixed(2)),
        currency: 'USD',
      },
      url: `https://www.winebid.com/auction/${idx + 10000}`,
      bidCount: Math.floor(Math.random() * 20) + 5,
      closingDate: new Date(Date.now() + Math.random() * 7 * 24 * 60 * 60 * 1000).toISOString(),
      lastUpdated: now,
      lastSale: {
        price: parseFloat((auctionPrice * (0.85 + Math.random() * 0.25)).toFixed(2)), // ±15% from current
        source: 'WineBid',
        date: lastSaleDate.toISOString(),
        daysAgo,
      },
    });

    // Sometimes add Zachys auction
    if (Math.random() > 0.5) {
      const zachysPrice = auctionPrice + Math.random() * 30 - 15;
      const zachysDaysAgo = Math.floor(Math.random() * 60) + 1;
      const zachysLastSale = new Date(Date.now() - (zachysDaysAgo * 24 * 60 * 60 * 1000));

      wines.push({
        id: `zachys-${wine.name.toLowerCase().replace(/\s+/g, '-')}-${wine.vintage}`,
        name: wine.name,
        vintage: wine.vintage,
        region: wine.region,
        provider: 'auction',
        providerName: 'Zachys',
        currentPrice: {
          amount: parseFloat(zachysPrice.toFixed(2)),
          currency: 'USD',
        },
        url: `https://www.zachys.com/auction/${idx + 20000}`,
        bidCount: Math.floor(Math.random() * 15) + 3,
        closingDate: new Date(Date.now() + Math.random() * 14 * 24 * 60 * 60 * 1000).toISOString(),
        lastUpdated: now,
        lastSale: {
          price: parseFloat((zachysPrice * (0.9 + Math.random() * 0.2)).toFixed(2)),
          source: 'Zachys',
          date: zachysLastSale.toISOString(),
          daysAgo: zachysDaysAgo,
        },
      });
    }
  });

  return wines;
}