/**
 * API token repository — cloud-agnostic datastore operations.
 */

import { getCollection } from '@/lib/datastore';
import { PRODUCT_ID } from '@/lib/product-config';
import type { BaseDocument, DocumentCollection } from '@bytelyst/datastore';

export interface ApiTokenDoc extends BaseDocument {
  userId: string;
  userName: string;
  name: string;
  prefix: string;
  tokenHash: string;
  status: 'active' | 'revoked' | 'expired';
  scopes: string[];
  createdAt: string;
  expiresAt: string;
  lastUsed: string | null;
  ttl?: number;
}

export type ApiTokenResponse = Omit<ApiTokenDoc, 'tokenHash'>;

function collection(): DocumentCollection<ApiTokenDoc> {
  return getCollection<ApiTokenDoc>('api_tokens', '/userId');
}

function stripHash(doc: ApiTokenDoc): ApiTokenResponse {
  const { tokenHash: _hash, ...rest } = doc;
  void _hash;
  return rest;
}

export async function getTokenById(id: string, userId: string): Promise<ApiTokenDoc | null> {
  return collection().findById(id, userId);
}

export async function listTokens(limit = 100, productId = PRODUCT_ID): Promise<ApiTokenResponse[]> {
  const resources = await collection().findMany({
    filter: { productId, status: { $ne: 'expired' } },
    sort: { createdAt: -1 },
    limit,
  });
  return resources.map(stripHash);
}

export async function listTokensByUser(
  userId: string,
  productId = PRODUCT_ID
): Promise<ApiTokenResponse[]> {
  const resources = await collection().findMany({
    filter: { productId, userId },
    sort: { createdAt: -1 },
  });
  return resources.map(stripHash);
}

export async function createToken(doc: ApiTokenDoc): Promise<ApiTokenResponse> {
  const resource = await collection().create(doc);
  return stripHash(resource);
}

export async function revokeToken(id: string, userId: string): Promise<boolean> {
  const existing = await getTokenById(id, userId);
  if (!existing) return false;

  await collection().update(id, userId, { status: 'revoked' } as Partial<ApiTokenDoc>);
  return true;
}

export async function deleteToken(id: string, userId: string): Promise<boolean> {
  try {
    await collection().delete(id, userId);
    return true;
  } catch {
    return false;
  }
}

export async function countActiveTokens(productId = PRODUCT_ID): Promise<number> {
  return collection().count({ productId, status: 'active' });
}
