/**
 * Device trust REST endpoints for SmartAuth.
 *
 * POST   /auth/devices/trust        — trust a device (Bearer)
 * GET    /auth/devices               — list devices (Bearer)
 * POST   /auth/devices/check         — check if device is trusted (Bearer)
 * DELETE /auth/devices/:fingerprint  — revoke trust for a device (Bearer)
 * POST   /auth/devices/revoke-all    — revoke all device trust (Bearer)
 */

import type { FastifyInstance } from 'fastify';
import { BadRequestError, UnauthorizedError } from '../../../lib/errors.js';
import * as deviceRepo from './repository.js';
import { TrustDeviceSchema, DeviceFingerprintSchema, TRUST_DURATIONS_DAYS } from './types.js';
import type { DeviceDoc } from './types.js';

export async function deviceRoutes(app: FastifyInstance) {
  // ── Trust a Device ──────────────────────────────────────────

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

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

    const { fingerprint, trustLevel, deviceInfo } = parsed.data;
    const durationDays = TRUST_DURATIONS_DAYS[trustLevel];
    const expiresAt = new Date();
    expiresAt.setDate(expiresAt.getDate() + durationDays);

    const now = new Date().toISOString();
    const doc: DeviceDoc = {
      id: `dev_${fingerprint}`,
      userId: payload.sub,
      productId: 'smartauth',
      fingerprint,
      trustLevel,
      deviceInfo: (deviceInfo ?? {}) as DeviceDoc['deviceInfo'],
      lastIp: req.ip,
      trustExpiresAt: expiresAt.toISOString(),
      createdAt: now,
      lastSeenAt: now,
    };

    const result = await deviceRepo.upsert(doc);
    req.log.info({ userId: payload.sub, fingerprint, trustLevel }, '[auth] Device trusted');
    return {
      fingerprint: result.fingerprint,
      trustLevel: result.trustLevel,
      trustExpiresAt: result.trustExpiresAt,
    };
  });

  // ── List Devices ──────────────────────────────────────────

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

    const devices = await deviceRepo.listByUser(payload.sub);
    return {
      devices: devices.map(d => ({
        fingerprint: d.fingerprint,
        trustLevel: d.trustLevel,
        deviceInfo: d.deviceInfo,
        lastIp: d.lastIp,
        lastLocation: d.lastLocation,
        trustExpiresAt: d.trustExpiresAt,
        createdAt: d.createdAt,
        lastSeenAt: d.lastSeenAt,
        isTrusted: deviceRepo.isDeviceTrusted(d),
      })),
    };
  });

  // ── Check Device Trust ────────────────────────────────────

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

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

    const device = await deviceRepo.getByFingerprint(payload.sub, parsed.data.fingerprint);
    const trusted = deviceRepo.isDeviceTrusted(device);

    if (device) {
      await deviceRepo.updateLastSeen(payload.sub, parsed.data.fingerprint, req.ip);
    }

    return {
      trusted,
      trustLevel: device?.trustLevel ?? 'unknown',
      trustExpiresAt: device?.trustExpiresAt ?? null,
    };
  });

  // ── Revoke Device Trust ───────────────────────────────────

  app.delete('/auth/devices/:fingerprint', async req => {
    const payload = req.jwtPayload;
    if (!payload?.sub) throw new UnauthorizedError('Authentication required');
    const { fingerprint } = req.params as { fingerprint: string };

    const revoked = await deviceRepo.revokeTrust(payload.sub, fingerprint);
    if (!revoked) throw new BadRequestError('Device not found');

    req.log.info({ userId: payload.sub, fingerprint }, '[auth] Device trust revoked');
    return { message: 'Device trust revoked' };
  });

  // ── Revoke All Device Trust ───────────────────────────────

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

    const count = await deviceRepo.revokeAllTrust(payload.sub);
    req.log.info({ userId: payload.sub, count }, '[auth] All device trust revoked');
    return { message: `Revoked trust for ${count} device(s)`, count };
  });
}
