import { randomUUIDv7 } from 'bun';

import { getDb, pgGet } from '@/shared/db';
import {
  createDevice,
  getDevice,
  listDevices,
  revokeDevice,
  touchDevice,
  upsertDeviceByHardwareId,
} from '@/entities/device';
import type { Device, DeviceDraft } from '@/entities/device';

/**
 * Idempotent device registration keyed on hardwareId (IOPlatformUUID).
 * Re-registration from the same device returns the existing row + original token.
 * A new token is only minted on first registration.
 */
export async function registerDevice(
  name: string,
  platform: string,
  hardwareId: string,
): Promise<{ device: Device; token: string; created: boolean }> {
  const pool = getDb();
  const id = randomUUIDv7();
  const token = randomUUIDv7() + '-' + randomUUIDv7();
  const draft: DeviceDraft = { id, name, hardwareId, token, platform };
  const { device, created } = await upsertDeviceByHardwareId(pool, draft);
  // If an existing device was returned, surface its stored token.
  return { device, token: device.token, created };
}

export async function verifyAndTouchDevice(token: string): Promise<Device> {
  const pool = getDb();
  const row = await pgGet<{ id: string }>(
    pool,
    'SELECT id FROM macsync.devices WHERE token = $1 AND revoked_at IS NULL',
    [token],
  );
  if (!row) throw new Error('invalid token');
  await touchDevice(pool, row.id);
  return getDevice(pool, row.id);
}

export async function listAllDevices(): Promise<readonly Device[]> {
  return listDevices(getDb());
}

export async function revokeDeviceById(id: string): Promise<void> {
  return revokeDevice(getDb(), id);
}
