import { prisma } from '../config/database.js';
import type { Role, TenantMembership } from '@horux/shared';

/**
 * Lista los tenants a los que el user tiene acceso vía la tabla
 * `tenant_memberships`. Usado por /auth/login, /auth/me, /auth/switch-tenant
 * para poblar el array `tenants[]` del UserInfo.
 *
 * Durante la transición (fase 2), si el user todavía no tiene memberships
 * (caso borde post-deploy antes del backfill), devuelve un array con su
 * tenant "default" (User.tenantId) para no romper UX.
 */
export async function getUserTenants(userId: string): Promise<TenantMembership[]> {
  const memberships = await prisma.tenantMembership.findMany({
    where: { userId, active: true },
    include: {
      tenant: { select: { id: true, nombre: true, rfc: true, plan: true, active: true } },
      rol: { select: { nombre: true } },
    },
    orderBy: { joinedAt: 'asc' },
  });

  return memberships
    .filter(m => m.tenant.active) // Esconde memberships de tenants desactivados
    .map(m => ({
      id: m.tenant.id,
      nombre: m.tenant.nombre,
      rfc: m.tenant.rfc,
      plan: m.tenant.plan,
      role: m.rol.nombre as Role,
      isOwner: m.isOwner,
    }));
}

/**
 * Verifica que el user tiene membership activo en el tenant dado. Usado por
 * /auth/switch-tenant antes de emitir un JWT con ese tenantId.
 */
/**
 * ¿El user es owner en al menos un tenant activo? Usado como gate en
 * POST /tenants/mine (agregar RFC nuevo) — solo users que ya son owner en
 * alguna empresa pueden registrar otra más.
 */
export async function isOwnerSomewhere(userId: string): Promise<boolean> {
  const row = await prisma.tenantMembership.findFirst({
    where: { userId, isOwner: true, active: true, tenant: { active: true } },
    select: { id: true },
  });
  return !!row;
}

/**
 * Devuelve el email del owner del tenant (primero por joinedAt). Usado por
 * subscription.service para enviar notificaciones de pago/cancelación al
 * dueño. Si el tenant no tiene owner activo, retorna null.
 */
export async function getTenantOwnerEmail(tenantId: string): Promise<string | null> {
  const m = await prisma.tenantMembership.findFirst({
    where: { tenantId, isOwner: true, active: true },
    include: { user: { select: { email: true } } },
    orderBy: { joinedAt: 'asc' },
  });
  return m?.user.email ?? null;
}

/**
 * Devuelve los emails de TODOS los owners activos del tenant (puede haber
 * más de uno). Usado para notificaciones broadcast (upload de documentos,
 * etc.) donde queremos avisar a todos los dueños.
 */
export async function getTenantOwnerEmails(tenantId: string): Promise<string[]> {
  const ms = await prisma.tenantMembership.findMany({
    where: { tenantId, isOwner: true, active: true },
    include: { user: { select: { email: true, active: true } } },
    orderBy: { joinedAt: 'asc' },
  });
  return ms
    .filter(m => m.user.active)
    .map(m => m.user.email);
}

/**
 * Dado un userId, retorna su email. Null si el user no existe o está inactivo.
 */
export async function getUserEmailById(userId: string): Promise<string | null> {
  const u = await prisma.user.findUnique({
    where: { id: userId },
    select: { email: true, active: true },
  });
  return u && u.active ? u.email : null;
}

export async function verifyMembership(userId: string, tenantId: string): Promise<{
  rolNombre: Role;
  isOwner: boolean;
} | null> {
  const m = await prisma.tenantMembership.findFirst({
    where: { userId, tenantId, active: true },
    include: { rol: { select: { nombre: true } }, tenant: { select: { active: true } } },
  });
  if (!m || !m.tenant.active) return null;
  return { rolNombre: m.rol.nombre as Role, isOwner: m.isOwner };
}
