/**
 * Invitations repository — cloud-agnostic via @bytelyst/datastore.
 * Consolidated from admin-dashboard-web + user-dashboard-web repos.
 */

import { getCollection } from '../../lib/datastore.js';
import type { InvitationCodeDoc } from './types.js';

function collection() {
  return getCollection<InvitationCodeDoc>('invitation_codes', '/id');
}

export async function list(
  limit = 100,
  offset = 0,
  productId?: string
): Promise<InvitationCodeDoc[]> {
  const results = await collection().findMany({
    filter: { productId: productId ?? '' },
    sort: { createdAt: -1 },
    limit: limit + offset,
  });
  return results.slice(offset);
}

export async function getById(id: string): Promise<InvitationCodeDoc | null> {
  try {
    return await collection().findById(id, id);
  } catch {
    return null;
  }
}

export async function getByCode(
  code: string,
  productId?: string
): Promise<InvitationCodeDoc | null> {
  return collection().findOne({
    filter: { productId: productId ?? '', code: code.toUpperCase() },
  });
}

export async function create(doc: InvitationCodeDoc): Promise<InvitationCodeDoc> {
  return collection().create(doc);
}

export async function update(
  id: string,
  updates: Partial<InvitationCodeDoc>
): Promise<InvitationCodeDoc | null> {
  try {
    return await collection().update(id, id, { ...updates, updatedAt: new Date().toISOString() });
  } catch {
    return null;
  }
}

export async function redeem(code: string, userId: string): Promise<InvitationCodeDoc | null> {
  const doc = await getByCode(code);
  if (!doc) return null;
  if (doc.status !== 'active') return null;
  if (doc.currentUses >= doc.maxUses) return null;
  if (doc.expiresAt && new Date(doc.expiresAt) < new Date()) return null;
  if (doc.redeemedBy.includes(userId)) return null;

  return update(doc.id, {
    currentUses: doc.currentUses + 1,
    redeemedBy: [...doc.redeemedBy, userId],
    ...(doc.currentUses + 1 >= doc.maxUses && { status: 'expired' as const }),
  });
}

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

export async function count(productId?: string): Promise<number> {
  return collection().count({ productId: productId ?? '' });
}
