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