import { createServerClient } from "@supabase/ssr";
import { NextResponse, type NextRequest } from "next/server";
import {
  PUBLIC_AUTH_PAGES,
  AUTH_ROUTES,
  RECOVERY_COOKIE_NAME,
} from "@/features/auth/constants";

/**
 * 서버 사이드 인증 상태를 관리하고 보호된 라우트를 처리합니다.
 */
// 서버 사이드 인증 상태를 관리하고 보호된 라우트를 처리합니다.
export async function updateSession(request: NextRequest) {
  // 1. 초기 Supabase 응답 객체 생성
  // request 헤더 등을 포함하여 초기 상태 설정
  let supabaseResponse = NextResponse.next({ request });

  // 2. Supabase 클라이언트 생성 (SSR 전용)
  // 쿠키 조작을 위한 setAll/getAll 메서드 오버라이딩 포함
  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        // 쿠키 가져오기
        getAll() {
          return request.cookies.getAll();
        },
        // 쿠키 설정하기 (요청 및 응답 객체 모두에 적용)
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value }) =>
            request.cookies.set(name, value),
          );
          supabaseResponse = NextResponse.next({ request });
          cookiesToSet.forEach(({ name, value, options }) =>
            supabaseResponse.cookies.set(name, value, options),
          );
        },
      },
    },
  );

  // 3. 현재 사용자 정보 조회
  // getUser() 사용이 보안상 안전함 (getSession보다 권장됨)
  const {
    data: { user },
  } = await supabase.auth.getUser();

  // 4. 현재 요청 URL과 복구용 쿠키 확인
  const { pathname } = request.nextUrl;
  const recoveryCookie = request.cookies.get(RECOVERY_COOKIE_NAME)?.value;

  // 5. 복구 쿠키가 있는데 로그인이 안 된 경우 (세션 만료 등)
  // 로그인 페이지로 강제 리다이렉트 후 복구 쿠키 삭제
  if (recoveryCookie && !user) {
    const response = NextResponse.redirect(
      new URL(AUTH_ROUTES.LOGIN, request.url),
    );
    response.cookies.delete(RECOVERY_COOKIE_NAME);
    return response;
  }

  // 6. 현재 페이지가 비밀번호 재설정 관련 라우트인지 확인
  const isRecoveryRoute =
    pathname.startsWith(AUTH_ROUTES.RESET_PASSWORD) ||
    pathname.startsWith(AUTH_ROUTES.AUTH_CONFIRM);

  // 7. 복구 쿠키가 있는데 재설정 라우트가 아닌 다른 곳으로 가려는 경우
  // 강제로 비밀번호 재설정 페이지로 리다이렉트 (보안 조치)
  if (recoveryCookie && !isRecoveryRoute) {
    return NextResponse.redirect(
      new URL(AUTH_ROUTES.RESET_PASSWORD, request.url),
    );
  }

  // 8. 현재 페이지가 로그인/회원가입 등 공용 인증 페이지인지 확인
  const isAuthPage = PUBLIC_AUTH_PAGES.some((page) =>
    pathname.startsWith(page),
  );

  // 9. 비로그인 사용자 접근 제어
  // - 유저가 없음 (!user)
  // - 인증 페이지 아님 (!isAuthPage)
  // - 메인 페이지(홈) 아님 (pathname !== AUTH_ROUTES.HOME)
  // -> 로그인 페이지로 리다이렉트
  if (!user && !isAuthPage && pathname !== AUTH_ROUTES.HOME) {
    return NextResponse.redirect(new URL(AUTH_ROUTES.LOGIN, request.url));
  }

  // 10. 로그인 사용자 접근 제어 (인증 페이지 접근 시)
  // - 유저가 있음 (user)
  // - 인증 페이지 접근 시도 (isAuthPage) - 예: 이미 로그인했는데 /login 접근
  // - 비밀번호 재설정은 아님
  // - 복구 모드 아님
  // -> 메인 페이지로 리다이렉트
  if (
    user &&
    isAuthPage &&
    pathname !== AUTH_ROUTES.RESET_PASSWORD &&
    !recoveryCookie
  ) {
    return NextResponse.redirect(new URL(AUTH_ROUTES.HOME, request.url));
  }

  // 11. 최종 응답 반환 (변경된 쿠키 등이 포함됨)
  return supabaseResponse;
}
