"use server"

import { revalidatePath } from "next/cache"
import { prisma } from "@/lib/prisma"
import { auth } from "@/lib/auth"
import { z } from "zod"

/**
 * Standard action result type
 */
export type ActionResult<T = void> = {
  success: boolean
  data?: T
  message?: string
  errors?: Record<string, string[]>
}

// ============================================================================
// VALIDATION SCHEMAS
// ============================================================================

const dateRangeSchema = z.object({
  startDate: z.date().optional(),
  endDate: z.date().optional(),
})

const hanziIdSchema = z.object({
  hanziId: z.string().min(1),
})

// ============================================================================
// PROGRESS ACTIONS
// ============================================================================

/**
 * Get dashboard statistics
 * Returns counts for due cards, learned cards, and daily progress
 */
export async function getStatistics(): Promise<ActionResult<{
  dueNow: number
  dueToday: number
  dueThisWeek: number
  totalLearned: number
  reviewedToday: number
  dailyGoal: number
  streak: number
}>> {
  try {
    const session = await auth()
    if (!session?.user?.id) {
      return {
        success: false,
        message: "Authentication required",
      }
    }

    const now = new Date()
    const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate())
    const todayEnd = new Date(todayStart)
    todayEnd.setDate(todayEnd.getDate() + 1)

    const weekEnd = new Date(todayStart)
    weekEnd.setDate(weekEnd.getDate() + 7)

    // Get user preferences for daily goal
    const preferences = await prisma.userPreference.findUnique({
      where: { userId: session.user.id },
    })

    const dailyGoal = preferences?.dailyGoal || 50

    // Count cards due now
    const dueNow = await prisma.userHanziProgress.count({
      where: {
        userId: session.user.id,
        nextReviewDate: {
          lte: now,
        },
      },
    })

    // Count cards due today
    const dueToday = await prisma.userHanziProgress.count({
      where: {
        userId: session.user.id,
        nextReviewDate: {
          lte: todayEnd,
        },
      },
    })

    // Count cards due this week
    const dueThisWeek = await prisma.userHanziProgress.count({
      where: {
        userId: session.user.id,
        nextReviewDate: {
          lte: weekEnd,
        },
      },
    })

    // Count total cards with progress
    const totalLearned = await prisma.userHanziProgress.count({
      where: {
        userId: session.user.id,
      },
    })

    // Count cards reviewed today (from session reviews)
    const reviewedToday = await prisma.sessionReview.count({
      where: {
        session: {
          userId: session.user.id,
          startedAt: {
            gte: todayStart,
            lt: todayEnd,
          },
        },
      },
    })

    // Calculate streak (consecutive days with reviews)
    const streak = await calculateStreak(session.user.id)

    return {
      success: true,
      data: {
        dueNow,
        dueToday,
        dueThisWeek,
        totalLearned,
        reviewedToday,
        dailyGoal,
        streak,
      },
    }
  } catch (error) {
    console.error("Get statistics error:", error)
    return {
      success: false,
      message: "Failed to get statistics",
    }
  }
}

/**
 * Calculate learning streak (consecutive days with reviews)
 */
async function calculateStreak(userId: string): Promise<number> {
  try {
    const sessions = await prisma.learningSession.findMany({
      where: {
        userId,
        cardsReviewed: {
          gt: 0,
        },
      },
      orderBy: {
        startedAt: "desc",
      },
      select: {
        startedAt: true,
      },
    })

    if (sessions.length === 0) return 0

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

    for (const session of sessions) {
      const sessionDate = new Date(session.startedAt)
      sessionDate.setHours(0, 0, 0, 0)

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

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

    return streak
  } catch (error) {
    console.error("Calculate streak error:", error)
    return 0
  }
}

/**
 * Get user progress overview with optional date range
 */
export async function getUserProgress(
  startDate?: Date,
  endDate?: Date
): Promise<ActionResult<{
  totalCards: number
  cardsReviewed: number
  correctAnswers: number
  incorrectAnswers: number
  accuracyPercent: number
  averageSessionLength: number
  dailyActivity: Array<{
    date: string
    reviews: number
    correct: number
    incorrect: number
  }>
}>> {
  try {
    const session = await auth()
    if (!session?.user?.id) {
      return {
        success: false,
        message: "Authentication required",
      }
    }

    const validation = dateRangeSchema.safeParse({ startDate, endDate })
    if (!validation.success) {
      return {
        success: false,
        message: "Invalid date range",
        errors: validation.error.flatten().fieldErrors,
      }
    }

    // Default to last 30 days if no range provided
    const end = endDate || new Date()
    const start = startDate || new Date(end.getTime() - 30 * 24 * 60 * 60 * 1000)

    // Get all sessions in date range
    const sessions = await prisma.learningSession.findMany({
      where: {
        userId: session.user.id,
        startedAt: {
          gte: start,
          lte: end,
        },
      },
      include: {
        reviews: true,
      },
    })

    const totalCards = await prisma.userHanziProgress.count({
      where: { userId: session.user.id },
    })

    const cardsReviewed = sessions.reduce((sum, s) => sum + s.cardsReviewed, 0)
    const correctAnswers = sessions.reduce((sum, s) => sum + s.correctAnswers, 0)
    const incorrectAnswers = sessions.reduce((sum, s) => sum + s.incorrectAnswers, 0)

    const accuracyPercent =
      cardsReviewed > 0 ? Math.round((correctAnswers / cardsReviewed) * 100) : 0

    const totalDuration = sessions.reduce((sum, s) => {
      if (!s.endedAt) return sum
      return sum + (s.endedAt.getTime() - s.startedAt.getTime())
    }, 0)

    const averageSessionLength =
      sessions.length > 0
        ? Math.round(totalDuration / sessions.length / 1000 / 60) // minutes
        : 0

    // Daily activity breakdown
    const dailyMap = new Map<string, { reviews: number; correct: number; incorrect: number }>()

    for (const session of sessions) {
      const dateKey = session.startedAt.toISOString().split("T")[0]
      const existing = dailyMap.get(dateKey) || { reviews: 0, correct: 0, incorrect: 0 }

      dailyMap.set(dateKey, {
        reviews: existing.reviews + session.cardsReviewed,
        correct: existing.correct + session.correctAnswers,
        incorrect: existing.incorrect + session.incorrectAnswers,
      })
    }

    const dailyActivity = Array.from(dailyMap.entries())
      .map(([date, stats]) => ({ date, ...stats }))
      .sort((a, b) => a.date.localeCompare(b.date))

    return {
      success: true,
      data: {
        totalCards,
        cardsReviewed,
        correctAnswers,
        incorrectAnswers,
        accuracyPercent,
        averageSessionLength,
        dailyActivity,
      },
    }
  } catch (error) {
    console.error("Get user progress error:", error)
    return {
      success: false,
      message: "Failed to get user progress",
    }
  }
}

/**
 * Get recent learning sessions
 */
export async function getLearningSessions(
  limit: number = 10
): Promise<ActionResult<Array<{
  id: string
  startedAt: Date
  endedAt: Date | null
  cardsReviewed: number
  correctAnswers: number
  incorrectAnswers: number
  accuracyPercent: number
  collectionName: string | null
}>>> {
  try {
    const session = await auth()
    if (!session?.user?.id) {
      return {
        success: false,
        message: "Authentication required",
      }
    }

    const sessions = await prisma.learningSession.findMany({
      where: {
        userId: session.user.id,
      },
      include: {
        collection: {
          select: {
            name: true,
          },
        },
      },
      orderBy: {
        startedAt: "desc",
      },
      take: limit,
    })

    const formattedSessions = sessions.map(s => ({
      id: s.id,
      startedAt: s.startedAt,
      endedAt: s.endedAt,
      cardsReviewed: s.cardsReviewed,
      correctAnswers: s.correctAnswers,
      incorrectAnswers: s.incorrectAnswers,
      accuracyPercent:
        s.cardsReviewed > 0 ? Math.round((s.correctAnswers / s.cardsReviewed) * 100) : 0,
      collectionName: s.collection?.name || "All Cards",
    }))

    return {
      success: true,
      data: formattedSessions,
    }
  } catch (error) {
    console.error("Get learning sessions error:", error)
    return {
      success: false,
      message: "Failed to get learning sessions",
    }
  }
}

/**
 * Get progress for individual hanzi
 */
export async function getHanziProgress(
  hanziId: string
): Promise<ActionResult<{
  hanzi: {
    id: string
    simplified: string
    pinyin: string
    meaning: string
  }
  progress: {
    correctCount: number
    incorrectCount: number
    consecutiveCorrect: number
    easeFactor: number
    interval: number
    nextReviewDate: Date
    manualDifficulty: string | null
  }
  recentReviews: Array<{
    date: Date
    isCorrect: boolean
    responseTime: number | null
  }>
}>> {
  try {
    const session = await auth()
    if (!session?.user?.id) {
      return {
        success: false,
        message: "Authentication required",
      }
    }

    const validation = hanziIdSchema.safeParse({ hanziId })
    if (!validation.success) {
      return {
        success: false,
        message: "Invalid hanzi ID",
        errors: validation.error.flatten().fieldErrors,
      }
    }

    // Get hanzi with progress
    const progress = await prisma.userHanziProgress.findUnique({
      where: {
        userId_hanziId: {
          userId: session.user.id,
          hanziId,
        },
      },
      include: {
        hanzi: {
          include: {
            forms: {
              where: { isDefault: true },
              include: {
                transcriptions: {
                  where: { type: "pinyin" },
                },
                meanings: true,
              },
            },
          },
        },
      },
    })

    if (!progress) {
      return {
        success: false,
        message: "No progress found for this hanzi",
      }
    }

    const defaultForm = progress.hanzi.forms[0]
    const pinyin = defaultForm?.transcriptions[0]?.value || ""
    const meaning = defaultForm?.meanings[0]?.meaning || ""

    // Get recent reviews for this hanzi
    const recentReviews = await prisma.sessionReview.findMany({
      where: {
        hanziId,
        session: {
          userId: session.user.id,
        },
      },
      orderBy: {
        createdAt: "desc",
      },
      take: 20,
      select: {
        createdAt: true,
        isCorrect: true,
        responseTime: true,
      },
    })

    return {
      success: true,
      data: {
        hanzi: {
          id: progress.hanzi.id,
          simplified: progress.hanzi.simplified,
          pinyin,
          meaning,
        },
        progress: {
          correctCount: progress.correctCount,
          incorrectCount: progress.incorrectCount,
          consecutiveCorrect: progress.consecutiveCorrect,
          easeFactor: progress.easeFactor,
          interval: progress.interval,
          nextReviewDate: progress.nextReviewDate,
          manualDifficulty: progress.manualDifficulty,
        },
        recentReviews: recentReviews.map(r => ({
          date: r.createdAt,
          isCorrect: r.isCorrect,
          responseTime: r.responseTime,
        })),
      },
    }
  } catch (error) {
    console.error("Get hanzi progress error:", error)
    return {
      success: false,
      message: "Failed to get hanzi progress",
    }
  }
}

/**
 * Reset progress for a specific hanzi
 */
export async function resetHanziProgress(
  hanziId: string
): Promise<ActionResult<void>> {
  try {
    const session = await auth()
    if (!session?.user?.id) {
      return {
        success: false,
        message: "Authentication required",
      }
    }

    const validation = hanziIdSchema.safeParse({ hanziId })
    if (!validation.success) {
      return {
        success: false,
        message: "Invalid hanzi ID",
        errors: validation.error.flatten().fieldErrors,
      }
    }

    // Delete the progress record
    await prisma.userHanziProgress.delete({
      where: {
        userId_hanziId: {
          userId: session.user.id,
          hanziId,
        },
      },
    })

    revalidatePath("/progress")
    revalidatePath("/dashboard")

    return {
      success: true,
      message: "Hanzi progress reset successfully",
    }
  } catch (error) {
    console.error("Reset hanzi progress error:", error)
    return {
      success: false,
      message: "Failed to reset hanzi progress",
    }
  }
}
