import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

/**
 * Seeds 90 days of mock metric snapshots, conversion events,
 * and channel metrics for each brand.
 *
 * Run: npx tsx prisma/seed-metrics.ts
 */
async function main() {
  console.log("Seeding metrics data...");

  const brands = await prisma.brand.findMany();
  if (brands.length === 0) {
    console.log("No brands found. Run the main seed first: npx tsx prisma/seed.ts");
    return;
  }

  const DAYS = 90;
  const channels = ["organic", "ai_search", "social", "gbp", "direct"] as const;
  const convTypes = ["phone", "form", "order", "booking"] as const;
  const pages = ["/", "/pricing", "/features", "/blog/seo-guide", "/contact", "/about", "/products"];
  const keywords = ["seo tool", "project management", "ai visibility", "website audit", "local seo", "content strategy"];

  for (const brand of brands) {
    console.log(`Seeding metrics for ${brand.name}...`);

    // Clear existing metric data for this brand
    await prisma.metricSnapshot.deleteMany({ where: { brandId: brand.id } });
    await prisma.conversionEvent.deleteMany({ where: { brandId: brand.id } });
    await prisma.channelMetric.deleteMany({ where: { brandId: brand.id } });

    // Base values per brand (vary by brand)
    const base = getBrandBase(brand.id);

    for (let d = DAYS; d >= 0; d--) {
      const date = new Date();
      date.setDate(date.getDate() - d);
      date.setHours(12, 0, 0, 0);

      // Growth factor — slight upward trend over time
      const growth = 1 + ((DAYS - d) / DAYS) * 0.15;
      const noise = () => 0.85 + Math.random() * 0.3;
      const weekday = date.getDay();
      const weekendDip = weekday === 0 || weekday === 6 ? 0.65 : 1;

      // Daily snapshot
      const sessions = Math.round(base.sessions * growth * noise() * weekendDip);
      const users = Math.round(sessions * 0.75);
      const organicClicks = Math.round(base.clicks * growth * noise() * weekendDip);
      const dayConversions = Math.round(base.conversions * growth * noise() * weekendDip);
      const dayRevenue = Math.round(base.revenue * growth * noise() * weekendDip);

      await prisma.metricSnapshot.create({
        data: {
          brandId: brand.id,
          date,
          sessions,
          users,
          pageviews: Math.round(sessions * 2.4),
          bounceRate: Math.round((0.35 + Math.random() * 0.15) * 100) / 100,
          avgSessionSec: Math.round(120 + Math.random() * 120),
          organicClicks,
          impressions: Math.round(organicClicks * (15 + Math.random() * 5)),
          avgPosition: Math.round((10 + Math.random() * 8) * 10) / 10,
          ctr: Math.round((0.04 + Math.random() * 0.03) * 1000) / 1000,
          seoScore: Math.min(100, base.seoScore + Math.round((DAYS - d) / DAYS * 8)),
          crawlHealth: Math.min(100, base.crawlHealth + Math.round((DAYS - d) / DAYS * 5)),
          aiMentions: Math.round(base.aiMentions * noise()),
          revenue: dayRevenue,
          conversions: dayConversions,
        },
      });

      // Channel metrics
      for (const channel of channels) {
        const channelShare = getChannelShare(channel);
        await prisma.channelMetric.create({
          data: {
            brandId: brand.id,
            date,
            channel,
            sessions: Math.round(sessions * channelShare),
            users: Math.round(users * channelShare),
            conversions: Math.round(dayConversions * channelShare * (channel === "organic" ? 1.3 : 0.8)),
            revenue: Math.round(dayRevenue * channelShare * (channel === "organic" ? 1.3 : 0.8)),
            bounceRate: Math.round((0.3 + Math.random() * 0.2) * 100) / 100,
          },
        });
      }

      // Conversion events (random number per day)
      const eventCount = Math.max(0, dayConversions + Math.round((Math.random() - 0.5) * 4));
      for (let e = 0; e < eventCount; e++) {
        const type = convTypes[Math.floor(Math.random() * convTypes.length)];
        const channel = weightedChannel();
        const value = type === "order" ? 50 + Math.round(Math.random() * 200) :
                      type === "booking" ? 100 + Math.round(Math.random() * 300) :
                      type === "form" ? 0 :
                      0;

        await prisma.conversionEvent.create({
          data: {
            brandId: brand.id,
            date,
            type,
            channel,
            value,
            landingPage: pages[Math.floor(Math.random() * pages.length)],
            keyword: Math.random() > 0.3 ? keywords[Math.floor(Math.random() * keywords.length)] : null,
            source: channel === "organic" ? "google" : channel === "social" ? "linkedin" : channel === "gbp" ? "google_maps" : null,
          },
        });
      }
    }

    console.log(`  → ${DAYS + 1} days of snapshots, channel metrics, and conversion events`);
  }

  console.log("Metrics seeding complete!");
}

function getBrandBase(brandId: string) {
  const bases: Record<string, { sessions: number; clicks: number; conversions: number; revenue: number; seoScore: number; crawlHealth: number; aiMentions: number }> = {
    "acme-corp":     { sessions: 280, clicks: 180, conversions: 8, revenue: 820, seoScore: 68, crawlHealth: 88, aiMentions: 12 },
    "beacon-health": { sessions: 410, clicks: 260, conversions: 12, revenue: 1200, seoScore: 76, crawlHealth: 86, aiMentions: 18 },
    "nova-digital":  { sessions: 110, clicks: 60, conversions: 3, revenue: 280, seoScore: 55, crawlHealth: 72, aiMentions: 5 },
  };
  return bases[brandId] ?? bases["acme-corp"];
}

function getChannelShare(channel: string): number {
  const shares: Record<string, number> = {
    organic: 0.55, ai_search: 0.08, social: 0.12, gbp: 0.10, direct: 0.15,
  };
  return shares[channel] ?? 0.1;
}

function weightedChannel(): string {
  const r = Math.random();
  if (r < 0.55) return "organic";
  if (r < 0.63) return "ai_search";
  if (r < 0.75) return "social";
  if (r < 0.85) return "gbp";
  return "direct";
}

main()
  .catch((e) => { console.error(e); process.exit(1); })
  .finally(() => prisma.$disconnect());
