import { HttpInterceptorFn, HttpRequest } from '@angular/common/http';
import { inject } from '@angular/core';
import { Router } from '@angular/router';
import { StorageService } from '../services/storage.service';
import { TokenValidator } from '../utils/token-validator';
import { RuntimeConfigService } from '../services/runtime-config.service';

/**
 * Auth Interceptor with Security Enhancements
 *
 * Security features:
 * - Validates token format before attaching
 * - Checks token expiration
 * - Prevents token leakage to external URLs
 * - Handles malformed tokens gracefully
 */
export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const storage = inject(StorageService);
  const router = inject(Router);
  const runtimeConfig = inject(RuntimeConfigService);

  // Skip token attachment for auth endpoints (login/register)
  if (isAuthEndpoint(req.url)) {
    return next(req);
  }

  // Only attach tokens to our API (includes configured runtime API URL)
  if (!isInternalApiRequest(req, runtimeConfig.apiBaseUrl)) {
    return next(req);
  }

  const token = storage.getToken();

  // Validate token before attaching
  if (token) {
    const validation = TokenValidator.validate(token);

    if (!validation.valid) {
      console.warn('Token validation failed:', validation.error);

      // Clear invalid token
      storage.clear();

      // Redirect to login for expired tokens
      if (validation.error === 'Token has expired') {
        router.navigate(['/login'], {
          queryParams: { reason: 'session_expired' },
        });
      }

      return next(req);
    }

    // Check if token needs refresh (within 5 minutes of expiry)
    if (TokenValidator.shouldRefresh(token, 300)) {
      // TODO: Implement token refresh logic
      console.warn('Token approaching expiry, consider refreshing');
    }

    const clonedReq = req.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`,
      },
    });
    return next(clonedReq);
  }

  return next(req);
};

/**
 * Check if request is to an authentication endpoint
 */
function isAuthEndpoint(url: string): boolean {
  const authEndpoints = [
    '/auth/login',
    '/auth/register',
    '/auth/department/login',
    '/auth/digilocker/login',
    '/auth/refresh',
    '/auth/forgot-password',
    '/auth/reset-password',
  ];

  return authEndpoints.some((endpoint) => url.includes(endpoint));
}

/**
 * Check if request is to our internal API
 * Prevents token leakage to external services
 */
function isInternalApiRequest(req: HttpRequest<unknown>, configuredApiUrl: string): boolean {
  const url = req.url.toLowerCase();

  // List of allowed API hosts
  const allowedHosts = [
    'localhost',
    '127.0.0.1',
    'api.goagel.gov.in', // Production API
    'staging-api.goagel.gov.in', // Staging API
  ];

  // Add configured API host dynamically (for VM/remote deployments)
  try {
    const configuredUrl = new URL(configuredApiUrl);
    if (configuredUrl.hostname && !allowedHosts.includes(configuredUrl.hostname)) {
      allowedHosts.push(configuredUrl.hostname);
    }
  } catch {
    // Invalid configured URL - ignore
  }

  try {
    const requestUrl = new URL(url, window.location.origin);
    return allowedHosts.some(
      (host) =>
        requestUrl.hostname === host ||
        requestUrl.hostname.endsWith('.' + host)
    );
  } catch {
    // Relative URL - assumed to be internal
    return url.startsWith('/') || url.startsWith('./');
  }
}
