import "dotenv/config";
import { PrismaClient, Prisma } from "@prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
import bcrypt from "bcryptjs";
import { getIsoWeek } from "../src/lib/week";

const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
const prisma = new PrismaClient({ adapter });

async function main() {
  const password = process.env.SEED_SUPER_ADMIN_PASSWORD ?? "ChangeMe123!";
  const superEmail =
    process.env.SEED_SUPER_ADMIN_EMAIL ?? "admin@optimumtrain.app";
  const hash = (pw: string) => bcrypt.hashSync(pw, 10);

  console.log("→ Seeding users…");
  const superAdmin = await prisma.user.upsert({
    where: { email: superEmail },
    update: {},
    create: {
      email: superEmail,
      name: "Super Admin",
      role: "SUPER_ADMIN",
      passwordHash: hash(password),
    },
  });

  const manager = await prisma.user.upsert({
    where: { email: "manager@optimumtrain.app" },
    update: {},
    create: {
      email: "manager@optimumtrain.app",
      name: "Marketing Manager",
      role: "MANAGER",
      passwordHash: hash("Manager123!"),
    },
  });

  const staffSeed = [
    { email: "seo@optimumtrain.app", name: "Sara SEO", position: "SEO Specialist" },
    { email: "media@optimumtrain.app", name: "Mike Media", position: "Media Buyer" },
    { email: "content@optimumtrain.app", name: "Cara Content", position: "Content Creator" },
    { email: "copy@optimumtrain.app", name: "Cody Copy", position: "Copywriter" },
  ];
  const staff = [];
  for (const s of staffSeed) {
    staff.push(
      await prisma.user.upsert({
        where: { email: s.email },
        update: {},
        create: {
          email: s.email,
          name: s.name,
          role: "STAFF",
          position: s.position,
          passwordHash: hash("Staff123!"),
        },
      })
    );
  }

  console.log("→ Seeding companies & channels…");
  // Wipe dependent data first so the seed stays idempotent.
  await prisma.post.deleteMany({});
  await prisma.platform.deleteMany({});
  await prisma.taskContributionLog.deleteMany({});
  await prisma.kpiIndicator.deleteMany({});
  await prisma.company.deleteMany({});
  await prisma.marketingChannel.deleteMany({});

  const companyA = await prisma.company.create({ data: { name: "Company A" } });
  const companyB = await prisma.company.create({ data: { name: "Company B" } });

  // Editable marketing channels (multi-select on KPIs).
  const channelNames = ["Meta", "Google", "TikTok", "Offline", "SEO", "Email", "Other"];
  const channels = [];
  for (const name of channelNames) {
    channels.push(await prisma.marketingChannel.create({ data: { name } }));
  }
  const channelByName = Object.fromEntries(channels.map((c) => [c.name, c]));

  console.log("→ Seeding company financials (this & last month)…");
  const finNow = new Date();
  const finCy = finNow.getFullYear();
  const finCm = finNow.getMonth() + 1;
  const finPrev = finCm === 1 ? { y: finCy - 1, m: 12 } : { y: finCy, m: finCm - 1 };
  // [budget, adSpend, revenue, leads, trials, enrollments] per company.
  const finSets: Record<string, number[]> = {
    [companyA.id]: [10000, 9200, 42000, 320, 180, 96],
    [companyB.id]: [8000, 8600, 31000, 240, 120, 64],
  };
  for (const [companyId, s] of Object.entries(finSets)) {
    await prisma.companyMonthlyFinancials.create({
      data: { companyId, year: finCy, month: finCm, budget: s[0], adSpend: s[1], revenue: s[2], leads: s[3], trials: s[4], enrollments: s[5] },
    });
    await prisma.companyMonthlyFinancials.create({
      data: {
        companyId,
        year: finPrev.y,
        month: finPrev.m,
        budget: s[0],
        adSpend: Math.round(s[1] * 0.85),
        revenue: Math.round(s[2] * 0.82),
        leads: Math.round(s[3] * 0.85),
        trials: Math.round(s[4] * 0.85),
        enrollments: Math.round(s[5] * 0.8),
      },
    });
  }

  console.log("→ Seeding KPI indicators…");
  // DEPARTMENT KPIs roll up to a company; PERSONAL KPIs target one staff member.
  const deptKpis: Prisma.KpiIndicatorUncheckedCreateInput[] = [
    { name: "Cost Per Lead", category: "SPEND", targetValue: 15, currentValue: 18.5, unit: "RM", period: "MONTHLY", type: "DEPARTMENT", weightage: 30, companyId: companyA.id, channels: { connect: [{ id: channelByName["Meta"].id }] } },
    { name: "Creative Designs", category: "OUTPUT", targetValue: 40, currentValue: 26, unit: "Count", period: "MONTHLY", type: "DEPARTMENT", weightage: 20, companyId: companyA.id },
    { name: "Posts per Month", category: "OUTPUT", targetValue: 30, currentValue: 18, unit: "Count", period: "MONTHLY", type: "DEPARTMENT", weightage: 20, companyId: companyA.id, channels: { connect: [{ id: channelByName["Meta"].id }, { id: channelByName["TikTok"].id }] } },
    { name: "Total Registrations", category: "ACQUISITION", targetValue: 200, currentValue: 132, unit: "Count", period: "MONTHLY", type: "DEPARTMENT", weightage: 30, companyId: companyB.id },
    { name: "Meta Ad CTR", category: "ENGAGEMENT", targetValue: 2.5, currentValue: 1.9, unit: "%", period: "MONTHLY", type: "DEPARTMENT", weightage: 20, companyId: companyB.id, channels: { connect: [{ id: channelByName["Meta"].id }] } },
    { name: "Free Trial Form Conversion", category: "CONVERSION", targetValue: 12, currentValue: 9.4, unit: "%", period: "MONTHLY", type: "DEPARTMENT", weightage: 20, companyId: companyB.id },
  ];
  const personalKpis: Prisma.KpiIndicatorUncheckedCreateInput[] = [
    { name: "Organic Keywords in Top 10", category: "ACQUISITION", targetValue: 25, currentValue: 14, unit: "Count", period: "MONTHLY", type: "PERSONAL", assignedUserId: staff[0].id, assignedPosition: staff[0].position },
    { name: "Backlinks Acquired", category: "ACQUISITION", targetValue: 20, currentValue: 11, unit: "Count", period: "MONTHLY", type: "PERSONAL", assignedUserId: staff[0].id, assignedPosition: staff[0].position },
    { name: "ROAS", category: "REVENUE", targetValue: 4, currentValue: 3.2, unit: "x", period: "MONTHLY", type: "PERSONAL", assignedUserId: staff[1].id, assignedPosition: staff[1].position },
    { name: "Ad Spend Managed", category: "SPEND", targetValue: 20000, currentValue: 17400, unit: "RM", period: "MONTHLY", type: "PERSONAL", assignedUserId: staff[1].id, assignedPosition: staff[1].position },
    { name: "Content Pieces Published", category: "OUTPUT", targetValue: 12, currentValue: 7, unit: "Count", period: "MONTHLY", type: "PERSONAL", assignedUserId: staff[2].id, assignedPosition: staff[2].position },
    { name: "Landing Pages Written", category: "OUTPUT", targetValue: 8, currentValue: 5, unit: "Count", period: "MONTHLY", type: "PERSONAL", assignedUserId: staff[3].id, assignedPosition: staff[3].position },
  ];

  const createdKpis = [];
  for (const k of [...deptKpis, ...personalKpis]) {
    createdKpis.push(await prisma.kpiIndicator.create({ data: k }));
  }
  const kpiByName = Object.fromEntries(createdKpis.map((k) => [k.name, k]));

  console.log("→ Seeding monthly KPI values (this & last month)…");
  const seedNow = new Date();
  const cy = seedNow.getFullYear();
  const cm = seedNow.getMonth() + 1;
  const prev = cm === 1 ? { y: cy - 1, m: 12 } : { y: cy, m: cm - 1 };
  for (const k of createdKpis) {
    await prisma.kpiMonthlyValue.create({
      data: { kpiIndicatorId: k.id, year: cy, month: cm, targetValue: k.targetValue, actualValue: k.currentValue },
    });
    await prisma.kpiMonthlyValue.create({
      data: {
        kpiIndicatorId: k.id,
        year: prev.y,
        month: prev.m,
        targetValue: k.targetValue,
        actualValue: Math.round(k.currentValue * 0.8 * 100) / 100,
      },
    });
  }

  console.log("→ Seeding social-media platforms…");
  const platformNames = ["Facebook", "Instagram", "TikTok", "YouTube", "LinkedIn"];
  const platforms = [];
  for (const name of platformNames) {
    platforms.push(await prisma.platform.create({ data: { name } }));
  }
  const platformByName = Object.fromEntries(platforms.map((p) => [p.name, p]));

  console.log("→ Seeding tasks + contributions…");
  const { week, year } = getIsoWeek(new Date());
  await prisma.task.deleteMany({});

  const sampleTasks = [
    { assignee: staff[0], title: "Optimise Quayside Mall landing page meta tags", status: "COMPLETED" as const, priority: "HIGH" as const, channel: "SEO" as const, dept: "Total Registrations", personal: "Organic Keywords in Top 10", delta: 3 },
    { assignee: staff[0], title: "Outreach for 5 parenting-blog backlinks", status: "IN_PROGRESS" as const, priority: "MEDIUM" as const, channel: "SEO" as const, dept: null, personal: "Backlinks Acquired", delta: 0 },
    { assignee: staff[1], title: "Launch Meta retargeting campaign — Kota Kemuning", status: "COMPLETED" as const, priority: "HIGH" as const, channel: "META" as const, dept: "Meta Ad CTR", personal: "ROAS", delta: 0.4 },
    { assignee: staff[1], title: "Reallocate budget to top 3 ad sets", status: "REVIEW" as const, priority: "MEDIUM" as const, channel: "META" as const, dept: "Cost Per Lead", personal: "Ad Spend Managed", delta: 1200 },
    { assignee: staff[2], title: "Write water-safety blog article", status: "COMPLETED" as const, priority: "MEDIUM" as const, channel: "SEO" as const, dept: null, personal: "Content Pieces Published", delta: 1 },
    { assignee: staff[3], title: "Rewrite Free Trial form copy", status: "TO_DO" as const, priority: "HIGH" as const, channel: "OTHER" as const, dept: "Free Trial Form Conversion", personal: "Landing Pages Written", delta: 0 },
  ];

  for (const t of sampleTasks) {
    const task = await prisma.task.create({
      data: {
        title: t.title,
        status: t.status,
        priority: t.priority,
        channel: t.channel,
        weekNumber: week,
        weekYear: year,
        userId: t.assignee.id,
        createdById: manager.id,
      },
    });
    const links: { name: string | null; delta: number }[] = [
      { name: t.dept, delta: t.delta },
      { name: t.personal, delta: t.delta },
    ];
    for (const link of links) {
      if (!link.name || !kpiByName[link.name]) continue;
      await prisma.taskContributionLog.create({
        data: {
          taskId: task.id,
          kpiIndicatorId: kpiByName[link.name].id,
          impactDescription: `Contribution from: ${t.title}`,
          metricDelta: link.delta,
        },
      });
    }
  }

  console.log("→ Seeding scheduled posts…");
  // Cara Content drafts social posts; the manager reviews them (FR-3).
  const author = staff[2];
  const samplePosts = [
    {
      title: "June water-safety tip",
      content: "☀️ Summer's here! Never leave kids unattended near water. Book a free trial class this week. #WaterSafety",
      mediaUrl: "https://drive.google.com/file/example-carousel",
      mediaNotes: "3 carousel images",
      status: "PENDING_APPROVAL" as const,
      platforms: ["Facebook", "Instagram"],
    },
    {
      title: "New Kota Kemuning class times",
      content: "📣 New weekend slots open at our Kota Kemuning pool! Limited spots — register today.",
      mediaUrl: "https://canva.com/design/example-reel",
      mediaNotes: "15s reel",
      status: "APPROVED" as const,
      platforms: ["Instagram", "TikTok"],
    },
    {
      title: "Parent testimonial — Sarah",
      content: "💙 'My daughter went from scared to swimming in 6 weeks!' — Sarah, parent of a Level 2 student.",
      mediaUrl: "https://youtube.com/watch?v=example",
      mediaNotes: "30s testimonial video",
      status: "DRAFT" as const,
      platforms: ["Facebook", "YouTube"],
    },
  ];
  for (const p of samplePosts) {
    await prisma.post.create({
      data: {
        title: p.title,
        content: p.content,
        mediaUrl: p.mediaUrl,
        mediaNotes: p.mediaNotes,
        status: p.status,
        authorId: author.id,
        reviewerId: p.status === "APPROVED" ? manager.id : null,
        platforms: { connect: p.platforms.map((n) => ({ id: platformByName[n].id })) },
      },
    });
  }

  console.log("\n✅ Seed complete.");
  console.log("   Super Admin:", superAdmin.email, "/", password);
  console.log("   Manager:    ", manager.email, "/ Manager123!");
  console.log("   Staff:       seo@ / media@ / content@ / copy@ optimumtrain.app / Staff123!");
}

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