import createMiddleware from "next-intl/middleware";
import type {JWT} from "next-auth/jwt";
import {getToken} from "next-auth/jwt";
import {NextRequest, NextResponse} from "next/server";
import {APP_ROUTES} from "@/lib/constants/routes";
import {routing} from "@/lib/i18n/routing";

const intlMiddleware = createMiddleware({
  locales: routing.locales,
  defaultLocale: routing.defaultLocale
});

function extractLocale(pathname: string) {
  const [, locale] = pathname.split("/");
  return routing.locales.includes(locale as (typeof routing.locales)[number]) ? locale : null;
}

function getPathWithoutLocale(pathname: string, locale: string | null) {
  if (!locale) {
    return pathname;
  }

  const nextPath = pathname.slice(locale.length + 1);
  return nextPath.length > 0 ? nextPath : "/";
}

function buildLocalizedUrl(request: NextRequest, locale: string, path: string, searchParams?: Record<string, string>) {
  const url = new URL(`/${locale}${path}`, request.url);

  if (searchParams) {
    for (const [key, value] of Object.entries(searchParams)) {
      url.searchParams.set(key, value);
    }
  }

  return url;
}

type AppToken = JWT & {
  platformRole?: "SUPER_ADMIN" | null;
  activeTenantId?: string | null;
  memberships?: Array<{
    tenantId: string;
    tenantSlug: string;
  }>;
};

function resolveDashboardPath(locale: string, token: AppToken | null) {
  if (token?.platformRole === "SUPER_ADMIN") {
    return `/${locale}${APP_ROUTES.superAdmin}`;
  }

  const membership =
    token?.memberships?.find((item) => item.tenantId === token.activeTenantId) ?? token?.memberships?.[0];

  if (membership) {
    return `/${locale}${APP_ROUTES.company}/${membership.tenantSlug}`;
  }

  return `/${locale}${APP_ROUTES.home}`;
}

export default async function middleware(request: NextRequest) {
  const intlResponse = intlMiddleware(request);
  const locale = extractLocale(request.nextUrl.pathname);
  const pathname = getPathWithoutLocale(request.nextUrl.pathname, locale);

  if (!locale) {
    return intlResponse;
  }

  if (pathname.startsWith("/api") || pathname.startsWith("/_next")) {
    return intlResponse;
  }

  const token = await getToken({
    req: request,
    secret: process.env.AUTH_SECRET
  });
  const sessionToken = (token && typeof token !== "string" ? (token as AppToken) : null);

  const isAuthPage =
    pathname === APP_ROUTES.signIn ||
    pathname === APP_ROUTES.signUp ||
    pathname === APP_ROUTES.forgotPassword;

  const isProtectedRoute =
    pathname.startsWith(APP_ROUTES.superAdmin) ||
    pathname.startsWith(APP_ROUTES.company);

  if (isAuthPage && sessionToken) {
    return NextResponse.redirect(new URL(resolveDashboardPath(locale, sessionToken), request.url));
  }

  if (!isProtectedRoute) {
    return intlResponse;
  }

  if (!sessionToken) {
    return NextResponse.redirect(
      buildLocalizedUrl(request, locale, APP_ROUTES.signIn, {
        callbackUrl: request.nextUrl.pathname
      })
    );
  }

  if (pathname.startsWith(APP_ROUTES.superAdmin)) {
    if (sessionToken.platformRole !== "SUPER_ADMIN") {
      return NextResponse.redirect(buildLocalizedUrl(request, locale, APP_ROUTES.unauthorized));
    }

    return intlResponse;
  }

  if (pathname.startsWith(APP_ROUTES.company)) {
    const tenantSlug = pathname.split("/")[2];
    const matchingMembership =
      sessionToken.memberships?.find((membership) => membership.tenantSlug === tenantSlug) ?? null;

    if (!matchingMembership && sessionToken.platformRole !== "SUPER_ADMIN") {
      return NextResponse.redirect(buildLocalizedUrl(request, locale, APP_ROUTES.unauthorized));
    }

    if (
      matchingMembership &&
      sessionToken.activeTenantId &&
      sessionToken.activeTenantId !== matchingMembership.tenantId
    ) {
      const activeMembership =
        sessionToken.memberships?.find((membership) => membership.tenantId === sessionToken.activeTenantId) ??
        matchingMembership;

      return NextResponse.redirect(
        buildLocalizedUrl(request, locale, `${APP_ROUTES.company}/${activeMembership.tenantSlug}`)
      );
    }
  }

  return intlResponse;
}

export const config = {
  matcher: ["/", "/(ar|en)/:path*"]
};