/**
 * Onboarding analytics REST endpoints.
 *
 * POST   /onboarding/step       — track step completion (any auth)
 * POST   /onboarding/complete   — track onboarding completion (any auth)
 * GET    /onboarding/funnel     — funnel conversion rates (admin)
 * GET    /onboarding/user/:userId — user progress (admin)
 */

import type { FastifyInstance } from 'fastify';
import { randomUUID } from 'node:crypto';
import { getRequestProductId } from '../../lib/request-context.js';
import { BadRequestError, UnauthorizedError } from '../../lib/errors.js';
import * as repo from './repository.js';
import {
  TrackStepSchema,
  TrackCompletionSchema,
  type OnboardingEventDoc,
  type OnboardingCompletionDoc,
} from './types.js';

function requireAdmin(req: { jwtPayload?: { role?: string } }): void {
  if (req.jwtPayload?.role !== 'admin') {
    throw new UnauthorizedError('Admin access required');
  }
}

export async function onboardingRoutes(app: FastifyInstance) {
  // ── Track step completion ──────────────────────────────────
  app.post('/onboarding/step', async (req, reply) => {
    const productId = getRequestProductId(req);
    const parsed = TrackStepSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }

    const now = new Date().toISOString();
    const doc: OnboardingEventDoc = {
      id: `obs_${randomUUID()}`,
      productId,
      userId: parsed.data.userId,
      stepName: parsed.data.stepName,
      stepIndex: parsed.data.stepIndex,
      completedAt: now,
      metadata: parsed.data.metadata,
    };

    const created = await repo.trackStep(doc);
    reply.code(201);
    return created;
  });

  // ── Track onboarding completion ────────────────────────────
  app.post('/onboarding/complete', async (req, reply) => {
    const productId = getRequestProductId(req);
    const parsed = TrackCompletionSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }

    const now = new Date().toISOString();
    const doc: OnboardingCompletionDoc = {
      id: `obc_${randomUUID()}`,
      productId,
      userId: parsed.data.userId,
      completedAt: now,
      totalSteps: parsed.data.totalSteps,
      durationMs: parsed.data.durationMs,
    };

    const created = await repo.trackCompletion(doc);
    reply.code(201);
    return created;
  });

  // ── Admin: funnel query ────────────────────────────────────
  app.get('/onboarding/funnel', async req => {
    requireAdmin(req);
    const productId = getRequestProductId(req);
    const { from, to } = req.query as { from?: string; to?: string };
    return repo.getFunnel(productId, from, to);
  });

  // ── Admin: user progress ───────────────────────────────────
  app.get('/onboarding/user/:userId', async req => {
    requireAdmin(req);
    const productId = getRequestProductId(req);
    const { userId } = req.params as { userId: string };

    const [steps, completion] = await Promise.all([
      repo.getUserSteps(productId, userId),
      repo.getUserCompletion(productId, userId),
    ]);

    return {
      userId,
      productId,
      steps,
      completed: !!completion,
      completion,
    };
  });
}
