import { NextResponse } from "next/server"; import { auth } from "@clerk/nextjs/server"; import { eq, sql } from "@fitai/database"; import { db, users as usersTable } from "@fitai/database"; import { ensureUserSynced } from "@/lib/sync-user"; import log from "@/lib/logger"; async function ensureGymsTable() { await db.run(sql` CREATE TABLE IF NOT EXISTS gyms ( id TEXT PRIMARY KEY, name TEXT NOT NULL, location TEXT, status TEXT NOT NULL CHECK (status IN ('active','inactive')) DEFAULT 'active', admin_user_id TEXT NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL ) `); } // GET /api/gyms // Lists active gyms for selection (grid) export async function GET() { try { await ensureGymsTable(); const rows = await db.all( sql`SELECT * FROM gyms WHERE status = 'active' ORDER BY created_at DESC`, ); return NextResponse.json(rows); } catch (error) { log.error("Failed to get gyms", error); return new NextResponse("Internal Server Error", { status: 500 }); } } // POST /api/gyms // Create a gym. Allowed roles: superAdmin, admin. // - admin: can only create gyms for themselves (adminUserId = current user) // - superAdmin: can create for self or specify adminUserId export async function POST(req: Request) { try { await ensureGymsTable(); const { userId } = await auth(); if (!userId) return new NextResponse("Unauthorized", { status: 401 }); // Ensure our local DB has the user synced (role, etc.) const currentUser = await ensureUserSynced(userId, { // minimal facade for ensureUserSynced to work: it expects an object implementing part of IDatabase getUserById: async (id: string) => { const row = await db .select() .from(usersTable) .where(eq(usersTable.id, id)) .get(); return row ? { id: row.id, email: row.email, firstName: row.firstName, lastName: row.lastName, password: row.password ?? "", phone: row.phone ?? undefined, role: row.role, imageUrl: undefined, createdAt: new Date(row.createdAt), updatedAt: new Date(row.updatedAt), } : null; }, updateUser: async (id: string, updates: any) => { await db .update(usersTable) .set({ ...updates, updatedAt: new Date(), }) .where(eq(usersTable.id, id)) .run(); const row = await db .select() .from(usersTable) .where(eq(usersTable.id, id)) .get(); return row ? { id: row.id, email: row.email, firstName: row.firstName, lastName: row.lastName, password: row.password ?? "", phone: row.phone ?? undefined, role: row.role, imageUrl: undefined, createdAt: new Date(row.createdAt), updatedAt: new Date(row.updatedAt), } : null; }, } as any); if ( !currentUser || (currentUser.role !== "admin" && currentUser.role !== "superAdmin") ) { return new NextResponse("Forbidden", { status: 403 }); } const body = await req.json().catch(() => null); if (!body || typeof body !== "object") { return new NextResponse("Invalid JSON body", { status: 400 }); } const name = String(body.name ?? "").trim(); const location = body.location ? String(body.location).trim() : null; let adminUserId: string | null = body.adminUserId ? String(body.adminUserId) : null; if (!name) { return NextResponse.json({ error: "name is required" }, { status: 400 }); } // Enforce admin ownership rules if (currentUser.role === "admin") { adminUserId = currentUser.id; } else if (currentUser.role === "superAdmin") { adminUserId = adminUserId || currentUser.id; } // Basic check that adminUserId exists and is an admin or superAdmin const adminRow = await db .select() .from(usersTable) .where(eq(usersTable.id, adminUserId!)) .get(); if ( !adminRow || (adminRow.role !== "admin" && adminRow.role !== "superAdmin") ) { return NextResponse.json( { error: "adminUserId must reference an admin or superAdmin" }, { status: 400 }, ); } const id = generateId(); const nowTs = Date.now(); await db.run( sql`INSERT INTO gyms (id, name, location, status, admin_user_id, created_at, updated_at) VALUES (${id}, ${name}, ${location ?? null}, 'active', ${adminUserId!}, ${nowTs}, ${nowTs})`, ); // Assign the admin to this gym immediately after creation await db.run( sql`UPDATE users SET gym_id = ${id}, updated_at = ${nowTs} WHERE id = ${adminUserId!}`, ); const created = await db.get(sql`SELECT * FROM gyms WHERE id = ${id}`); return NextResponse.json(created, { status: 201 }); } catch (error) { log.error("Failed to create gym", error); return new NextResponse("Internal Server Error", { status: 500 }); } } function generateId(): string { // Simple URL-safe id generator return ( Math.random().toString(36).slice(2, 10) + Math.random().toString(36).slice(2, 10) ); }