import { NextResponse } from "next/server";
import { headers } from "next/headers";
import { connectDB } from "@/lib/db";
import { auth } from "@/lib/auth";
import { USER_ROLES } from "@/config/app.config";
import { STAFF_PERMISSIONS } from "@/config/permissions.config";
import { assertAdminOrStaffPermissions } from "@/lib/staff-authz";
import { InventoryLocation } from "@/models/inventory-location.model";
import { getDemoModeMutationResponse } from "@/lib/demo-mode";

/**
 * Reading locations is broad on purpose: the admin, staff, and vendor
 * dashboards (product form, POS, transfers, settings) all need the list, so any
 * signed-in non-customer may fetch it. Writing is not — see
 * `requireLocationWriteSession`.
 */
async function requirePrivilegedSession(): Promise<
  | { ok: true }
  | { ok: false; response: NextResponse }
> {
  const session = await auth.api.getSession({ headers: await headers() });
  if (!session) {
    return {
      ok: false,
      response: NextResponse.json(
        { success: false, message: "Authentication required" },
        { status: 401 },
      ),
    };
  }
  const roles = session.user.roles ?? [session.user.role];
  const isPrivileged = roles.some(
    (role) => role && role !== USER_ROLES.CUSTOMER,
  );
  if (!isPrivileged) {
    return {
      ok: false,
      response: NextResponse.json(
        { success: false, message: "You do not have permission to manage locations" },
        { status: 403 },
      ),
    };
  }
  return { ok: true };
}

/**
 * Inventory locations are platform-global — one vendor renaming or deleting the
 * default location breaks POS checkout and transfers for the whole store. So
 * mutations need an admin, or a staff member the admin gave inventory/POS
 * rights to; a vendor with a dashboard login is not enough.
 */
export async function requireLocationWriteSession(): Promise<
  | { ok: true }
  | { ok: false; response: NextResponse }
> {
  const session = await auth.api.getSession({ headers: await headers() });
  if (!session) {
    return {
      ok: false,
      response: NextResponse.json(
        { success: false, message: "Authentication required" },
        { status: 401 },
      ),
    };
  }

  try {
    await assertAdminOrStaffPermissions(
      session as unknown as { user: { id: string; role: string } },
      [STAFF_PERMISSIONS.MANAGE_INVENTORY, STAFF_PERMISSIONS.MANAGE_POS],
      "any",
    );
    return { ok: true };
  } catch {
    return {
      ok: false,
      response: NextResponse.json(
        {
          success: false,
          message: "You do not have permission to manage locations",
        },
        { status: 403 },
      ),
    };
  }
}

export async function GET(request: Request) {
  try {
    const authResult = await requirePrivilegedSession();
    if (!authResult.ok) return authResult.response;

    await connectDB();

    const { searchParams } = new URL(request.url);
    const includeInactive = searchParams.get("includeInactive") === "true";

    const filter = includeInactive ? {} : { isActive: true };
    const locations = await InventoryLocation.find(filter)
      .sort({ isDefault: -1, name: 1 })
      .lean();

    return NextResponse.json({
      success: true,
      data: locations,
    });
  } catch (error) {
    console.error("Failed to fetch locations:", error);
    return NextResponse.json(
      { success: false, message: "Failed to fetch locations" },
      { status: 500 }
    );
  }
}

export async function POST(request: Request) {
  try {
    const authResult = await requireLocationWriteSession();
    if (!authResult.ok) return authResult.response;

    await connectDB();

    const body = await request.json();
    const { name, address, isDefault } = body;

    if (!name || typeof name !== "string" || name.trim().length === 0) {
      return NextResponse.json(
        { success: false, message: "Location name is required" },
        { status: 400 }
      );
    }

    const location = await InventoryLocation.create({
      name: name.trim(),
      address: address?.trim() || "",
      isDefault: Boolean(isDefault),
      isActive: true,
    });

    return NextResponse.json(
      {
        success: true,
        data: location.toObject(),
        message: "Location created successfully",
      },
      { status: 201 }
    );
  } catch (error) {
    console.error("Failed to create location:", error);
    return NextResponse.json(
      { success: false, message: "Failed to create location" },
      { status: 500 }
    );
  }
}
