/**
 * Session queries - typed async functions for the sessions table.
 */

import { eq, lt } from 'drizzle-orm';
import type { DrizzleClient } from '../client.js';
import { sessions } from '../schema.js';

/**
 * Insert a new session row.
 *
 * @param input.ipEncrypted - Must be a SHA-256 hash (16 hex chars) produced by
 *   `hashIp()` from `src/server/auth/ip-hash.ts`. Never pass a plaintext IP.
 */
export async function create(
  db: DrizzleClient,
  input: {
    id: string;
    userId: string;
    csrfToken: string;
    userAgent?: string;
    ipEncrypted?: string;
    expiresAt: Date;
    refreshTokenHash: string;
  },
) {
  const [row] = await db
    .insert(sessions)
    .values({
      id: input.id,
      userId: input.userId,
      csrfToken: input.csrfToken,
      userAgent: input.userAgent ?? '',
      ipEncrypted: input.ipEncrypted,
      expiresAt: input.expiresAt,
      refreshTokenHash: input.refreshTokenHash,
    })
    .returning();
  return row!;
}

export async function findById(db: DrizzleClient, id: string) {
  const [row] = await db.select().from(sessions).where(eq(sessions.id, id)).limit(1);
  if (!row) return null;
  if (row.revokedAt) return null;
  if (row.expiresAt < new Date()) return null;
  return row;
}

export async function revoke(db: DrizzleClient, id: string) {
  const [row] = await db
    .update(sessions)
    .set({ revokedAt: new Date() })
    .where(eq(sessions.id, id))
    .returning();
  return row ?? null;
}

export async function revokeByRefreshTokenHash(db: DrizzleClient, refreshTokenHash: string) {
  const [row] = await db
    .update(sessions)
    .set({ revokedAt: new Date() })
    .where(eq(sessions.refreshTokenHash, refreshTokenHash))
    .returning();
  return row ?? null;
}

export async function purgeExpired(db: DrizzleClient) {
  const result = await db.delete(sessions).where(lt(sessions.expiresAt, new Date()));
  return result;
}
