
import {
  transformTemplateConfigWithMediaDetails,
  convertMediaTagsToUrls,
  convertUrlsToMediaTags,
  TRANSFORM_DIRECTION,
  MEDIA_CONTENT_TYPE,
} from '../transformTemplateConfig';
import { getMediaDetails } from '../../services/api';
import { WHATSAPP } from '../../v2Containers/Whatsapp/constants';

jest.mock('../../services/api', () => ({
  getMediaDetails: jest.fn(),
}));

const mockUrlToIdMapping = {
  'http://example.com/image1.png': 'id1',
  'http://example.com/video.mp4': 'id2',
};

const mockIdToUrlMapping = {
  id1: 'http://example.com/image1.png',
  id2: 'http://example.com/video.mp4',
};

describe('transformTemplateConfig', () => {
  beforeEach(() => {
    getMediaDetails.mockClear();
    // eslint-disable-next-line no-console
    console.warn = jest.fn();
    // eslint-disable-next-line no-console
    console.error = jest.fn();
    // eslint-disable-next-line no-console
    console.log = jest.fn();
  });

  describe('transformTemplateConfigWithMediaDetails', () => {
    it('should return original config for non-whatsapp channel', async () => {
      const templateConfig = { cards: [{ media: { url: 'some_url' } }] };
      const result = await transformTemplateConfigWithMediaDetails(
        templateConfig,
        'SMS',
        'media123',
      );
      expect(result).toEqual(templateConfig);
      expect(getMediaDetails).not.toHaveBeenCalled();
    });

    it('should return original config if no cards are present', async () => {
      const templateConfig = { cards: [] };
      const result = await transformTemplateConfigWithMediaDetails(
        templateConfig,
        WHATSAPP,
        'media123',
      );
      expect(result).toEqual(templateConfig);
    });

    it('should return original config and warn if mediaDetailsId is missing', async () => {
      const templateConfig = { cards: [{ media: { url: 'some_url' } }] };
      const result = await transformTemplateConfigWithMediaDetails(
        templateConfig,
        WHATSAPP,
        null,
      );
      expect(result).toEqual(templateConfig);
      // eslint-disable-next-line no-console
      expect(console.warn).toHaveBeenCalledWith(
        'mediaDetailsId is required for transformTemplateConfigWithMediaDetails',
      );
    });

    it('should handle forward transformation (URL to Tag)', async () => {
      getMediaDetails.mockResolvedValue({ response: mockUrlToIdMapping });
      const templateConfig = {
        cards: [
          { media: { url: 'http://example.com/image1.png' } },
          { media: { url: 'http://example.com/video.mp4' } },
        ],
      };

      const result = await transformTemplateConfigWithMediaDetails(
        templateConfig,
        WHATSAPP,
        'media123',
      );

      expect(result.cards[0].media.url).toBe('{{media_content(id1)}}');
      expect(result.cards[1].media.url).toBe('{{media_content(id2)}}');
    });

    it('should handle reverse transformation (Tag to URL)', async () => {
      getMediaDetails.mockResolvedValue({ response: mockUrlToIdMapping });
      const templateConfig = {
        cards: [
          { media: { url: '{{media_content(id1)}}' } },
          { media: { url: '{{media_content(id2)}}' } },
        ],
      };

      const result = await transformTemplateConfigWithMediaDetails(
        templateConfig,
        WHATSAPP,
        'media123',
      );

      expect(result.cards[0].media.url).toBe(mockIdToUrlMapping.id1);
      expect(result.cards[1].media.url).toBe(mockIdToUrlMapping.id2);
    });

    it('should handle smart transformation for mixed content', async () => {
      getMediaDetails.mockResolvedValue({ response: mockUrlToIdMapping });
      const templateConfig = {
        cards: [
          { media: { url: 'http://example.com/image1.png' } }, // URL
          { media: { url: '{{media_content(id2)}}' } }, // Tag
        ],
      };

      const result = await transformTemplateConfigWithMediaDetails(
        templateConfig,
        WHATSAPP,
        'media123',
      );

      expect(result.cards[0].media.url).toBe('{{media_content(id1)}}');
      expect(result.cards[1].media.url).toBe(mockIdToUrlMapping.id2);
    });

    it('should force forward transformation', async () => {
        getMediaDetails.mockResolvedValue({ response: mockUrlToIdMapping });
        const templateConfig = {
          cards: [{ media: { url: 'http://example.com/image1.png' } }],
        };

        const result = await transformTemplateConfigWithMediaDetails(
          templateConfig,
          WHATSAPP,
          'media123',
          { forceDirection: TRANSFORM_DIRECTION.FORWARD },
        );

        expect(result.cards[0].media.url).toBe('{{media_content(id1)}}');
    });

    it('should force reverse transformation', async () => {
        getMediaDetails.mockResolvedValue({ response: mockUrlToIdMapping });
        const templateConfig = {
          cards: [{ media: { url: '{{media_content(id1)}}' } }],
        };

        const result = await transformTemplateConfigWithMediaDetails(
          templateConfig,
          WHATSAPP,
          'media123',
          { forceDirection: TRANSFORM_DIRECTION.REVERSE },
        );

        expect(result.cards[0].media.url).toBe(mockIdToUrlMapping.id1);
    });

    it('should handle API failure gracefully', async () => {
        const error = new Error('API Error');
        getMediaDetails.mockRejectedValue(error);
        const templateConfig = {
            cards: [{ media: { url: 'http://example.com/image1.png' } }],
        };

        const result = await transformTemplateConfigWithMediaDetails(
            templateConfig,
            WHATSAPP,
            'media123',
        );

        // Fallback logic does not transform
        expect(result.cards[0].media.url).toBe('http://example.com/image1.png');
        // eslint-disable-next-line no-console
        expect(console.error).toHaveBeenCalledWith(
            'Failed to fetch media details for transformation:',
            error,
        );
    });

    it('should warn when no media mapping is found for a URL', async () => {
        getMediaDetails.mockResolvedValue({ response: mockUrlToIdMapping });
        const templateConfig = {
          cards: [{ media: { url: 'http://example.com/unmapped.jpg' } }],
        };

        await transformTemplateConfigWithMediaDetails(
          templateConfig,
          WHATSAPP,
          'media123',
        );

        // eslint-disable-next-line no-console
        expect(console.warn).toHaveBeenCalledWith(
          'No media detail ID found for URL: http://example.com/unmapped.jpg',
        );
    });

    it('should warn when no URL is found for a media ID', async () => {
        getMediaDetails.mockResolvedValue({ response: mockUrlToIdMapping });
        const templateConfig = {
          cards: [{ media: { url: '{{media_content(unmapped_id)}}' } }],
        };

        await transformTemplateConfigWithMediaDetails(
          templateConfig,
          WHATSAPP,
          'media123',
        );

        // eslint-disable-next-line no-console
        expect(console.warn).toHaveBeenCalledWith(
          'No URL found for media ID: unmapped_id',
        );
    });

    it('should handle cards with non-string media url gracefully', async () => {
      getMediaDetails.mockResolvedValue({ response: mockUrlToIdMapping });
      const templateConfig = {
        cards: [
          { media: { url: 123 } },
        ],
      };
      const result = await transformTemplateConfigWithMediaDetails(templateConfig, WHATSAPP, 'media123');
      expect(result.cards[0].media.url).toBe(123);
      expect(console.warn).toHaveBeenCalledWith('No media detail ID found for URL: 123');
    });

    it('should use fallback to extract media id when API fails for forced forward transform', async () => {
      getMediaDetails.mockRejectedValue(new Error('API Error'));
      const templateConfig = {
        cards: [{ media: { url: '{{media_content(fallback_id)}}' } }],
      };
      const result = await transformTemplateConfigWithMediaDetails(
        templateConfig,
        WHATSAPP,
        'media123',
        { forceDirection: TRANSFORM_DIRECTION.FORWARD },
      );
      expect(result.cards[0].media.url).toBe('{{media_content(fallback_id)}}');
      expect(console.error).toHaveBeenCalledWith(
        'Failed to fetch media details for transformation:',
        expect.any(Error),
      );
    });

    it('should return original config if media details mapping is empty', async () => {
      getMediaDetails.mockResolvedValue({ response: {} });
      const templateConfig = {
        cards: [{ media: { url: 'http://example.com/image1.png' } }],
      };
      const result = await transformTemplateConfigWithMediaDetails(
        templateConfig,
        WHATSAPP,
        'media123',
      );
      expect(result).toEqual(templateConfig);
      expect(console.warn).toHaveBeenCalledWith('No media details mapping found in API response');
    });
  });

  describe('convenience wrappers', () => {
    it('convertUrlsToMediaTags should force forward direction', async () => {
        getMediaDetails.mockResolvedValue({ response: mockUrlToIdMapping });
        const templateConfig = {
          cards: [{ media: { url: 'http://example.com/image1.png' } }],
        };

        const result = await convertUrlsToMediaTags(templateConfig, WHATSAPP, 'media123');

        expect(getMediaDetails).toHaveBeenCalledWith({ id: 'media123' });
        expect(result.cards[0].media.url).toBe('{{media_content(id1)}}');
    });

    it('convertMediaTagsToUrls should force reverse direction', async () => {
        getMediaDetails.mockResolvedValue({ response: mockUrlToIdMapping });
        const templateConfig = {
          cards: [{ media: { url: '{{media_content(id1)}}' } }],
        };

        const result = await convertMediaTagsToUrls(templateConfig, WHATSAPP, 'media123');

        expect(getMediaDetails).toHaveBeenCalledWith({ id: 'media123' });
        expect(result.cards[0].media.url).toBe(mockIdToUrlMapping.id1);
    });
  });
});
