/**
 * InApp Sagas Tests
 *
 * Tests for InApp sagas including HTML content create/edit flows
 */

import { call, put } from 'redux-saga/effects';
import * as Api from '../../../services/api';
import {
  inAppTemplateCreate,
  editTemplate,
  getTemplateDetails,
  uploadInAppAsset,
} from '../sagas';
import {
  INAPP_TEMPLATE_CREATE_SUCCESS,
  INAPP_TEMPLATE_CREATE_FAILURE,
  INAPP_EDIT_TEMPLATE_SUCCESS,
  INAPP_EDIT_TEMPLATE_FAILURE,
  GET_INAPP_TEMPLATE_DETAILS_SUCCESS,
  GET_INAPP_TEMPLATE_DETAILS_FAILURE,
  UPLOAD_INAPP_ASSET_SUCCESS,
  UPLOAD_INAPP_ASSET_FAILURE,
} from '../constants';
import { INAPP } from '../../CreativesContainer/constants';

describe('InApp Sagas', () => {
  describe('inAppTemplateCreate', () => {
    const payload = {
      name: 'Test Template',
      versions: {
        base: {
          content: {
            ANDROID: {
              title: 'Android Title',
              message: '<p>Android HTML Content</p>',
              bodyType: 'MODAL',
            },
            IOS: {
              title: 'iOS Title',
              message: '<p>iOS HTML Content</p>',
              bodyType: 'MODAL',
            },
          },
        },
      },
      type: INAPP,
    };

    test('creates template successfully with HTML content', () => {
      const generator = inAppTemplateCreate({
        payload,
        callback: jest.fn(),
      });

      const mockResponse = {
        response: {
          id: 'template-123',
          name: 'Test Template',
        },
        status: {
          code: 201,
        },
      };

      expect(generator.next().value).toEqual(
        call(Api.createChannelWiseTemplate, { channel: INAPP, template: payload })
      );

      expect(generator.next(mockResponse).value).toEqual(
        put({
          type: INAPP_TEMPLATE_CREATE_SUCCESS,
          data: mockResponse.response,
          statusCode: 201,
          errorMsg: undefined,
        })
      );

      const callback = generator.next().value;
      expect(callback).toBeUndefined(); // Callback is called but not yielded

      expect(generator.next().done).toBe(true);
    });

    test('handles API error when creating template', () => {
      const generator = inAppTemplateCreate({
        payload,
        callback: jest.fn(),
      });

      const mockError = {
        response: null,
        status: {
          code: 400,
        },
        message: 'Validation error',
      };

      expect(generator.next().value).toEqual(
        call(Api.createChannelWiseTemplate, { channel: INAPP, template: payload })
      );

      expect(generator.next(mockError).value).toEqual(
        put({
          type: INAPP_TEMPLATE_CREATE_FAILURE,
          error: 'Validation error',
          errorMsg: 'Validation error',
        })
      );

      const callback = generator.next().value;
      expect(callback).toBeUndefined();

      expect(generator.next().done).toBe(true);
    });

    test('handles exception during template creation', () => {
      const generator = inAppTemplateCreate({
        payload,
        callback: jest.fn(),
      });

      const error = new Error('Network error');

      expect(generator.next().value).toEqual(
        call(Api.createChannelWiseTemplate, { channel: INAPP, template: payload })
      );

      expect(generator.throw(error).value).toEqual(
        put({
          type: INAPP_TEMPLATE_CREATE_FAILURE,
          error,
          errorMsg: undefined,
        })
      );

      expect(generator.next().done).toBe(true);
    });
  });

  describe('editTemplate', () => {
    const payload = {
      _id: 'template-123',
      name: 'Updated Template',
      versions: {
        base: {
          content: {
            ANDROID: {
              title: 'Updated Android Title',
              message: '<p>Updated Android HTML</p>',
              bodyType: 'MODAL',
            },
            IOS: {
              title: 'Updated iOS Title',
              message: '<p>Updated iOS HTML</p>',
              bodyType: 'MODAL',
            },
          },
        },
      },
      type: INAPP,
    };

    test('edits template successfully with HTML content', () => {
      const generator = editTemplate({
        payload,
        callback: jest.fn(),
      });

      const mockResponse = {
        response: {
          id: 'template-123',
          name: 'Updated Template',
        },
        status: {
          code: 200,
        },
      };

      expect(generator.next().value).toEqual(
        call(Api.createChannelWiseTemplate, { channel: INAPP, template: payload })
      );

      expect(generator.next(mockResponse).value).toEqual(
        put({
          type: INAPP_EDIT_TEMPLATE_SUCCESS,
          data: mockResponse.response,
          statusCode: 200,
          errorMsg: undefined,
        })
      );

      expect(generator.next().done).toBe(true);
    });

    test('handles API error when editing template', () => {
      const generator = editTemplate({
        payload,
        callback: jest.fn(),
      });

      const mockError = {
        response: null,
        status: {
          code: 404,
        },
        message: 'Template not found',
      };

      expect(generator.next().value).toEqual(
        call(Api.createChannelWiseTemplate, { channel: INAPP, template: payload })
      );

      expect(generator.next(mockError).value).toEqual(
        put({
          type: INAPP_EDIT_TEMPLATE_FAILURE,
          error: 'Template not found',
          errorMsg: 'Template not found',
        })
      );

      expect(generator.next().done).toBe(true);
    });
  });

  describe('getTemplateDetails', () => {
    test('fetches template details successfully', () => {
      const generator = getTemplateDetails({
        id: 'template-123',
        callback: jest.fn(),
      });

      const mockResponse = {
        response: {
          id: 'template-123',
          name: 'Test Template',
          versions: {
            base: {
              content: {
                ANDROID: {
                  title: 'Android Title',
                  message: '<p>Android HTML Content</p>',
                },
                IOS: {
                  title: 'iOS Title',
                  message: '<p>iOS HTML Content</p>',
                },
              },
            },
          },
        },
      };

      expect(generator.next().value).toEqual(
        call(Api.getTemplateDetails, {
          id: 'template-123',
          channel: INAPP,
        })
      );

      expect(generator.next(mockResponse).value).toEqual(
        put({
          type: GET_INAPP_TEMPLATE_DETAILS_SUCCESS,
          data: mockResponse.response,
        })
      );

      expect(generator.next().done).toBe(true);
    });

    test('handles error when fetching template details', () => {
      const generator = getTemplateDetails({
        id: 'template-123',
        callback: jest.fn(),
      });

      const error = new Error('Not found');

      expect(generator.next().value).toEqual(
        call(Api.getTemplateDetails, {
          id: 'template-123',
          channel: INAPP,
        })
      );

      expect(generator.throw(error).value).toEqual(
        put({
          type: GET_INAPP_TEMPLATE_DETAILS_FAILURE,
          error,
        })
      );

      expect(generator.next().done).toBe(true);
    });
  });

  describe('uploadInAppAsset', () => {
    test('uploads asset successfully', () => {
      const params = {
        file: new File(['test'], 'test.jpg'),
        assetType: 'image',
        fileParams: {},
        templateType: INAPP,
      };

      const generator = uploadInAppAsset(params);

      const mockResponse = {
        response: {
          asset: {
            url: 'https://cdn.example.com/image.jpg',
            id: 'asset-123',
          },
        },
        status: {
          code: 200,
        },
      };

      expect(generator.next().value).toEqual(
        call(Api.uploadFile, params)
      );

      expect(generator.next(mockResponse).value).toEqual(
        put({
          type: UPLOAD_INAPP_ASSET_SUCCESS,
          data: mockResponse.response.asset,
          statusCode: 200,
          templateType: INAPP,
        })
      );

      expect(generator.next().done).toBe(true);
    });

    test('handles error when uploading asset', () => {
      const params = {
        file: new File(['test'], 'test.jpg'),
        assetType: 'image',
        fileParams: {},
        templateType: INAPP,
      };

      const generator = uploadInAppAsset(params);

      const error = new Error('Upload failed');

      expect(generator.next().value).toEqual(
        call(Api.uploadFile, params)
      );

      expect(generator.throw(error).value).toEqual(
        put({
          type: UPLOAD_INAPP_ASSET_FAILURE,
          error,
        })
      );

      expect(generator.next().done).toBe(true);
    });
  });
});

