import { eq, desc } from 'drizzle-orm';
import { db, subscriptions } from '@server/db/drizzle';
import { initDatabase } from '@server/db/init';
import { verifySession, type SessionPayload } from '@server/auth';

export type GateValue = 'ok' | 'expired' | 'inactive' | 'unauthenticated';

const EXEMPT_ROLES = new Set(['superadmin', 'support']);

/**
 * Evaluate the trial/subscription gate for an already-verified session.
 * Returns 'ok' for exempt roles, sessions without a restaurantId, or active
 * subscriptions; 'expired' when a trial has ended; 'inactive' when the
 * subscription is missing/cancelled; 'unauthenticated' when the session is
 * null. Throws on DB errors so callers can decide their own fail-open
 * semantics.
 */
export async function evaluateGateForSession(session: SessionPayload | null): Promise<GateValue> {
  if (!session) return 'unauthenticated';
  if (EXEMPT_ROLES.has(session.role)) return 'ok';
  if (!session.restaurantId) return 'ok';

  await initDatabase();

  const rows = await db
    .select({ status: subscriptions.status, trialEnd: subscriptions.trialEnd })
    .from(subscriptions)
    .where(eq(subscriptions.restaurantId, session.restaurantId))
    .orderBy(desc(subscriptions.createdAt))
    .limit(1);

  const sub = rows[0];
  if (!sub) return 'inactive';

  const isTrialExpired =
    sub.status === 'trial' && (!sub.trialEnd || new Date(sub.trialEnd) < new Date());
  if (isTrialExpired) return 'expired';

  if (sub.status === 'inactive' || sub.status === 'cancelled') return 'inactive';
  return 'ok';
}

/**
 * Convenience wrapper: verifies a session token and evaluates the gate.
 * Used by both the /api/auth/gate HTTP route and middleware.
 */
export async function evaluateGateForToken(token: string | undefined | null): Promise<GateValue> {
  if (!token) return 'unauthenticated';
  const session = await verifySession(token);
  return evaluateGateForSession(session);
}
