import { NextRequest, NextResponse } from "next/server";
import { auth } from "@clerk/nextjs/server";
import { getDatabase } from "@/lib/database";
import { ensureUserSynced } from "@/lib/sync-user";
import log from "@/lib/logger";

/**
 * GET /api/trainer-client
 * Get trainer-client assignments
 *
 * Query params:
 * - trainerId: string (optional) - Filter by trainer
 * - clientId: string (optional) - Filter by client
 */
export async function GET(request: NextRequest) {
  try {
    const { userId: authUserId } = await auth();
    if (!authUserId) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const db = await getDatabase();
    const currentUser = await ensureUserSynced(authUserId, db);

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

    // Only admins and superadmins can view all assignments
    if (currentUser.role !== "admin" && currentUser.role !== "superAdmin") {
      return NextResponse.json(
        { error: "Only admins can view trainer-client assignments" },
        { status: 403 },
      );
    }

    const { searchParams } = new URL(request.url);
    const trainerId = searchParams.get("trainerId");
    const clientId = searchParams.get("clientId");

    if (trainerId && clientId) {
      const [trainer, client] = await Promise.all([
        db.getUserById(trainerId),
        db.getUserById(clientId),
      ]);

      if (!trainer || !client) {
        return NextResponse.json({ error: "User not found" }, { status: 404 });
      }

      if (
        currentUser.role !== "superAdmin" &&
        (!currentUser.gymId ||
          trainer.gymId !== currentUser.gymId ||
          client.gymId !== currentUser.gymId)
      ) {
        return NextResponse.json(
          { error: "Cannot access assignments from other gyms" },
          { status: 403 },
        );
      }
    }

    if (trainerId && !clientId) {
      const trainer = await db.getUserById(trainerId);
      if (!trainer) {
        return NextResponse.json(
          { error: "Trainer not found" },
          { status: 404 },
        );
      }

      if (
        currentUser.role !== "superAdmin" &&
        (!currentUser.gymId || trainer.gymId !== currentUser.gymId)
      ) {
        return NextResponse.json(
          { error: "Cannot access assignments from other gyms" },
          { status: 403 },
        );
      }
    }

    if (!trainerId && clientId) {
      const client = await db.getUserById(clientId);
      if (!client) {
        return NextResponse.json(
          { error: "Client not found" },
          { status: 404 },
        );
      }

      if (
        currentUser.role !== "superAdmin" &&
        (!currentUser.gymId || client.gymId !== currentUser.gymId)
      ) {
        return NextResponse.json(
          { error: "Cannot access assignments from other gyms" },
          { status: 403 },
        );
      }
    }

    let assignments = trainerId
      ? await db.getTrainerClientAssignments(trainerId)
      : await db.getAllTrainerClientAssignments();

    if (clientId) {
      assignments = assignments.filter((a) => a.clientId === clientId);
    }

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

      const involvedUserIds = Array.from(
        new Set(
          assignments.flatMap((assignment) => [
            assignment.trainerId,
            assignment.clientId,
          ]),
        ),
      );

      const users = await Promise.all(
        involvedUserIds.map((userId) => db.getUserById(userId)),
      );

      const gymByUserId = new Map(
        users
          .filter((user): user is NonNullable<typeof user> => !!user)
          .map((user) => [user.id, user.gymId]),
      );

      assignments = assignments.filter((assignment) => {
        const trainerGymId = gymByUserId.get(assignment.trainerId);
        const clientGymId = gymByUserId.get(assignment.clientId);

        return (
          trainerGymId === currentUser.gymId &&
          clientGymId === currentUser.gymId
        );
      });
    }

    return NextResponse.json({ assignments });
  } catch (error) {
    log.error("Failed to get trainer-client assignments", error);
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 },
    );
  }
}

/**
 * POST /api/trainer-client
 * Create a new trainer-client assignment
 */
export async function POST(request: NextRequest) {
  try {
    const { userId: authUserId } = await auth();
    if (!authUserId) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const db = await getDatabase();
    const currentUser = await ensureUserSynced(authUserId, db);

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

    // Only admins can create assignments
    if (currentUser.role !== "admin" && currentUser.role !== "superAdmin") {
      return NextResponse.json(
        { error: "Only admins can assign trainers to clients" },
        { status: 403 },
      );
    }

    const body = await request.json();
    const { trainerId, clientId } = body;

    if (!trainerId || !clientId) {
      return NextResponse.json(
        { error: "trainerId and clientId are required" },
        { status: 400 },
      );
    }

    // Verify trainer exists and has trainer role
    const trainer = await db.getUserById(trainerId);
    if (!trainer) {
      return NextResponse.json({ error: "Trainer not found" }, { status: 404 });
    }
    if (trainer.role !== "trainer" && trainer.role !== "admin") {
      return NextResponse.json(
        { error: "User must be a trainer or admin" },
        { status: 400 },
      );
    }

    // Verify client exists
    const client = await db.getUserById(clientId);
    if (!client) {
      return NextResponse.json({ error: "Client not found" }, { status: 404 });
    }
    if (client.role !== "client") {
      return NextResponse.json(
        { error: "User must be a client" },
        { status: 400 },
      );
    }

    if (
      currentUser.role !== "superAdmin" &&
      (!currentUser.gymId ||
        trainer.gymId !== currentUser.gymId ||
        client.gymId !== currentUser.gymId)
    ) {
      return NextResponse.json(
        { error: "Cannot assign users from other gyms" },
        { status: 403 },
      );
    }

    // Check if assignment already exists
    const existingAssignments = await db.getTrainerClientAssignments(trainerId);
    const existingAssignment = existingAssignments.find(
      (a) => a.clientId === clientId && a.isActive,
    );
    if (existingAssignment) {
      return NextResponse.json(
        { error: "Trainer is already assigned to this client" },
        { status: 409 },
      );
    }

    // Create the assignment
    const assignment = await db.createTrainerClientAssignment({
      trainerId,
      clientId,
      assignedAt: new Date(),
      assignedBy: currentUser.id,
      isActive: true,
    });

    log.info("Trainer-client assignment created", {
      trainerId,
      clientId,
      assignedBy: currentUser.id,
    });

    return NextResponse.json({ assignment }, { status: 201 });
  } catch (error) {
    log.error("Failed to create trainer-client assignment", error);
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 },
    );
  }
}
