import { HttpErrorResponse, HttpInterceptorFn } from '@angular/common/http';
import { catchError, throwError } from 'rxjs';

export interface HttpProblemDetails {
  type?: string;
  title: string;
  status?: number;
  detail?: string;
  instance?: string;
  [extension: string]: unknown;
}

export class HttpProblemDetailsError extends Error {
  constructor(
    readonly problem: HttpProblemDetails,
    readonly originalError: HttpErrorResponse
  ) {
    super(problem.detail ?? problem.title, { cause: originalError });
    this.name = 'HttpProblemDetailsError';
  }
}

/** Converts RFC 9457-like responses into a typed error while retaining the original response. */
export const problemDetailsInterceptor: HttpInterceptorFn = (request, next) =>
  next(request).pipe(
    catchError((error: unknown) => {
      if (error instanceof HttpErrorResponse && isProblemDetails(error.error)) {
        return throwError(() => new HttpProblemDetailsError(error.error, error));
      }

      return throwError(() => error);
    })
  );

function isProblemDetails(value: unknown): value is HttpProblemDetails {
  if (typeof value !== 'object' || value === null) {
    return false;
  }

  const candidate = value as Record<string, unknown>;
  return typeof candidate['title'] === 'string';
}
