import { Page } from 'playwright';
import { BaseScraper } from './base-scraper';
import { VendorListing } from './types';

export class PlayerAuctionsScraper extends BaseScraper {
  getVendorName(): 'playerauctions' {
    return 'playerauctions';
  }

  getTargetUrl(): string {
    return 'https://www.playerauctions.com/star-citizen-auec/';
  }

  async extractListings(page: Page): Promise<VendorListing[]> {
    // Wait for page readiness
    await page.waitForTimeout(3000);

    // Close cookie popup if it exists
    try {
      const cookieClose = page.locator('[id*="cookie"] button, [class*="cookie"] button, button:has-text("Accept"), button:has-text("Close")').first();
      if (await cookieClose.isVisible({ timeout: 2000 }).catch(() => false)) {
        await cookieClose.click();
        await page.waitForTimeout(500);
      }
    } catch (e) {
      // No cookie popup or already closed
    }

    // Find offer cards - they have class "offer-item"
    const offerCards = await page.locator('.offer-item, [class*="offer-item"]').all();

    if (offerCards.length === 0) {
      return this.extractListingsAlternative(page);
    }

    const listings: VendorListing[] = [];
    const targetQuantityM = 1000000; // 1000000 M = 1 trillion AUEC (field is already in millions)

    // Step 2-5: Process each offer card
    for (let i = 0; i < Math.min(offerCards.length, 20); i++) {
      try {
        const card = offerCards[i];

        // Find the quantity input (shows number with "M" suffix, has +/- buttons)
        const qtyInput = card.locator('input[type="number"]').first();
        
        if (!(await qtyInput.isVisible({ timeout: 1000 }).catch(() => false))) {
          continue;
        }

        // Set quantity to 1000000 (which means 1000000 M = 1 trillion AUEC)
        await qtyInput.scrollIntoViewIfNeeded();
        await qtyInput.click({ force: true });
        await qtyInput.fill('');
        await qtyInput.pressSequentially(targetQuantityM.toString(), { delay: 10 });
        await qtyInput.press('Enter'); // Trigger update
        
        // Wait for price to update (0.5-2 seconds as per instructions)
        await page.waitForTimeout(2500);

        // Step 3: Extract the total price from the BUY NOW button area
        // Look for the price near the BUY NOW button - it's typically in a large font
        let totalPriceUSD = 0;
        
        // Try to find the price element near BUY NOW button
        const buyNowButton = card.locator('button:has-text("BUY NOW"), [class*="buy"]').first();
        if (await buyNowButton.isVisible().catch(() => false)) {
          // Get the parent container and look for price nearby
          const priceContainer = buyNowButton.locator('xpath=..').first();
          const priceText = await priceContainer.textContent().catch(() => '');
          
          // Extract price - should be like "$5.00" in large text
          if (priceText) {
            const priceMatch = priceText.match(/\$\s*([\d,]+\.\d{2})/);
            if (priceMatch) {
              totalPriceUSD = parseFloat(priceMatch[1].replace(/,/g, ''));
            }
          }
        }
        
        // Fallback: look for price in the card, but exclude "Minutes" context
        if (totalPriceUSD === 0) {
          const cardText = await card.textContent().catch(() => '');
          if (cardText) {
            const lines = cardText.split('\n').map(l => l.trim());
          
          for (const line of lines) {
            // Skip lines that contain time indicators
            if (line.includes('Minutes') || line.includes('Hours') || line.includes('Days')) {
              continue;
            }
            
            // Look for price pattern with decimal
            const priceMatch = line.match(/\$\s*([\d,]+\.\d{2})/);
            if (priceMatch) {
              const price = parseFloat(priceMatch[1].replace(/,/g, ''));
              if (price > 0 && price < 100000) {
                totalPriceUSD = price;
                break;
              }
            }
          }
          }
        }
        
        if (totalPriceUSD === 0) {
          continue;
        }

        // Step 4: Compute USD per 1M
        const pricePerMillion = totalPriceUSD / targetQuantityM;

        // Extract seller name and delivery time from card text
        const fullCardText = await card.textContent().catch(() => '');
        const sellerMatch = fullCardText ? fullCardText.match(/([a-zA-Z0-9_-]{3,20})/) : null;
        const seller = sellerMatch ? sellerMatch[1] : 'Unknown';

        const deliveryMatch = fullCardText ? fullCardText.match(/(\d+\s*(?:Minutes?|Hours?|Days?))/i) : null;
        const deliveryTime = deliveryMatch ? deliveryMatch[1] : undefined;

        listings.push({
          vendor: 'playerauctions',
          amountAUEC: targetQuantityM * 1_000_000,
          priceUSD: totalPriceUSD,
          pricePerMillion,
          seller: seller.trim(),
          deliveryTime,
          scrapedAt: new Date(),
          url: this.getTargetUrl(),
        });

      } catch (error) {
        // Skip this card
      }
    }

    if (listings.length === 0) {
      return this.extractListingsAlternative(page);
    }

    return listings;
  }

  private async extractListingsAlternative(page: Page): Promise<VendorListing[]> {

    const listings = await page.evaluate(() => {
      const results: Array<{
        amountAUEC: number;
        priceUSD: number;
        pricePerMillion: number;
        seller?: string;
      }> = [];

      const bodyText = document.body.innerText;
      const lines = bodyText.split('\n').map((l: string) => l.trim()).filter((l: string) => l.length > 0);

      const seenPrices = new Set<number>();

      for (let i = 0; i < lines.length; i++) {
        const line = lines[i];

        // Look for "$1 = X M aUEC" pattern and convert
        const exchangeMatch = line.match(/\$1\s*=\s*([\d,]+(?:\.\d+)?)\s*M\s*(?:aUEC)?/i);
        
        if (exchangeMatch) {
          const millionsPerDollar = parseFloat(exchangeMatch[1].replace(/,/g, ''));
          const pricePerMillion = 1 / millionsPerDollar;

          if (seenPrices.has(pricePerMillion)) continue;
          seenPrices.add(pricePerMillion);

          const targetQuantityM = 1000000;
          const amountAUEC = targetQuantityM * 1_000_000;
          const priceUSD = pricePerMillion * targetQuantityM;

          results.push({
            amountAUEC,
            priceUSD,
            pricePerMillion,
            seller: 'Unknown',
          });
        }
      }

      return results;
    });

    const scrapedAt = new Date();
    const url = this.getTargetUrl();

    return listings.map((listing: any) => ({
      vendor: 'playerauctions' as const,
      amountAUEC: listing.amountAUEC,
      priceUSD: listing.priceUSD,
      pricePerMillion: listing.pricePerMillion,
      seller: listing.seller,
      deliveryTime: undefined,
      scrapedAt,
      url,
    }));
  }
}
