import { describe, it, expect, vi, beforeEach } from 'vitest';
import { apiClient } from '@/services/api/client';
import {
  getHLSMasterPlaylistURL,
  getHLSQualityPlaylistURL,
  getHLSSegmentURL,
  getHLSStreamInfo,
  type HLSStreamInfo,
} from './hlsService';

// Mock apiClient
vi.mock('@/services/api/client', () => ({
  apiClient: {
    defaults: {
      baseURL: 'http://localhost:8080/api/v1',
    },
    get: vi.fn(),
  },
}));

describe('hlsService', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('getHLSMasterPlaylistURL', () => {
    it('should generate correct master playlist URL', () => {
      const trackId = 123;
      const url = getHLSMasterPlaylistURL(trackId);
      expect(url).toBe(
        'http://localhost:8080/api/v1/tracks/123/hls/master.m3u8',
      );
    });

    it('should handle different base URLs', () => {
      (apiClient.defaults as any).baseURL = 'https://api.example.com/api/v1';
      const url = getHLSMasterPlaylistURL(456);
      expect(url).toBe(
        'https://api.example.com/api/v1/tracks/456/hls/master.m3u8',
      );
    });

    it('should handle base URL without trailing slash', () => {
      (apiClient.defaults as any).baseURL = 'http://localhost:8080/api/v1';
      const url = getHLSMasterPlaylistURL(789);
      expect(url).toBe(
        'http://localhost:8080/api/v1/tracks/789/hls/master.m3u8',
      );
    });
  });

  describe('getHLSQualityPlaylistURL', () => {
    beforeEach(() => {
      (apiClient.defaults as any).baseURL = 'http://localhost:8080/api/v1';
    });

    it('should generate correct quality playlist URL', () => {
      const trackId = 123;
      const bitrate = '128k';
      const url = getHLSQualityPlaylistURL(trackId, bitrate);
      expect(url).toBe(
        'http://localhost:8080/api/v1/tracks/123/hls/128k/playlist.m3u8',
      );
    });

    it('should handle different bitrates', () => {
      const trackId = 123;
      const bitrates = ['128k', '192k', '320k'];

      bitrates.forEach((bitrate) => {
        const url = getHLSQualityPlaylistURL(trackId, bitrate);
        expect(url).toBe(
          `http://localhost:8080/api/v1/tracks/123/hls/${bitrate}/playlist.m3u8`,
        );
      });
    });

    it('should handle different track IDs', () => {
      const bitrate = '192k';
      const trackIds = [1, 100, 999];

      trackIds.forEach((trackId) => {
        const url = getHLSQualityPlaylistURL(trackId, bitrate);
        expect(url).toBe(
          `http://localhost:8080/api/v1/tracks/${trackId}/hls/${bitrate}/playlist.m3u8`,
        );
      });
    });
  });

  describe('getHLSSegmentURL', () => {
    beforeEach(() => {
      (apiClient.defaults as any).baseURL = 'http://localhost:8080/api/v1';
    });

    it('should generate correct segment URL', () => {
      const trackId = 123;
      const bitrate = '128k';
      const segment = 'segment_000.ts';
      const url = getHLSSegmentURL(trackId, bitrate, segment);
      expect(url).toBe(
        'http://localhost:8080/api/v1/tracks/123/hls/128k/segment_000.ts',
      );
    });

    it('should handle different segment names', () => {
      const trackId = 123;
      const bitrate = '192k';
      const segments = ['segment_000.ts', 'segment_001.ts', 'segment_002.ts'];

      segments.forEach((segment) => {
        const url = getHLSSegmentURL(trackId, bitrate, segment);
        expect(url).toBe(
          `http://localhost:8080/api/v1/tracks/123/hls/${bitrate}/${segment}`,
        );
      });
    });

    it('should handle different bitrates and segments', () => {
      const trackId = 456;
      const combinations = [
        { bitrate: '128k', segment: 'segment_000.ts' },
        { bitrate: '192k', segment: 'segment_001.ts' },
        { bitrate: '320k', segment: 'segment_002.ts' },
      ];

      combinations.forEach(({ bitrate, segment }) => {
        const url = getHLSSegmentURL(trackId, bitrate, segment);
        expect(url).toBe(
          `http://localhost:8080/api/v1/tracks/456/hls/${bitrate}/${segment}`,
        );
      });
    });
  });

  describe('getHLSStreamInfo', () => {
    beforeEach(() => {
      (apiClient.defaults as any).baseURL = 'http://localhost:8080/api/v1';
    });

    it('should fetch HLS stream info successfully', async () => {
      const trackId = 123;
      const mockResponse: HLSStreamInfo = {
        trackId: 123,
        bitrates: [128, 192, 320],
        playlistUrl: 'http://localhost:8080/api/v1/tracks/123/hls/master.m3u8',
      };

      vi.mocked(apiClient.get).mockResolvedValue({
        data: mockResponse,
      } as any);

      const result = await getHLSStreamInfo(trackId);

      expect(apiClient.get).toHaveBeenCalledWith('/tracks/123/hls/info');
      expect(result).toEqual(mockResponse);
      expect(result.trackId).toBe(123);
      expect(result.bitrates).toEqual([128, 192, 320]);
      expect(result.playlistUrl).toBe(
        'http://localhost:8080/api/v1/tracks/123/hls/master.m3u8',
      );
    });

    it('should handle API errors', async () => {
      const trackId = 999;
      const error = new Error('Track not found');

      vi.mocked(apiClient.get).mockRejectedValue(error);

      await expect(getHLSStreamInfo(trackId)).rejects.toThrow(
        'Track not found',
      );
      expect(apiClient.get).toHaveBeenCalledWith('/tracks/999/hls/info');
    });

    it('should handle different track IDs', async () => {
      const trackIds = [1, 100, 999];

      for (const trackId of trackIds) {
        const mockResponse: HLSStreamInfo = {
          trackId,
          bitrates: [128, 192],
          playlistUrl: `http://localhost:8080/api/v1/tracks/${trackId}/hls/master.m3u8`,
        };

        vi.mocked(apiClient.get).mockResolvedValueOnce({
          data: mockResponse,
        } as any);

        const result = await getHLSStreamInfo(trackId);
        expect(result.trackId).toBe(trackId);
        expect(apiClient.get).toHaveBeenCalledWith(
          `/tracks/${trackId}/hls/info`,
        );
      }
    });

    it('should handle empty bitrates array', async () => {
      const trackId = 123;
      const mockResponse: HLSStreamInfo = {
        trackId: 123,
        bitrates: [],
        playlistUrl: 'http://localhost:8080/api/v1/tracks/123/hls/master.m3u8',
      };

      vi.mocked(apiClient.get).mockResolvedValue({
        data: mockResponse,
      } as any);

      const result = await getHLSStreamInfo(trackId);
      expect(result.bitrates).toEqual([]);
    });
  });
});
