import { query } from '../../../utils/db' export default defineEventHandler(async (event) => { const queryParams = getQuery(event) const { year, month, week } = queryParams as { year?: string, month?: string, week?: string } if (!year || !month || !week) { return { error: 'year, month, week are required' } } const y = parseInt(year) const m = parseInt(month) const w = parseInt(week) const firstDayOfMonth = new Date(y, m - 1, 1) const firstDayWeekday = firstDayOfMonth.getDay() const mondayOffset = firstDayWeekday === 0 ? -6 : 1 - firstDayWeekday const firstMondayOfMonth = new Date(y, m - 1, 1 + mondayOffset) const weekStart = new Date(firstMondayOfMonth) weekStart.setDate(weekStart.getDate() + (w - 1) * 7) const weekEnd = new Date(weekStart) weekEnd.setDate(weekEnd.getDate() + 6) const weekDates: string[] = [] for (let i = 0; i < 7; i++) { const d = new Date(weekStart) d.setDate(d.getDate() + i) const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}` weekDates.push(dateStr) } const startDate = weekDates[0] const endDate = weekDates[6] const heatmapData = await query(` SELECT TO_CHAR(checked_at::timestamp, 'YYYY-MM-DD') as date, TO_CHAR(checked_at::timestamp, 'HH24:00') as time_slot, COUNT(*) as total_count, SUM(CASE WHEN is_success = 1 THEN 1 ELSE 0 END) as success_count, ROUND(SUM(CASE WHEN is_success = 1 THEN 1.0 ELSE 0.0 END) / COUNT(*) * 100, 1) as success_rate FROM privnet_logs WHERE checked_at::date >= $1 AND checked_at::date <= $2 GROUP BY date, time_slot ORDER BY date, time_slot `, [startDate, endDate]) const lastDayOfMonth = new Date(y, m, 0) const lastDayFromFirstMonday = Math.floor((lastDayOfMonth.getTime() - firstMondayOfMonth.getTime()) / (1000 * 60 * 60 * 24)) const totalWeeks = Math.ceil((lastDayFromFirstMonday + 1) / 7) return { heatmapData, weekDates, totalWeeks: Math.max(totalWeeks, 1), year: y, month: m, week: w } })