'use server';

import { revalidatePath } from 'next/cache';
import { getCurrentUser, hashPassword, deleteOtherSessions } from '@/lib/auth';
import { prisma } from '@/lib/prisma';

/**
 * Admin user-management server actions.
 *
 * Every action does its own admin gate (defense in depth — the page that
 * calls them also checks `user.isAdmin`, but actions are POSTable from
 * anywhere). The "last admin" guard prevents demoting or deleting the
 * final admin, which would lock the instance out of admin-only flows.
 */

async function requireAdmin() {
  const me = await getCurrentUser();
  if (!me) throw new Error('Not signed in');
  if (!me.isAdmin) throw new Error('Forbidden');
  return me;
}

async function adminCount(): Promise<number> {
  return prisma.user.count({ where: { isAdmin: true } });
}

export async function setUserAdmin(
  userId: string,
  makeAdmin: boolean,
): Promise<{ success?: true; error?: string }> {
  try {
    await requireAdmin();
    const target = await prisma.user.findUnique({ where: { id: userId } });
    if (!target) return { error: 'User not found.' };

    if (target.isAdmin === makeAdmin) {
      return { success: true }; // no-op
    }

    if (target.isAdmin && !makeAdmin && (await adminCount()) <= 1) {
      return {
        error:
          'Cannot demote the last admin. Promote another user to admin first.',
      };
    }

    await prisma.user.update({
      where: { id: userId },
      data: { isAdmin: makeAdmin },
    });
    revalidatePath('/main/admin/users');
    return { success: true };
  } catch (err) {
    console.error('setUserAdmin error:', err);
    return { error: (err as Error).message ?? 'Failed.' };
  }
}

export async function adminResetPassword(
  userId: string,
  newPassword: string,
): Promise<{ success?: true; error?: string; revoked?: number }> {
  try {
    await requireAdmin();
    if (newPassword.length < 8) {
      return { error: 'Password must be at least 8 characters.' };
    }
    const target = await prisma.user.findUnique({ where: { id: userId } });
    if (!target) return { error: 'User not found.' };

    const hash = await hashPassword(newPassword);
    await prisma.user.update({
      where: { id: userId },
      data: { passwordHash: hash },
    });

    // Force the user to re-authenticate everywhere — admin-initiated
    // reset implies the old credential is no longer trusted.
    const revoked = await deleteOtherSessions(userId, null);
    revalidatePath('/main/admin/users');
    return { success: true, revoked };
  } catch (err) {
    console.error('adminResetPassword error:', err);
    return { error: (err as Error).message ?? 'Failed.' };
  }
}

export async function deleteUser(
  userId: string,
): Promise<{ success?: true; error?: string }> {
  try {
    const me = await requireAdmin();
    if (userId === me.id) {
      return {
        error:
          'You cannot delete your own account from here. Ask another admin, or do it from your own settings page.',
      };
    }
    const target = await prisma.user.findUnique({ where: { id: userId } });
    if (!target) return { error: 'User not found.' };

    if (target.isAdmin && (await adminCount()) <= 1) {
      return {
        error:
          'Cannot delete the last admin. Promote another user to admin first.',
      };
    }

    // Cascading delete is configured in schema.prisma via onDelete:
    // Cascade on every relation owned by User, so this removes their
    // workouts, exercises, sessions, preferences, etc. in one shot.
    await prisma.user.delete({ where: { id: userId } });
    revalidatePath('/main/admin/users');
    return { success: true };
  } catch (err) {
    console.error('deleteUser error:', err);
    return { error: (err as Error).message ?? 'Failed.' };
  }
}
