import { usePrisma } from "../utils/prisma";

/**
 * Device-Binding pro User. Free=1, Pro=1, Legend=3 (siehe plan-features.maxDevices).
 * deviceId kommt vom Frontend via Capacitor Device.getId() (persistent UUID).
 */

export interface DeviceRecord {
  id: string;
  deviceId: string;
  platform: string;
  model: string | null;
  name: string | null;
  lastSeenAt: Date;
  createdAt: Date;
}

/** Liste aller Devices eines Users, aktuellstes zuerst. */
export async function listUserDevices(userId: string): Promise<DeviceRecord[]> {
  const db = usePrisma();
  return db.userDevice.findMany({
    where: { userId },
    orderBy: { lastSeenAt: "desc" },
    select: {
      id: true,
      deviceId: true,
      platform: true,
      model: true,
      name: true,
      lastSeenAt: true,
      createdAt: true,
    },
  });
}

/** Gibt das Device zurück wenn registriert; sonst null. */
export async function findUserDevice(
  userId: string,
  deviceId: string,
): Promise<DeviceRecord | null> {
  const db = usePrisma();
  return db.userDevice.findUnique({
    where: { userId_deviceId: { userId, deviceId } },
    select: {
      id: true,
      deviceId: true,
      platform: true,
      model: true,
      name: true,
      lastSeenAt: true,
      createdAt: true,
    },
  });
}

/**
 * Idempotente Registrierung. Wenn Device bereits existiert: Touch lastSeenAt.
 * Wenn nicht existiert UND Limit erreicht: throw mit Liste der existierenden Devices.
 */
export async function registerDevice(opts: {
  userId: string;
  deviceId: string;
  platform: string;
  model?: string | null;
  name?: string | null;
  maxDevices: number;
}): Promise<{
  device: DeviceRecord;
  created: boolean;
}> {
  const db = usePrisma();

  // Idempotent: existiert das Device schon?
  const existing = await findUserDevice(opts.userId, opts.deviceId);
  if (existing) {
    // model/name beim Re-Register aktualisieren — User-Agent oder OS-Version
    // kann sich geändert haben (App-Update, OS-Upgrade, iPad-Detection-Fix).
    const updated = await db.userDevice.update({
      where: { id: existing.id },
      data: {
        lastSeenAt: new Date(),
        ...(opts.model !== undefined && { model: opts.model }),
        ...(opts.name !== undefined && { name: opts.name }),
      },
      select: {
        id: true,
        deviceId: true,
        platform: true,
        model: true,
        name: true,
        lastSeenAt: true,
        createdAt: true,
      },
    });
    return { device: updated, created: false };
  }

  // Neues Device — Limit prüfen
  const count = await db.userDevice.count({ where: { userId: opts.userId } });
  if (count >= opts.maxDevices) {
    throw Object.assign(new Error("device_limit_reached"), {
      code: "DEVICE_LIMIT_REACHED",
      currentCount: count,
      max: opts.maxDevices,
    });
  }

  const created = await db.userDevice.create({
    data: {
      userId: opts.userId,
      deviceId: opts.deviceId,
      platform: opts.platform,
      model: opts.model ?? null,
      name: opts.name ?? null,
    },
    select: {
      id: true,
      deviceId: true,
      platform: true,
      model: true,
      name: true,
      lastSeenAt: true,
      createdAt: true,
    },
  });
  return { device: created, created: true };
}

/** Touch lastSeenAt — wird in der Auth-Middleware bei jedem Request aufgerufen. */
export async function touchDevice(userId: string, deviceId: string): Promise<void> {
  const db = usePrisma();
  await db.userDevice
    .updateMany({
      where: { userId, deviceId },
      data: { lastSeenAt: new Date() },
    })
    .catch(() => {
      /* race-safe: wenn Device gerade gelöscht wurde */
    });
}

/** User entfernt ein eigenes Device — gibt Slot frei. */
export async function deleteUserDevice(userId: string, id: string): Promise<void> {
  const db = usePrisma();
  await db.userDevice.deleteMany({ where: { id, userId } });
}
