import { CallHandler, ExecutionContext } from '@nestjs/common';
import { lastValueFrom, of } from 'rxjs';
import { MediaStorageService } from '../media/media-storage.service';
import { MediaUrlInterceptor } from './media-url.interceptor';

describe('MediaUrlInterceptor', () => {
  const storageService = {
    shouldSignResponseUrls: jest.fn(() => true),
    resolveResponseUrl: jest.fn(async (url: string) => {
      if (url.endsWith('.m3u8')) {
        return 'https://api.oudelaa.test/api/v1/media/hls/uploads/posts/hls/master.m3u8';
      }
      return url.includes('s3.cumin.dev') ? `${url}?signed=true` : url;
    }),
  } as unknown as MediaStorageService;
  const interceptor = new MediaUrlInterceptor(storageService);
  const context = {
    getType: () => 'http',
  } as ExecutionContext;

  beforeEach(() => {
    (storageService.resolveResponseUrl as jest.Mock).mockClear();
  });

  it('signs nested media URLs and variants throughout a response', async () => {
    const response = {
      imageUrls: ['https://s3.cumin.dev/uploads/image.jpg'],
      media: {
        displayUrl: 'https://s3.cumin.dev/uploads/display.jpg',
        images: [
          {
            url: 'https://s3.cumin.dev/uploads/medium.jpg',
            originalUrl: 'https://s3.cumin.dev/uploads/original.jpg',
            variants: {
              lowUrl: 'https://s3.cumin.dev/uploads/low.jpg',
            },
          },
        ],
        preferredPlaybackUrl: 'https://s3.cumin.dev/uploads/audio.mp3',
      },
      externalUrl: 'https://cdn.example.com/image.jpg',
    };
    const next = { handle: () => of(response) } as CallHandler;

    const result = (await lastValueFrom(interceptor.intercept(context, next))) as typeof response;

    expect(result.imageUrls[0]).toContain('?signed=true');
    expect(result.media.displayUrl).toContain('?signed=true');
    expect(result.media.images[0].originalUrl).toContain('?signed=true');
    expect(result.media.images[0].variants.lowUrl).toContain('?signed=true');
    expect(result.media.preferredPlaybackUrl).toContain('?signed=true');
    expect(result.externalUrl).toBe('https://cdn.example.com/image.jpg');
  });

  it('uses the rewritten HLS endpoint while keeping signed MP4 as fallback', async () => {
    const response = {
      videoUrl: 'https://s3.cumin.dev/uploads/posts/video/video.mp4',
      hlsUrl: 'https://s3.cumin.dev/uploads/posts/hls/stream/master.m3u8',
      media: {
        videoUrl: 'https://s3.cumin.dev/uploads/posts/video/video.mp4',
        hlsUrl: 'https://s3.cumin.dev/uploads/posts/hls/stream/master.m3u8',
        preferredPlaybackUrl: 'https://s3.cumin.dev/uploads/posts/hls/stream/master.m3u8',
      },
    };
    const next = { handle: () => of(response) } as CallHandler;

    const result = (await lastValueFrom(interceptor.intercept(context, next))) as typeof response;

    expect(result.hlsUrl).toContain('/api/v1/media/hls/');
    expect(result.media.hlsUrl).toContain('/api/v1/media/hls/');
    expect(result.media.preferredPlaybackUrl).toContain('/api/v1/media/hls/');
    expect(result.videoUrl).toContain('signed=true');
    expect(result.media.videoUrl).toContain('signed=true');
  });
});
