import { NextResponse } from "next/server";
import { auth } from "@clerk/nextjs/server";
import { eq, sql } from "@fitai/database";
import { db, users as usersTable, gyms as gymsTable } from "@fitai/database";
import { ensureUserSynced } from "@/lib/sync-user";
import { getDatabase } from "@/lib/database";
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 {
    const { userId } = await auth();
    if (!userId) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const appDb = await getDatabase();
    const currentUser = await ensureUserSynced(userId, appDb);

    if (!currentUser) {
      return NextResponse.json({ error: "Forbidden" }, { status: 403 });
    }

    if (currentUser.role !== "admin" && currentUser.role !== "superAdmin") {
      return NextResponse.json({ error: "Forbidden" }, { status: 403 });
    }

    await ensureGymsTable();
    let rows = await db
      .select()
      .from(gymsTable)
      .where(eq(gymsTable.status, "active"))
      .orderBy(sql`created_at DESC`)
      .all();

    if (currentUser.role !== "superAdmin") {
      if (!currentUser.gymId) {
        return NextResponse.json({ error: "No gym assigned" }, { status: 403 });
      }
      rows = rows.filter((row) => row.id === currentUser.gymId);
    }

    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 });

    const appDb = await getDatabase();
    const currentUser = await ensureUserSynced(userId, appDb);

    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 = new Date();

    // Use Drizzle's insert method instead of raw SQL
    await db.insert(gymsTable).values({
      id,
      name,
      location: location ?? null,
      status: "active",
      adminUserId: adminUserId!,
      createdAt: nowTs,
      updatedAt: nowTs,
    });

    // Assign the admin to this gym immediately after creation
    await db
      .update(usersTable)
      .set({ gymId: id, updatedAt: nowTs })
      .where(eq(usersTable.id, adminUserId!));

    const created = await db
      .select()
      .from(gymsTable)
      .where(eq(gymsTable.id, id))
      .get();
    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)
  );
}
