import { HttpErrorResponse, HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { Router } from '@angular/router';
import { catchError, switchMap, throwError } from 'rxjs';
import { AuthService } from '../services/auth/auth.service';
import { API_CONFIG } from '../config/api.config';
import { AUTH_ENDPOINTS } from '../end-points/auth/auth.endpoints';

const RETRY_HEADER = 'X-Auth-Retry';

function isEndpointRequest(requestUrl: string, endpointUrl: string): boolean {
  return (
    requestUrl === endpointUrl ||
    requestUrl.startsWith(`${endpointUrl}?`)
  );
}

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const authService = inject(AuthService);
  const router = inject(Router);

  const isLoginRequest = isEndpointRequest(
    req.url,
    AUTH_ENDPOINTS.login
  );

  const isRefreshRequest = isEndpointRequest(
    req.url,
    AUTH_ENDPOINTS.refresh
  );

  if (isLoginRequest || isRefreshRequest) {
    return next(req);
  }

  const token = authService.accessToken;
  const authReq = token
    ? req.clone({ setHeaders: { Authorization: `Bearer ${token}` } })
    : req;

  return next(authReq).pipe(
    catchError((error: HttpErrorResponse) => {
      if (error.status !== 401 || !authService.accessToken || isRefreshRequest || req.headers.has(RETRY_HEADER)) {
        return throwError(() => error);
      }

      return authService.refreshAccessToken().pipe(
        switchMap(() => {
          const refreshedToken = authService.accessToken;

          if (!refreshedToken) {
            return throwError(() => error);
          }

          const retriedRequest = req.clone({
            setHeaders: {
              Authorization: `Bearer ${refreshedToken}`,
              [RETRY_HEADER]: 'true',
            },
          });

          return next(retriedRequest);
        }),
        catchError((refreshError) => {
          authService.logout();
          const currentUrl = router.url;
          const safeReturnUrl = currentUrl.startsWith('/') ? currentUrl : '/';
          void router.navigate(['/auth/login'], {
            queryParams: { returnUrl: safeReturnUrl },
          });
          return throwError(() => refreshError);
        })
      );
    })
  );
};
