import { prisma } from "../prisma";
import { DashboardStats } from "@/types";

/**
 * Get number of workouts this week (Mon-Sun)
 */
export async function getWeeklyWorkoutCount(userId: string): Promise<number> {
  const now = new Date();
  const dayOfWeek = now.getDay();
  const daysBack = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // Monday is 0

  const mondayStart = new Date(now);
  mondayStart.setDate(mondayStart.getDate() - daysBack);
  mondayStart.setHours(0, 0, 0, 0);

  const sundayEnd = new Date(mondayStart);
  sundayEnd.setDate(sundayEnd.getDate() + 6);
  sundayEnd.setHours(23, 59, 59, 999);

  const count = await prisma.workout.count({
    where: {
      userId,
      deletedAt: null,
      date: {
        gte: mondayStart,
        lte: sundayEnd,
      },
    },
  });

  return count;
}

/**
 * Get total workouts ever for user
 */
export async function getTotalWorkoutCount(userId: string): Promise<number> {
  return prisma.workout.count({
    where: { userId, deletedAt: null },
  });
}

/**
 * Get number of workouts this month (1st to end of month)
 */
export async function getMonthlyWorkoutCount(userId: string): Promise<number> {
  const now = new Date();
  const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
  monthStart.setHours(0, 0, 0, 0);

  const monthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0);
  monthEnd.setHours(23, 59, 59, 999);

  return prisma.workout.count({
    where: {
      userId,
      deletedAt: null,
      date: {
        gte: monthStart,
        lte: monthEnd,
      },
    },
  });
}

/**
 * Get number of workouts this year (Jan 1 to Dec 31)
 */
export async function getYearlyWorkoutCount(userId: string): Promise<number> {
  const now = new Date();
  const yearStart = new Date(now.getFullYear(), 0, 1);
  yearStart.setHours(0, 0, 0, 0);

  const yearEnd = new Date(now.getFullYear(), 11, 31);
  yearEnd.setHours(23, 59, 59, 999);

  return prisma.workout.count({
    where: {
      userId,
      deletedAt: null,
      date: {
        gte: yearStart,
        lte: yearEnd,
      },
    },
  });
}

/**
 * Get current streak (consecutive days with workouts, working backwards from today)
 */
export async function getCurrentStreak(userId: string): Promise<number> {
  const workouts = await prisma.workout.findMany({
    where: { userId, deletedAt: null },
    select: { date: true },
    orderBy: { date: "desc" },
  });

  if (workouts.length === 0) {
    return 0;
  }

  let streak = 0;
  let currentDate = new Date();
  currentDate.setHours(0, 0, 0, 0);

  for (const workout of workouts) {
    const workoutDate = new Date(workout.date);
    workoutDate.setHours(0, 0, 0, 0);

    const daysDiff = Math.floor(
      (currentDate.getTime() - workoutDate.getTime()) / (1000 * 60 * 60 * 24)
    );

    if (daysDiff === streak) {
      streak++;
    } else {
      break;
    }
  }

  return streak;
}

/**
 * Get total volume (sum of reps * weight) for this week
 */
export async function getWeeklyVolume(userId: string): Promise<number> {
  const now = new Date();
  const dayOfWeek = now.getDay();
  const daysBack = dayOfWeek === 0 ? 6 : dayOfWeek - 1;

  const mondayStart = new Date(now);
  mondayStart.setDate(mondayStart.getDate() - daysBack);
  mondayStart.setHours(0, 0, 0, 0);

  const sundayEnd = new Date(mondayStart);
  sundayEnd.setDate(sundayEnd.getDate() + 6);
  sundayEnd.setHours(23, 59, 59, 999);

  const setLogs = await prisma.setLog.findMany({
    where: {
      workout: {
        userId,
        deletedAt: null,
        date: {
          gte: mondayStart,
          lte: sundayEnd,
        },
      },
    },
    select: {
      reps: true,
      weight: true,
    },
  });

  const totalVolume = setLogs.reduce((sum, set) => {
    const reps = set.reps || 0;
    const weight = set.weight || 0;
    return sum + reps * weight;
  }, 0);

  return totalVolume;
}

/**
 * Get all dashboard stats combined
 */
export async function getDashboardStats(userId: string): Promise<DashboardStats> {
  const [
    totalWorkouts,
    _weeklyWorkoutCount,
    _currentStreak,
    weeklyVolume,
    recentWorkouts,
  ] = await Promise.all([
    getTotalWorkoutCount(userId),
    getWeeklyWorkoutCount(userId),
    getCurrentStreak(userId),
    getWeeklyVolume(userId),
    prisma.workout.findMany({
      where: { userId, deletedAt: null },
      include: {
        setLogs: {
          include: {
            exercise: true,
          },
          orderBy: {
            setNumber: "asc",
          },
        },
      },
      orderBy: {
        date: "desc",
      },
      take: 5,
    }),
  ]);

  // Calculate total sets and reps from recent workouts
  let totalSets = 0;
  let totalReps = 0;
  const personalBests: DashboardStats["personalBests"] = [];

  for (const workout of recentWorkouts) {
    for (const set of (workout as any).setLogs) {
      totalSets++;
      if (set.reps) {
        totalReps += set.reps;
      }
    }
  }

  return {
    totalWorkouts,
    totalVolume: weeklyVolume,
    totalSets,
    totalReps,
    personalBests,
    recentWorkouts: recentWorkouts as any,
  };
}
