import "server-only";
import { BoostedOddStatus, EventStatus, MarketStatus, SelectionStatus, SportsPagePromotionStatus } from "@prisma/client";
import { prisma } from "@/server/db";
import { env } from "@/server/env";
import { refreshEventMarketsFromProvider } from "@/server/sync/odds-sync";

export async function getSportsbookLobby(input?: { sportSlug?: string; liveOnly?: boolean }) {
  try {
    const config = env();
    const now = new Date();
    const windowEnd = new Date(now.getTime() + config.ODDS_PREMATCH_WINDOW_DAYS * 24 * 60 * 60 * 1000);
    const sports = await prisma.sport.findMany({
      where: {
        isActive: true,
        events: {
          some: {
            status: EventStatus.SCHEDULED,
            isLive: false,
            startsAt: { gt: now, lte: windowEnd },
            OR: [{ providerKey: null }, { providerKey: { not: { startsWith: "boost" } } }]
          }
        }
      },
      orderBy: [{ sortOrder: "asc" }, { name: "asc" }]
    });
    const sportsPromotionsPromise = prisma.sportsPagePromotion.findMany({
      where: {
        status: SportsPagePromotionStatus.ACTIVE,
        startsAt: { lte: now },
        OR: [{ endsAt: null }, { endsAt: { gt: now } }]
      },
      orderBy: [{ sortOrder: "asc" }, { startsAt: "desc" }],
      take: 8
    });

    if (input?.liveOnly) {
      const sportsPromotions = await sportsPromotionsPromise;
      return { sports, events: [], boostedOdds: [], sportsPromotions, unavailable: false, liveDisabled: true };
    }

    const [events, boostedOdds, sportsPromotions] = await Promise.all([
      prisma.event.findMany({
        where: {
          ...(input?.sportSlug ? { sport: { slug: input.sportSlug } } : {}),
          status: EventStatus.SCHEDULED,
          isLive: false,
          startsAt: { gt: now, lte: windowEnd },
          OR: [{ providerKey: null }, { providerKey: { not: { startsWith: "boost" } } }]
        },
        include: {
          sport: true,
          competition: true,
          markets: {
            where: { status: MarketStatus.OPEN },
            include: {
              selections: {
                where: { status: SelectionStatus.ACTIVE },
                orderBy: { key: "asc" }
              }
            },
            orderBy: { key: "asc" }
          }
        },
        orderBy: [{ startsAt: "asc" }],
        take: 1000
      }),
      prisma.boostedOdd.findMany({
        where: {
          status: BoostedOddStatus.ACTIVE,
          startsAt: { gt: now },
          event: {
            ...(input?.sportSlug ? { sport: { slug: input.sportSlug } } : {}),
            status: EventStatus.SCHEDULED,
            isLive: false,
            startsAt: { gt: now, lte: windowEnd }
          },
          market: { status: MarketStatus.OPEN },
          selection: { status: SelectionStatus.ACTIVE }
        },
        include: {
          category: true,
          event: {
            include: {
              sport: true,
              competition: true
            }
          },
          market: true,
          selection: true
        },
        orderBy: [{ category: { sortOrder: "asc" } }, { sortOrder: "asc" }, { startsAt: "asc" }],
        take: 10
      }),
      sportsPromotionsPromise
    ]);

    return { sports, events, boostedOdds, sportsPromotions, unavailable: false };
  } catch {
    return { sports: [], events: [], boostedOdds: [], sportsPromotions: [], unavailable: true };
  }
}

export async function getPromotions() {
  try {
    const promotions = await prisma.bonusPromotion.findMany({
      where: { status: "ACTIVE", startsAt: { lte: new Date() }, OR: [{ endsAt: null }, { endsAt: { gt: new Date() } }] },
      orderBy: { startsAt: "desc" }
    });
    return { promotions, unavailable: false };
  } catch {
    return { promotions: [], unavailable: true };
  }
}

export async function getEventDetails(eventId: string) {
  const now = new Date();
  const windowEnd = new Date(now.getTime() + env().ODDS_PREMATCH_WINDOW_DAYS * 24 * 60 * 60 * 1000);
  const event = await findEventDetails(eventId, now, windowEnd);

  if (!event || hasEnoughMarketsForDetail(event)) {
    return event;
  }

  await refreshEventMarketsFromProvider(eventId).catch(() => undefined);
  return findEventDetails(eventId, now, windowEnd);
}

function findEventDetails(eventId: string, now: Date, windowEnd: Date) {
  return prisma.event.findFirst({
    where: {
      id: eventId,
      status: EventStatus.SCHEDULED,
      isLive: false,
      startsAt: { gt: now, lte: windowEnd }
    },
    include: {
      sport: true,
      competition: true,
      markets: {
        where: { status: MarketStatus.OPEN },
        include: {
          selections: {
            where: { status: SelectionStatus.ACTIVE },
            orderBy: { key: "asc" }
          }
        },
        orderBy: { key: "asc" }
      }
    }
  });
}

type EventDetailsResult = Awaited<ReturnType<typeof findEventDetails>>;

function hasEnoughMarketsForDetail(event: NonNullable<EventDetailsResult>) {
  const selectionCount = event.markets.reduce((count, market) => count + market.selections.length, 0);
  return event.markets.length >= 4 && selectionCount >= 8;
}
