import { ForbiddenException } from "@nestjs/common";
import { and, eq } from "drizzle-orm";
import { schema, withUser } from "@slackwsh/data";
import { asEntityId, type EntityIdInput } from "./channels";

export interface PushSubscriptionInput {
  endpoint: string;
  keys: { p256dh: string; auth: string };
  userAgent?: string | null;
}

export async function upsertPushSubscription(actorUserId: EntityIdInput, input: PushSubscriptionInput) {
  const userId = asEntityId(actorUserId);
  const endpoint = input.endpoint.trim();
  if (!endpoint.startsWith("https://")) throw new ForbiddenException("invalid push endpoint");
  const p256dh = input.keys?.p256dh?.trim();
  const auth = input.keys?.auth?.trim();
  if (!p256dh || !auth) throw new ForbiddenException("push subscription keys are required");

  return withUser(userId, async (tx) => {
    const [existing] = await tx
      .select()
      .from(schema.pushSubscriptions)
      .where(eq(schema.pushSubscriptions.endpoint, endpoint))
      .limit(1);
    if (existing && existing.userId !== userId) {
      throw new ForbiddenException("push endpoint is registered to another account");
    }
    if (existing) {
      const [updated] = await tx
        .update(schema.pushSubscriptions)
        .set({
          p256dh,
          auth,
          userAgent: input.userAgent ?? existing.userAgent,
          lastSeenAt: new Date(),
        })
        .where(eq(schema.pushSubscriptions.id, existing.id))
        .returning();
      return updated;
    }
    const [inserted] = await tx
      .insert(schema.pushSubscriptions)
      .values({
        userId,
        endpoint,
        p256dh,
        auth,
        userAgent: input.userAgent ?? null,
      })
      .returning();
    return inserted;
  });
}

export async function deletePushSubscription(actorUserId: EntityIdInput, endpoint: string) {
  const userId = asEntityId(actorUserId);
  return withUser(userId, async (tx) => {
    await tx
      .delete(schema.pushSubscriptions)
      .where(and(eq(schema.pushSubscriptions.userId, userId), eq(schema.pushSubscriptions.endpoint, endpoint.trim())));
    return { deleted: true };
  });
}
