/**
 * GET /api/analytics/retention — Cohort retention analysis.
 *
 * Groups users by signup week, then checks how many were active at
 * 7, 14, and 30 days after signup. Returns a table suitable for a
 * retention heatmap.
 */

import { NextRequest, NextResponse } from 'next/server';
import { logError } from '@/lib/logger';
import { getCurrentUserFromRequest } from '@/lib/auth-server';
import { getCollection } from '@/lib/datastore';
import { getRequestProductId } from '@/lib/product-config';
interface CohortRow {
  cohortWeek: string; // e.g. "2026-W05"
  cohortStart: string; // ISO date of Monday
  signups: number;
  retained7d: number;
  retained14d: number;
  retained30d: number;
  rate7d: number; // 0-100
  rate14d: number;
  rate30d: number;
}
function getWeekLabel(date: Date): string {
  const d = new Date(date);
  d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
  const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
  const weekNo = Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7);
  return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, '0')}`;
}
function getMondayOfWeek(date: Date): string {
  const d = new Date(date);
  const day = d.getUTCDay() || 7;
  d.setUTCDate(d.getUTCDate() - day + 1);
  return d.toISOString().slice(0, 10);
}
export async function GET(req: NextRequest) {
  try {
    const caller = await getCurrentUserFromRequest(req);
    if (!caller) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }
    const url = new URL(req.url);
    const weeks = parseInt(url.searchParams.get('weeks') ?? '8', 10);
    const productId = getRequestProductId(req);
    // Get users created in the last N weeks
    const sinceDate = new Date(Date.now() - weeks * 7 * 86400000).toISOString().slice(0, 10);
    const usersCollection = getCollection('users', '/id');
    const users = await usersCollection.rawQuery<{ id: string; createdAt: string }>(
      'SELECT c.id, c.createdAt FROM c ' +
        'WHERE c.productId = @pid AND c.createdAt >= @since ' +
        'ORDER BY c.createdAt ASC',
      { pid: productId, since: sinceDate }
    );
    if (users.length === 0) {
      return NextResponse.json({ cohorts: [], totalUsers: 0 });
    }
    // Group users by signup week
    const cohortMap = new Map<string, { start: string; userIds: string[] }>();
    for (const u of users) {
      const d = new Date(u.createdAt);
      const week = getWeekLabel(d);
      const monday = getMondayOfWeek(d);
      if (!cohortMap.has(week)) {
        cohortMap.set(week, { start: monday, userIds: [] });
      }
      cohortMap.get(week)!.userIds.push(u.id);
    }
    // Get all usage records for these users
    const usageCollection = getCollection('usage_daily', '/userId');
    const usageRecords = await usageCollection.rawQuery<{ userId: string; date: string }>(
      'SELECT c.userId, c.date FROM c WHERE c.productId = @pid AND c.date >= @since',
      { pid: productId, since: sinceDate }
    );
    // Build a set of (userId, date) for quick lookup
    const userActiveDates = new Map<string, Set<string>>();
    for (const r of usageRecords) {
      if (!userActiveDates.has(r.userId)) {
        userActiveDates.set(r.userId, new Set());
      }
      userActiveDates.get(r.userId)!.add(r.date);
    }
    // Calculate retention for each cohort
    const cohorts: CohortRow[] = [];
    const now = Date.now();
    for (const [week, { start, userIds }] of cohortMap) {
      const cohortStart = new Date(start).getTime();
      const signups = userIds.length;
      let retained7d = 0;
      let retained14d = 0;
      let retained30d = 0;
      for (const uid of userIds) {
        const dates = userActiveDates.get(uid);
        if (!dates) continue;
        // Check if user was active in the window [start+Nd, start+Nd+7d)
        const hasActivityInRange = (offsetDays: number) => {
          const rangeStart = cohortStart + offsetDays * 86400000;
          const rangeEnd = rangeStart + 7 * 86400000;
          if (rangeStart > now) return false; // Window hasn't arrived yet
          for (const d of dates) {
            const ts = new Date(d).getTime();
            if (ts >= rangeStart && ts < rangeEnd) return true;
          }
          return false;
        };
        if (hasActivityInRange(7)) retained7d++;
        if (hasActivityInRange(14)) retained14d++;
        if (hasActivityInRange(30)) retained30d++;
      }
      const day7elapsed = now - cohortStart >= 14 * 86400000;
      const day14elapsed = now - cohortStart >= 21 * 86400000;
      const day30elapsed = now - cohortStart >= 37 * 86400000;
      cohorts.push({
        cohortWeek: week,
        cohortStart: start,
        signups,
        retained7d,
        retained14d,
        retained30d,
        rate7d: day7elapsed ? Math.round((retained7d / signups) * 100) : -1,
        rate14d: day14elapsed ? Math.round((retained14d / signups) * 100) : -1,
        rate30d: day30elapsed ? Math.round((retained30d / signups) * 100) : -1,
      });
    }
    return NextResponse.json({
      cohorts,
      totalUsers: users.length,
      weeksAnalyzed: weeks,
    });
  } catch (error) {
    logError('Retention analysis error', error);
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
  }
}
