import { Role, SportsPagePromotionStatus } from "@prisma/client";
import { prisma } from "../src/server/db";
import { env, isProductionRuntime } from "../src/server/env";
import { hashPassword } from "../src/server/security/password";
import { syncOddsFromProvider } from "../src/server/sync/odds-sync";
import { ensureWallet, creditAvailable } from "../src/server/wallet/ledger";
import { LedgerEntryType } from "@prisma/client";

async function main() {
  const config = env();
  if (isProductionRuntime(config)) {
    throw new Error("Seed is blocked in production.");
  }

  const adminEmail = config.ADMIN_BOOTSTRAP_EMAIL ?? "admin@zirabet.local";
  const adminPassword = config.ADMIN_BOOTSTRAP_PASSWORD ?? "ChangeMe-Admin-42";

  const admin = await prisma.user.upsert({
    where: { email: adminEmail },
    create: {
      email: adminEmail,
      username: "zirabet_admin",
      passwordHash: await hashPassword(adminPassword),
      status: "ACTIVE",
      roles: [Role.SUPER_ADMIN, Role.ADMIN],
      emailVerifiedAt: new Date(),
      profile: {
        create: {
          firstName: "Zirabet",
          lastName: "Admin",
          dateOfBirth: new Date("1990-01-01"),
          country: "BZ",
          currency: "EUR",
          language: "fr"
        }
      }
    },
    update: {
      roles: [Role.SUPER_ADMIN, Role.ADMIN],
      status: "ACTIVE"
    }
  });

  const player = await prisma.user.upsert({
    where: { email: "player@zirabet.local" },
    create: {
      email: "player@zirabet.local",
      username: "player_one",
      passwordHash: await hashPassword("Player-Password-42"),
      status: "ACTIVE",
      roles: [Role.USER],
      emailVerifiedAt: new Date(),
      profile: {
        create: {
          firstName: "Alex",
          lastName: "Rivera",
          dateOfBirth: new Date("1992-06-12"),
          country: "BZ",
          currency: "EUR",
          language: "fr",
          depositLimitDaily: "500.00",
          lossLimitDaily: "250.00",
          sessionLimitMinutes: 180
        }
      }
    },
    update: {}
  });

  await ensureWallet(admin.id, "EUR");
  await ensureWallet(player.id, "EUR");
  await creditAvailable({
    userId: player.id,
    currency: "EUR",
    amount: "1000",
    type: LedgerEntryType.DEPOSIT,
    referenceType: "dev_seed",
    referenceId: player.id,
    idempotencyKey: "seed:player:deposit:eur",
    reason: "Dev/staging seed balance"
  });

  await Promise.all([
    prisma.bonusPromotion.upsert({
      where: { code: "WELCOME_SPORT" },
      create: {
        code: "WELCOME_SPORT",
        name: "Sport Bonus de premier dépôt",
        status: "ACTIVE",
        type: "welcome_deposit",
        currency: "EUR",
        maxBonusAmount: "1000",
        wageringMultiplier: "1",
        contributionRules: {
          welcome: { matchPercent: 300, firstDepositOnly: true, promoCode: false },
          sportsbook: { football: 1, tennis: 0.7, basketball: 0.8, live: 1 }
        },
        startsAt: new Date(),
        terms: "Bonus sport crédité automatiquement sur le premier dépôt éligible."
      },
      update: {
        name: "Sport Bonus de premier dépôt",
        status: "ACTIVE",
        type: "welcome_deposit",
        maxBonusAmount: "1000",
        wageringMultiplier: "1",
        contributionRules: {
          welcome: { matchPercent: 300, firstDepositOnly: true, promoCode: false },
          sportsbook: { football: 1, tennis: 0.7, basketball: 0.8, live: 1 }
        },
        terms: "Bonus sport crédité automatiquement sur le premier dépôt éligible."
      }
    }),
    prisma.bonusPromotion.upsert({
      where: { code: "AZIA" },
      create: {
        code: "AZIA",
        name: "Code promo AZIA",
        status: "ACTIVE",
        type: "welcome_deposit",
        currency: "EUR",
        maxBonusAmount: "2500",
        wageringMultiplier: "1",
        contributionRules: {
          welcome: { matchPercent: 500, firstDepositOnly: true, promoCode: true },
          sportsbook: { all: 1 }
        },
        startsAt: new Date(),
        terms: "Code promotionnel crédité automatiquement sur le premier dépôt éligible."
      },
      update: {
        name: "Code promo AZIA",
        status: "ACTIVE",
        type: "welcome_deposit",
        maxBonusAmount: "2500",
        wageringMultiplier: "1",
        contributionRules: {
          welcome: { matchPercent: 500, firstDepositOnly: true, promoCode: true },
          sportsbook: { all: 1 }
        },
        terms: "Code promotionnel crédité automatiquement sur le premier dépôt éligible."
      }
    }),
    prisma.sportsPagePromotion.upsert({
      where: { id: "00000000-0000-0000-0000-00000000b001" },
      create: {
        id: "00000000-0000-0000-0000-00000000b001",
        title: "Cotes boostées du jour",
        subtitle: "Retrouvez les sélections sport mises en avant par ZiraBet.",
        badge: "Cotes boostées",
        imageUrl: "/images/home/promo-sport-boosts.png",
        href: "/sports#cote-boostee",
        status: SportsPagePromotionStatus.ACTIVE,
        sortOrder: 10,
        startsAt: new Date()
      },
      update: {
        title: "Cotes boostées du jour",
        subtitle: "Retrouvez les sélections sport mises en avant par ZiraBet.",
        badge: "Cotes boostées",
        imageUrl: "/images/home/promo-sport-boosts.png",
        href: "/sports#cote-boostee",
        status: SportsPagePromotionStatus.ACTIVE,
        sortOrder: 10
      }
    }),
    prisma.sportsPagePromotion.upsert({
      where: { id: "00000000-0000-0000-0000-00000000b002" },
      create: {
        id: "00000000-0000-0000-0000-00000000b002",
        title: "Offres sport ZiraBet",
        subtitle: "Les opérations sportsbook en cours, publiées par l'équipe admin.",
        badge: "Promotion",
        imageUrl: "/images/home/promo-sport-offers.png",
        href: "/promotions",
        status: SportsPagePromotionStatus.ACTIVE,
        sortOrder: 20,
        startsAt: new Date()
      },
      update: {
        title: "Offres sport ZiraBet",
        subtitle: "Les opérations sportsbook en cours, publiées par l'équipe admin.",
        badge: "Promotion",
        imageUrl: "/images/home/promo-sport-offers.png",
        href: "/promotions",
        status: SportsPagePromotionStatus.ACTIVE,
        sortOrder: 20
      }
    }),
    ...[
      ["wood", "Bois", "0", 10, 5, { support: "standard", levelBonusAmount: 0 }, 1],
      ["bronze", "Bronze", "500", 25, 10, { support: "standard", levelBonusAmount: 5 }, 2],
      ["silver", "Argent", "5000", 40, 20, { support: "standard", levelBonusAmount: 60 }, 3],
      ["gold", "Or", "50000", 75, 35, { support: "priority", levelBonusAmount: 250 }, 4],
      ["platinum", "Platine", "150000", 100, 50, { support: "priority", levelBonusAmount: 500 }, 5],
      ["jade", "Jade", "300000", 125, 65, { support: "priority", levelBonusAmount: 1000 }, 6],
      ["sapphire", "Saphir", "1000000", 150, 80, { support: "priority", manager: true, levelBonusAmount: 2500 }, 7],
      ["black", "Rubis", "5000000", 200, 110, { support: "priority", manager: true, levelBonusAmount: 10000 }, 8]
    ].map(([key, name, minVolume, cashbackBps, rakebackBps, perks, sortOrder]) =>
      prisma.vipTier.upsert({
        where: { key: String(key) },
        create: {
          key: String(key),
          name: String(name),
          minVolume: String(minVolume),
          cashbackBps: Number(cashbackBps),
          rakebackBps: Number(rakebackBps),
          perks,
          sortOrder: Number(sortOrder)
        },
        update: {
          name: String(name),
          minVolume: String(minVolume),
          cashbackBps: Number(cashbackBps),
          rakebackBps: Number(rakebackBps),
          perks,
          sortOrder: Number(sortOrder)
        }
      })
    )
  ]);

  await syncOddsFromProvider();

  console.log("Seed completed for dev/staging.");
  console.log(`Admin: ${adminEmail} / ${adminPassword}`);
  console.log("Player: player@zirabet.local / Player-Password-42");
}

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