import { NextResponse, type NextRequest } from "next/server";

const mutatingMethods = new Set(["POST", "PUT", "PATCH", "DELETE"]);

export function middleware(request: NextRequest) {
  if (!mutatingMethods.has(request.method)) return NextResponse.next();
  if (request.nextUrl.pathname === "/api/billing/webhook") return NextResponse.next();

  const origin = request.headers.get("origin");
  if (!origin) return NextResponse.next();

  const allowed = new Set([request.nextUrl.origin]);
  const host = request.headers.get("host");
  const forwardedHost = request.headers.get("x-forwarded-host");
  const forwardedProto = request.headers.get("x-forwarded-proto") ?? request.nextUrl.protocol.replace(":", "");

  for (const candidateHost of [host, forwardedHost]) {
    if (candidateHost) {
      allowed.add(`${request.nextUrl.protocol}//${candidateHost}`);
      allowed.add(`${forwardedProto}://${candidateHost}`);
    }
  }

  const publicUrl = process.env.NEXT_PUBLIC_SITE_URL;
  if (publicUrl) {
    try {
      allowed.add(new URL(publicUrl).origin);
      allowed.add(new URL(publicUrl.replace("://", "://www.")).origin);
    } catch {
      // Ignore malformed local configuration and keep same-origin protection.
    }
  }

  if (!allowed.has(origin) && !isTrustedLocalOrigin(origin, request.nextUrl)) {
    return NextResponse.json({ ok: false, error: "Ungueltige Anfragequelle." }, { status: 403 });
  }

  return NextResponse.next();
}

export const config = {
  matcher: "/api/:path*",
};

function isTrustedLocalOrigin(origin: string, target: URL) {
  try {
    const source = new URL(origin);
    const localHosts = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
    return (
      localHosts.has(source.hostname) &&
      localHosts.has(target.hostname) &&
      source.port === target.port
    );
  } catch {
    return false;
  }
}
