/**
 * QR auth endpoints for SmartAuth Phase 5E.
 *
 * POST /auth/qr/create   — create a QR challenge (desktop/TV client)
 * POST /auth/qr/confirm  — confirm QR login from auth app (mobile, authenticated)
 * GET  /auth/qr/:id/status — poll QR challenge status (desktop/TV client)
 */

import type { FastifyInstance } from 'fastify';
import { BadRequestError, UnauthorizedError, NotFoundError } from '../../../lib/errors.js';
import * as repo from './repository.js';
import * as jwt from '../jwt.js';
import * as userRepo from '../repository.js';
import { QrChallengeCreateSchema, QrConfirmSchema } from './types.js';

export async function qrAuthRoutes(app: FastifyInstance) {
  // ── Create QR challenge (unauthenticated — desktop shows QR) ──

  app.post('/auth/qr/create', async req => {
    const parsed = QrChallengeCreateSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }

    const challenge = repo.create(parsed.data.productId, parsed.data.platform);

    req.log.info({ challengeId: challenge.id }, '[auth] QR challenge created');
    return {
      id: challenge.id,
      challengeToken: challenge.challengeToken,
      expiresAt: challenge.expiresAt,
    };
  });

  // ── Confirm QR login (auth app — authenticated user scans QR) ──

  app.post('/auth/qr/confirm', async req => {
    const payload = req.jwtPayload;
    if (!payload?.sub) throw new UnauthorizedError('Authentication required');

    const parsed = QrConfirmSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }

    const challenge = repo.confirm(parsed.data.challengeToken, payload.sub);
    if (!challenge) {
      throw new BadRequestError('Invalid, expired, or already confirmed QR challenge');
    }

    req.log.info({ challengeId: challenge.id, userId: payload.sub }, '[auth] QR login confirmed');
    return { message: 'Login authorized', challengeId: challenge.id };
  });

  // ── Poll QR challenge status (desktop polls until confirmed) ──

  app.get('/auth/qr/:id/status', async req => {
    const { id } = req.params as { id: string };
    const challenge = repo.getById(id);
    if (!challenge) throw new NotFoundError('QR challenge not found');

    if (challenge.status === 'confirmed' && challenge.userId) {
      // Issue tokens for the confirmed user
      const user = await userRepo.getById(challenge.userId);
      if (!user) throw new NotFoundError('User not found');

      const accessToken = await jwt.createAccessToken({
        sub: user.id,
        email: user.email,
        role: user.role as 'user' | 'admin' | 'super_admin',
        productId: challenge.productId,
        plan: (user.plan ?? 'free') as 'free' | 'pro' | 'enterprise',
        displayName: user.displayName,
      });
      const refreshToken = await jwt.createRefreshToken({
        sub: user.id,
        productId: challenge.productId,
      });

      return {
        status: 'confirmed',
        accessToken,
        refreshToken,
        user: {
          id: user.id,
          email: user.email,
          displayName: user.displayName,
          plan: user.plan,
          role: user.role,
        },
      };
    }

    return {
      status: challenge.status,
      accessToken: null,
      refreshToken: null,
      user: null,
    };
  });
}
