import prisma from './prisma';
import { VendorListing } from '../scrapers/types';

export class PriceRepository {
  async saveListings(listings: VendorListing[]): Promise<void> {
    // Use a single timestamp for all listings in this batch
    const batchTimestamp = new Date();
    
    await prisma.vendorPrice.createMany({
      data: listings.map(listing => ({
        vendor: listing.vendor,
        sellerName: listing.seller,
        usdPrice: listing.priceUSD,
        auecAmount: listing.amountAUEC,
        usdPerMillion: listing.pricePerMillion,
        deliveryTime: listing.deliveryTime,
        url: listing.url,
        timestamp: batchTimestamp,
      })),
    });
  }

  async savePriceIndex(lowestPrice: number, vendor: string, sellerName?: string): Promise<void> {
    await prisma.priceIndex.create({
      data: {
        lowestPrice,
        vendor,
        sellerName,
      },
    });
  }

  async logScrape(status: string, message?: string, runtimeMs?: number): Promise<void> {
    await prisma.scrapeLog.create({
      data: {
        status,
        message,
        runtimeMs,
      },
    });
  }

  async getLatestPrices() {
    // Get the most recent timestamp across all vendors
    const latest = await prisma.vendorPrice.findFirst({
      orderBy: { timestamp: 'desc' },
      select: { timestamp: true },
    });

    if (!latest) return [];

    // Get all prices from that timestamp (all vendors)
    return prisma.vendorPrice.findMany({
      where: { timestamp: latest.timestamp },
      orderBy: { usdPerMillion: 'asc' },
    });
  }

  async getLatestPricesOld() {
    // Get the most recent timestamp for each vendor
    const latestEldorado = await prisma.vendorPrice.findFirst({
      where: { vendor: 'eldorado' },
      orderBy: { timestamp: 'desc' },
      select: { timestamp: true },
    });

    const latestPlayerAuctions = await prisma.vendorPrice.findFirst({
      where: { vendor: 'playerauctions' },
      orderBy: { timestamp: 'desc' },
      select: { timestamp: true },
    });

    // Get all prices from the latest scrape of each vendor
    const prices = [];
    
    if (latestEldorado) {
      const eldoradoPrices = await prisma.vendorPrice.findMany({
        where: {
          vendor: 'eldorado',
          timestamp: latestEldorado.timestamp,
        },
      });
      prices.push(...eldoradoPrices);
    }

    if (latestPlayerAuctions) {
      // Get all PlayerAuctions listings within 30 seconds of the latest timestamp
      const timeWindow = new Date(latestPlayerAuctions.timestamp.getTime() - 30000);
      const paPrices = await prisma.vendorPrice.findMany({
        where: {
          vendor: 'playerauctions',
          timestamp: {
            gte: timeWindow,
            lte: latestPlayerAuctions.timestamp,
          },
        },
      });
      prices.push(...paPrices);
    }

    // Sort by price
    return prices.sort((a, b) => 
      Number(a.usdPerMillion) - Number(b.usdPerMillion)
    );
  }

  async getLowestPrice() {
    const latest = await prisma.priceIndex.findFirst({
      orderBy: { timestamp: 'desc' },
    });

    return latest;
  }

  async getPricesBySeller(seller: string, platform?: string) {
    return prisma.vendorPrice.findMany({
      where: {
        sellerName: seller,
        ...(platform && { vendor: platform }),
      },
      orderBy: { timestamp: 'desc' },
      take: 100,
    });
  }

  async getPricesByPlatform(platform: string) {
    const latest = await prisma.vendorPrice.findFirst({
      where: { vendor: platform },
      orderBy: { timestamp: 'desc' },
      select: { timestamp: true },
    });

    if (!latest) return [];

    return prisma.vendorPrice.findMany({
      where: {
        vendor: platform,
        timestamp: latest.timestamp,
      },
      orderBy: { usdPerMillion: 'asc' },
    });
  }

  async getPriceHistory(from: Date, to: Date, seller?: string, platform?: string) {
    return prisma.vendorPrice.findMany({
      where: {
        timestamp: {
          gte: from,
          lte: to,
        },
        ...(seller && { sellerName: seller }),
        ...(platform && { vendor: platform }),
      },
      orderBy: { timestamp: 'asc' },
    });
  }

  async getIndexHistory(range: string) {
    const now = new Date();
    let from = new Date();

    switch (range) {
      case '1h':
        from = new Date(now.getTime() - 60 * 60 * 1000);
        break;
      case '6h':
        from = new Date(now.getTime() - 6 * 60 * 60 * 1000);
        break;
      case '24h':
        from = new Date(now.getTime() - 24 * 60 * 60 * 1000);
        break;
      case '7d':
        from = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
        break;
      case '30d':
        from = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
        break;
      case '90d':
        from = new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000);
        break;
      case 'all':
        from = new Date(0);
        break;
      default:
        from = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
    }

    return prisma.priceIndex.findMany({
      where: {
        timestamp: { gte: from },
      },
      orderBy: { timestamp: 'asc' },
    });
  }
}
