import _, { isEmpty, find } from 'lodash';
import { renderHook, waitFor, act as reactAct } from '@testing-library/react';
import useEmailWrapper from '../hooks/useEmailWrapper';
import { EmailWrapperMockData } from '../mockdata/mockdata';
import { EMAIL_CREATE_MODES, STEPS } from '../constants';
import { gtmPush } from '../../../utils/gtmTrackers';

// Mock dependencies
jest.mock('lodash', () => ({
  ...jest.requireActual('lodash'),
  isEmpty: jest.fn().mockImplementation((val) => {
    if (val === null || val === undefined) return true;
    if (typeof val === 'object') return Object.keys(val).length === 0;
    if (typeof val === 'string') return val.trim().length === 0;
    return !val;
  }),
  find: jest.fn(),
}));

let mockCapNotificationError;
jest.mock('@capillarytech/cap-ui-library/CapNotification', () => {
  mockCapNotificationError = jest.fn();
  return {
    error: mockCapNotificationError,
  };
});

jest.mock('../../../utils/gtmTrackers', () => ({
  gtmPush: jest.fn(),
}));

jest.mock('../../../utils/common', () => ({
  hasSupportCKEditor: jest.fn(() => true), // Default to legacy flow
}));

const mockStopTimer = jest.fn();

jest.mock('@capillarytech/cap-ui-utils', () => ({
  ...jest.requireActual('@capillarytech/cap-ui-utils'),
  GA: {
    timeTracker: {
      startTimer: jest.fn(),
      stopTimer: jest.fn(),
    },
  },
}));

describe('useEmailWrapper', () => {
  let mockProps;

  beforeEach(() => {
    jest.clearAllMocks();
    isEmpty.mockClear();
    find.mockClear();
    mockCapNotificationError.mockClear();
    gtmPush.mockClear();
    mockStopTimer.mockClear();

    isEmpty.mockImplementation((val) => {
      if (val === null || val === undefined) return true;
      if (typeof val === 'object') return Object.keys(val).length === 0;
      if (typeof val === 'string') return val.trim().length === 0;
      return !val;
    });

    mockProps = {
      ...EmailWrapperMockData,
      intl: { formatMessage: jest.fn((msg) => msg.defaultMessage || msg.id || '') },
      onEmailModeChange: jest.fn(),
      showNextStep: jest.fn(),
      onResetStep: jest.fn(),
      onEnterTemplateName: jest.fn(),
      onRemoveTemplateName: jest.fn(),
      templatesActions: {
        resetTemplateData: jest.fn(),
        getDefaultBeeTemplates: jest.fn(),
        handleZipUpload: jest.fn(),
        handleHtmlUpload: jest.fn(),
        setEdmTemplate: jest.fn(),
        setBEETemplate: jest.fn(),
      },
      emailActions: {
        getCmsAccounts: jest.fn(),
        getTemplateDetails: jest.fn(),
        getCmsSetting: jest.fn(),
        clearStoreValues: jest.fn(),
      },
      EmailLayout: null,
      CmsTemplates: null,
      SelectedEdmDefaultTemplate: null,
      isUploading: false,
      getCmsTemplatesInProgress: false,
      step: STEPS.MODE_SELECTION,
      emailCreateMode: '',
      setIsLoadingContent: jest.fn(),
      isGetFormData: false,
      getFormdata: jest.fn(),
      type: 'someType',
      isFullMode: false,
      cap: { currentOrgDetails: { id: 'org1' } },
      showTemplateName: true,
      showLiquidErrorInFooter: false,
      onValidationFail: jest.fn(),
      forwardedTags: [],
      selectedOfferDetails: null,
      onPreviewContentClicked: jest.fn(),
      onTestContentClicked: jest.fn(),
      editor: null,
      moduleType: '',
      eventContextTags: [],
      waitEventContextTags: {},
      isLoyaltyModule: false,
      cmsTemplatesLoader: false,
      currentOrgDetails: { id: 'org1' },
    };
  });

  it('is a function', () => {
    expect(typeof useEmailWrapper).toBe('function');
  });

  it('initializes with correct default state', () => {
    const { result } = renderHook(() => useEmailWrapper(mockProps));

    expect(result.current.templateName).toBeDefined();
    expect(result.current.modes).toBeDefined();
    expect(result.current.onTemplateNameChange).toBeInstanceOf(Function);
  });

  it('passes waitEventContextTags through emailProps', () => {
    const waitMap = { block1: { eventName: 'E', blockName: 'B', tags: [] } };
    const { result } = renderHook(() =>
      useEmailWrapper({ ...mockProps, waitEventContextTags: waitMap }),
    );
    expect(result.current.emailProps.waitEventContextTags).toEqual(waitMap);
  });

  it('handles template name change correctly', () => {
    const { result } = renderHook(() => useEmailWrapper(mockProps));

    reactAct(() => {
      result.current.onTemplateNameChange({ target: { value: 'New Template' } });
    });

    expect(result.current.templateName).toBe('New Template');
    expect(result.current.isTemplateNameEmpty).toBe(false);
    expect(mockProps.onEnterTemplateName).toHaveBeenCalled();
  });

  it('detects empty template name correctly', () => {
    const { result } = renderHook(() => useEmailWrapper(mockProps));

    reactAct(() => {
      result.current.onTemplateNameChange({ target: { value: '' } });
    });

    expect(result.current.templateName).toBe('');
    expect(result.current.isTemplateNameEmpty).toBe(true);
    expect(mockProps.onRemoveTemplateName).toHaveBeenCalled();
  });

  it('handles mode change correctly', () => {
    const { result } = renderHook(() => useEmailWrapper(mockProps));

    reactAct(() => {
      result.current.onChange({ target: { value: EMAIL_CREATE_MODES.UPLOAD } });
    });

    // onEmailModeChange is called with (mappedValue, value) - both are UPLOAD in this case
    expect(mockProps.onEmailModeChange).toHaveBeenCalledWith(EMAIL_CREATE_MODES.UPLOAD, EMAIL_CREATE_MODES.UPLOAD);
  });

  it('handles zip file upload correctly and calls success callbacks', () => {
    mockProps.templatesActions.handleZipUpload.mockImplementation((file, onSuccess, onError) => {
      onSuccess();
    });

    const { result } = renderHook(() => useEmailWrapper({
      ...mockProps,
      isUploading: false,
    }));

    const mockFile = {
      name: 'test.zip',
      size: 1024 * 1024,
      originFileObj: new Blob(['test data'], { type: 'application/zip' }),
    };

    reactAct(() => {
      result.current.useFileUpload({ file: mockFile });
    });

    expect(mockProps.templatesActions.handleZipUpload).toHaveBeenCalledWith(
      mockFile.originFileObj,
      expect.any(Function),
      expect.any(Function)
    );

    expect(gtmPush).toHaveBeenCalled();
    // User must enter template name and click Continue in footer; no auto-advance after upload
    expect(mockProps.showNextStep).not.toHaveBeenCalled();
    expect(mockCapNotificationError).not.toHaveBeenCalled();
    expect(result.current.modeContent).toEqual({ file: mockFile });
  });

  it('handles zip file upload error correctly', () => {
    mockProps.templatesActions.handleZipUpload.mockImplementation((file, onSuccess, onError) => {
      onError();
    });

    const { result } = renderHook(() => useEmailWrapper({
      ...mockProps,
      isUploading: false,
    }));

    const mockFile = {
      name: 'test.zip',
      size: 1024 * 1024,
      originFileObj: new Blob(['test data'], { type: 'application/zip' }),
    };

    reactAct(() => {
      result.current.useFileUpload({ file: mockFile });
    });

    expect(mockProps.templatesActions.handleZipUpload).toHaveBeenCalled();
    expect(mockCapNotificationError).toHaveBeenCalled();
    expect(mockProps.showNextStep).not.toHaveBeenCalled();
  });

  it('handles HTML file upload correctly', async () => {
    const mockHtmlContent = '<html><body>Test</body></html>';
    const mockFile = {
      name: 'test.html',
      size: 1024,
      originFileObj: new Blob([mockHtmlContent], { type: 'text/html' }),
    };

    const mockReader = {
      onload: null,
      onerror: null,
      readAsText: jest.fn(function () {
        this.result = mockHtmlContent;
        if (this.onload) {
          this.onload();
        }
      }),
      result: '',
    };
    const fileReaderSpy = jest.spyOn(global, 'FileReader').mockImplementation(() => mockReader);

    const { result } = renderHook(() => useEmailWrapper({
      ...mockProps,
      isUploading: false,
    }));

    reactAct(() => {
      result.current.useFileUpload({ file: mockFile });
    });

    await waitFor(() => {
      expect(mockReader.readAsText).toHaveBeenCalledWith(mockFile.originFileObj);
      expect(mockProps.templatesActions.handleHtmlUpload).toHaveBeenCalledWith(mockHtmlContent);
    });

    expect(result.current.modeContent).toEqual({ file: mockFile });
    expect(mockCapNotificationError).not.toHaveBeenCalled();

    fileReaderSpy.mockRestore();
  });

  it('shows error for invalid file type during upload', () => {
    const { result } = renderHook(() => useEmailWrapper({
      ...mockProps,
      isUploading: false,
    }));

    const mockFile = {
      name: 'test.txt',
      size: 1024,
      originFileObj: new Blob(['test data'], { type: 'text/plain' }),
    };

    reactAct(() => {
      result.current.useFileUpload({ file: mockFile });
    });

    expect(mockCapNotificationError).toHaveBeenCalledWith(expect.objectContaining({
      key: "email-upload-error",
    }));
    expect(mockProps.templatesActions.handleZipUpload).not.toHaveBeenCalled();
    expect(mockProps.templatesActions.handleHtmlUpload).not.toHaveBeenCalled();
  });

  it('shows error for oversized file during upload', () => {
    const { result } = renderHook(() => useEmailWrapper({
      ...mockProps,
      isUploading: false,
    }));

    const mockFile = {
      name: 'large_file.zip',
      size: 6 * 1024 * 1024,
      originFileObj: new Blob(['large data'], { type: 'application/zip' }),
    };

    reactAct(() => {
      result.current.useFileUpload({ file: mockFile });
    });

    expect(mockCapNotificationError).toHaveBeenCalledWith(expect.objectContaining({
      key: "email-upload-error",
    }));
    expect(mockProps.templatesActions.handleZipUpload).not.toHaveBeenCalled();
  });

  it('shows error if no file or originFileObj is provided for upload', () => {
    const { result } = renderHook(() => useEmailWrapper({
      ...mockProps,
      isUploading: false,
    }));

    reactAct(() => {
      result.current.useFileUpload({ file: null });
    });
    expect(mockCapNotificationError).toHaveBeenCalledTimes(1);
    expect(mockCapNotificationError).toHaveBeenCalledWith(expect.objectContaining({ key: "email-upload-error" }));

    mockCapNotificationError.mockClear();
    reactAct(() => {
      result.current.useFileUpload({ file: { name: 'test.zip', size: 100 } });
    });
    expect(mockCapNotificationError).toHaveBeenCalledTimes(1);
    expect(mockCapNotificationError).toHaveBeenCalledWith(expect.objectContaining({ key: "email-upload-error" }));

    expect(mockProps.templatesActions.handleZipUpload).not.toHaveBeenCalled();
    expect(mockProps.templatesActions.handleHtmlUpload).not.toHaveBeenCalled();
  });

  it('calls showNextStep when useEditor is invoked', () => {
    const { result } = renderHook(() => useEmailWrapper(mockProps));
    const templateId = 'template123';

    reactAct(() => {
      result.current.cmsTemplatesProps.handleEdmDefaultTemplateSelection(templateId);
    });

    expect(result.current.modeContent).toEqual({ id: templateId });
    expect(mockProps.showNextStep).toHaveBeenCalled();
  });

  it('calls getDefaultBeeTemplates in useEffect when in EDITOR mode, TEMPLATE_SELECTION step, and no templates', () => {
    // Ensure hasSupportCKEditor returns true for legacy flow
    const { hasSupportCKEditor } = require('../../../utils/common');
    hasSupportCKEditor.mockReturnValue(true);

    renderHook(() => useEmailWrapper({
      ...mockProps,
      step: STEPS.TEMPLATE_SELECTION,
      emailCreateMode: EMAIL_CREATE_MODES.EDITOR,
      CmsTemplates: null,
      getCmsTemplatesInProgress: false,
    }));

    expect(mockProps.templatesActions.getDefaultBeeTemplates).toHaveBeenCalledTimes(1);
  });

  it('does NOT call getDefaultBeeTemplates if templates already exist or are loading', () => {
    renderHook(() => useEmailWrapper({
      ...mockProps,
      step: STEPS.TEMPLATE_SELECTION,
      emailCreateMode: EMAIL_CREATE_MODES.EDITOR,
      CmsTemplates: [{ _id: '1', name: 'Test Template' }],
      getCmsTemplatesInProgress: false,
    }));
    expect(mockProps.templatesActions.getDefaultBeeTemplates).not.toHaveBeenCalled();

    renderHook(() => useEmailWrapper({
      ...mockProps,
      step: STEPS.TEMPLATE_SELECTION,
      emailCreateMode: EMAIL_CREATE_MODES.EDITOR,
      CmsTemplates: null,
      getCmsTemplatesInProgress: true,
    }));
    expect(mockProps.templatesActions.getDefaultBeeTemplates).not.toHaveBeenCalled();
  });

  it('calls setEdmTemplate/setBEETemplate in useEffect when in EDITOR mode and CREATE_TEMPLATE_CONTENT step', async () => {
    // Ensure hasSupportCKEditor returns true for legacy flow
    const { hasSupportCKEditor } = require('../../../utils/common');
    hasSupportCKEditor.mockReturnValue(true);
    // 1. Setup
    const templateId = 'editorTemplate456';
    const mockTemplateData = { _id: templateId, name: 'Selected Editor Template' };

    // Ensure mocks are clean from previous tests
    find.mockClear();
    isEmpty.mockClear();
    mockProps.templatesActions.setEdmTemplate.mockClear();
    mockProps.templatesActions.setBEETemplate.mockClear();
    mockProps.showNextStep.mockClear();

    // 2. Mock find (this will be called by the *internal* handleEdmDefaultTemplateSelection)
    find.mockImplementation((array, criteria) => {
      // console.log('DEBUG: find called with', JSON.stringify(array), JSON.stringify(criteria)); // Optional debug
      if (array && criteria && criteria._id === templateId && array[0]?._id === templateId) {
        return mockTemplateData;
      }
      return null;
    });

    // 3. Initial Render (Template Selection Step)
    const initialProps = {
      ...mockProps,
      step: STEPS.TEMPLATE_SELECTION,
      emailCreateMode: EMAIL_CREATE_MODES.EDITOR,
      CmsTemplates: [mockTemplateData],
      SelectedEdmDefaultTemplate: null,
      // selectedCreateMode is initially '' from hook's useState
    };
    const { result, rerender } = renderHook((props) => useEmailWrapper(props), {
      initialProps,
    });

    // 4. Simulate user selecting a template ID via the exposed callback (useEditor)
    reactAct(() => {
      // This maps to useEditor which calls setModeContent and showNextStep
      result.current.cmsTemplatesProps.handleEdmDefaultTemplateSelection(templateId);
    });
    // Verify internal state updated and mock called
    expect(result.current.modeContent).toEqual({ id: templateId }); // State updated
    expect(mockProps.showNextStep).toHaveBeenCalledTimes(1); // User action effect

    // Clear mocks after user action to isolate effect calls
    mockProps.templatesActions.setEdmTemplate.mockClear();
    mockProps.templatesActions.setBEETemplate.mockClear();

    // 5. Rerender with step changed to CREATE_TEMPLATE_CONTENT
    const createContentProps = {
      ...initialProps, // Base props
      step: STEPS.CREATE_TEMPLATE_CONTENT, // *** Change step ***
      SelectedEdmDefaultTemplate: null, // *** Ensure this is null ***
      // The internal state `modeContent = { id: templateId }` persists
      // The internal state `selectedCreateMode = ''` also persists (not changed yet)
    };

    // Mock isEmpty just before rerender for the specific check inside the effect
    isEmpty.mockImplementation((val) => {
      // console.log('DEBUG: isEmpty called with', JSON.stringify(val)); // Optional debug
      // Return true ONLY for the 'SelectedEdmDefaultTemplate' check (which is null)
      if (val === null) return true;
      // Provide a fallback for other potential isEmpty calls if needed
      if (typeof val === 'object' && !val) return true;
      if (typeof val === 'object' && Object.keys(val).length === 0) return true;
      if (typeof val === 'string' && val.trim().length === 0) return true;
      return !val;
    });

    rerender(createContentProps);

    // 6. Wait for effects triggered by the rerender
    await reactAct(async () => {
      // Allow React to process the rerender and run effects
      await new Promise((resolve) => setTimeout(resolve, 10));
    });

    // Assert that the template setting actions were called as a result of the effect
    // Note: The effect may run multiple times in React 18+ StrictMode or due to dependency changes
    // We verify that it was called at least once with the correct data after clearing mocks
    const setEdmTemplateCalls = mockProps.templatesActions.setEdmTemplate.mock.calls;
    const setBEETemplateCalls = mockProps.templatesActions.setBEETemplate.mock.calls;
    
    // The effect should call handleEdmDefaultTemplateSelection, which calls both functions
    // We expect at least 1 call each after clearing mocks (the effect call)
    expect(setEdmTemplateCalls.length).toBeGreaterThanOrEqual(1);
    expect(setBEETemplateCalls.length).toBeGreaterThanOrEqual(1);
    
    // Verify the first call after clearing was with the correct data
    expect(setEdmTemplateCalls[0]).toEqual([mockTemplateData]);
    expect(setBEETemplateCalls[0]).toEqual([mockTemplateData]);
    
    // If there are multiple calls (due to effect running twice), verify all are correct
    if (setEdmTemplateCalls.length > 1) {
      setEdmTemplateCalls.forEach((call) => {
        expect(call).toEqual([mockTemplateData]);
      });
    }
    if (setBEETemplateCalls.length > 1) {
      setBEETemplateCalls.forEach((call) => {
        expect(call).toEqual([mockTemplateData]);
      });
    }
  });

  it('sets selectedCreateMode in useEffect when in UPLOAD mode and CREATE_TEMPLATE_CONTENT step with EmailLayout', async () => {
    const initialRenderProps = {
      ...mockProps,
      step: STEPS.MODE_SELECTION,
      emailCreateMode: EMAIL_CREATE_MODES.UPLOAD,
      EmailLayout: null,
    };

    const { result, rerender } = renderHook((props) => useEmailWrapper(props), {
      initialProps: initialRenderProps,
    });

    const rerenderProps = {
      ...mockProps,
      step: STEPS.CREATE_TEMPLATE_CONTENT,
      emailCreateMode: EMAIL_CREATE_MODES.UPLOAD,
      EmailLayout: { html: '<p>Test Layout</p>' },
    };

    // Reset isEmpty to default before setting the specific mock for the effect
    isEmpty.mockImplementation((val) => {
      if (val === null || val === undefined) return true;
      if (typeof val === 'object') return Object.keys(val).length === 0;
      if (typeof val === 'string') return val.trim().length === 0;
      return !val;
    });
    // Mock isEmpty specifically for the EmailLayout check inside the useEffect
    isEmpty.mockImplementationOnce(() => false); // Mock !isEmpty(EmailLayout) to be true

    rerender(rerenderProps);

    // Wait for the effect to run, set selectedCreateMode, and isShowEmailCreate to update
    await waitFor(() => {
      expect(result.current.isShowEmailCreate).toBe(true);
    });

    // Restore default isEmpty behavior after the specific mock is used
    isEmpty.mockImplementation((val) => {
      if (val === null || val === undefined) return true;
      if (typeof val === 'object') return Object.keys(val).length === 0;
      if (typeof val === 'string') return val.trim().length === 0;
      return !val;
    });
    isEmpty.mockClear(); // Clear any remaining mock state if needed

    expect(mockProps.templatesActions.setEdmTemplate).not.toHaveBeenCalled();
    expect(mockProps.templatesActions.setBEETemplate).not.toHaveBeenCalled();
  });

  it('calls cleanup functions on unmount', () => {
    const { unmount } = renderHook(() => useEmailWrapper(mockProps));

    unmount();

    expect(mockProps.onResetStep).toHaveBeenCalled();
    expect(mockProps.templatesActions.resetTemplateData).toHaveBeenCalled();
  });

  it('correctly computes isShowEmailCreate based on state transitions', async () => {
    // --- Case 1: Initial state -> false ---
    const initialPropsCase1 = {
      ...mockProps,
      step: STEPS.MODE_SELECTION,
      emailCreateMode: '',
      EmailLayout: null,
      SelectedEdmDefaultTemplate: null,
    };
    // Mock isEmpty for initial render checks if needed (though selectedCreateMode is the main driver)
    isEmpty.mockReturnValue(true); // General mock for empty things

    const { result, rerender } = renderHook((props) => useEmailWrapper(props), {
      initialProps: initialPropsCase1,
    });
    expect(result.current.isShowEmailCreate).toBe(false);
    isEmpty.mockClear(); // Clear general mock

    // --- Case 2: UPLOAD mode selected, Layout available -> true ---
    const uploadProps = {
      ...mockProps,
      step: STEPS.CREATE_TEMPLATE_CONTENT,
      emailCreateMode: EMAIL_CREATE_MODES.UPLOAD,
      EmailLayout: { html: '<p>Test</p>' }, // Layout is present
      SelectedEdmDefaultTemplate: null,
    };

    // Reset isEmpty to default before setting the specific mock for the effect
    isEmpty.mockImplementation((val) => {
      if (val === null || val === undefined) return true;
      if (typeof val === 'object') return Object.keys(val).length === 0;
      if (typeof val === 'string') return val.trim().length === 0;
      return !val;
    });
    // Mock isEmpty specifically for the EmailLayout check inside the useEffect
    isEmpty.mockImplementationOnce(() => false); // Mock !isEmpty(EmailLayout) to be true

    rerender(uploadProps);

    // Wait for the effect to run, set selectedCreateMode, and isShowEmailCreate to update
    await waitFor(() => {
      expect(result.current.isShowEmailCreate).toBe(true);
    });

    // Restore default isEmpty behavior after the specific mock is used
    isEmpty.mockImplementation((val) => {
      if (val === null || val === undefined) return true;
      if (typeof val === 'object') return Object.keys(val).length === 0;
      if (typeof val === 'string') return val.trim().length === 0;
      return !val;
    });
    isEmpty.mockClear(); // Clear any remaining mock state if needed

    // --- Case 3: EDITOR mode selected, Template becomes available -> true (via effect) ---
    const templateId = 't1';
    const mockTemplate = { _id: templateId };
    find.mockReturnValue(mockTemplate); // Ensure find is mocked for this case

    const editorPropsInitial = {
      ...mockProps,
      step: STEPS.TEMPLATE_SELECTION,
      emailCreateMode: EMAIL_CREATE_MODES.EDITOR,
      CmsTemplates: [mockTemplate],
      SelectedEdmDefaultTemplate: null,
    };
    rerender(editorPropsInitial);

    // Simulate selecting the template via the exposed handler
    reactAct(() => {
      result.current.cmsTemplatesProps.handleEdmDefaultTemplateSelection(templateId);
    });
    // Verify modeContent was updated internally by the act above
    expect(result.current.modeContent).toEqual({ id: templateId });

    const editorPropsFinal = {
      ...mockProps, // Use fresh props base
      step: STEPS.CREATE_TEMPLATE_CONTENT, // Move to the create step
      emailCreateMode: EMAIL_CREATE_MODES.EDITOR,
      CmsTemplates: [mockTemplate],
      SelectedEdmDefaultTemplate: null, // Template not yet selected in props
      // modeContent state ({id: templateId}) should persist internally from the reactAct call
    };

    // Mock isEmpty specifically for the check within the useEffect triggered by rerender
    // It should return true for SelectedEdmDefaultTemplate to proceed
    isEmpty.mockImplementation((arg) => arg === null || arg === undefined || Object.keys(arg).length === 0); // General implementation first
    isEmpty.mockImplementationOnce(() => true); // Mock the specific check for SelectedEdmDefaultTemplate

    rerender(editorPropsFinal);

    // Cleanup mocks if necessary for subsequent tests (though beforeEach should handle)
    find.mockClear();
    isEmpty.mockClear();
  });

  describe('New Flow (hasSupportCKEditor = false) - Editor Type Determination', () => {
    let newFlowMockProps;
    let mockEmailActions;

    beforeEach(() => {
      const { hasSupportCKEditor } = require('../../../utils/common');
      hasSupportCKEditor.mockReturnValue(false); // New flow

      mockEmailActions = {
        getTemplateDetails: jest.fn(),
        getCmsAccounts: jest.fn(),
        clearStoreValues: jest.fn(),
      };

      newFlowMockProps = {
        ...mockProps,
        emailActions: mockEmailActions,
        Email: {
          templateDetails: null,
          BEETemplate: null,
          getTemplateDetailsInProgress: false,
          isBeeEnabled: true,
        },
        location: {
          pathname: '/email/create',
          query: {},
        },
        params: {},
        templateData: null,
      };
    });

    describe('Create Flow', () => {
      it('should set HTML editor when HTML_EDITOR mode is selected', async () => {
        const { result } = renderHook((props) => useEmailWrapper(props), {
          initialProps: newFlowMockProps,
        });

        // Select HTML Editor mode
        reactAct(() => {
          result.current.onChange({ target: { value: EMAIL_CREATE_MODES.HTML_EDITOR } });
        });

        await waitFor(() => {
          const emailProps = result.current.emailProps;
          expect(emailProps.editor).toBe('HTML');
          expect(emailProps.selectedEditorMode).toBe(EMAIL_CREATE_MODES.HTML_EDITOR);
        });
      });
    });

    describe('Edit Flow - HTML Editor Template', () => {
      it('should call getTemplateDetails and set HTML editor for HTML template', async () => {
        const templateId = 'html-template-123';
        const htmlTemplateData = {
          _id: templateId,
          name: 'HTML Template',
          versions: {
            base: {
              activeTab: 'en',
              en: {
                is_drag_drop: false,
                html_content: '<html><body>Test</body></html>',
              },
            },
          },
        };

        const editProps = {
          ...newFlowMockProps,
          params: { id: templateId },
          location: {
            pathname: `/email/edit/${templateId}`,
            query: { id: templateId },
          },
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: null,
            getTemplateDetailsInProgress: false,
          },
        };

        const { result, rerender } = renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        // Verify getTemplateDetails is called
        await waitFor(() => {
          expect(mockEmailActions.getTemplateDetails).toHaveBeenCalledWith(templateId, 'email');
        });

        // Simulate template data loaded
        rerender({
          ...editProps,
          Email: {
            ...editProps.Email,
            templateDetails: htmlTemplateData,
            getTemplateDetailsInProgress: false,
          },
        });

        await waitFor(() => {
          const emailProps = result.current.emailProps;
          expect(emailProps.editor).toBe('HTML');
          expect(emailProps.selectedEditorMode).toBe(EMAIL_CREATE_MODES.HTML_EDITOR);
        });
      });

      it('should detect HTML template from templateData prop (library mode)', async () => {
        const htmlTemplateData = {
          _id: 'html-template-456',
          name: 'HTML Template',
          base: {
            is_drag_drop: false,
            html_content: '<html><body>Test</body></html>',
          },
        };

        const editProps = {
          ...newFlowMockProps,
          templateData: htmlTemplateData,
          location: {
            pathname: '/email/edit',
            query: { type: 'embedded', module: 'library' },
          },
        };

        const { result } = renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        await waitFor(() => {
          const emailProps = result.current.emailProps;
          expect(emailProps.editor).toBe('HTML');
          expect(emailProps.selectedEditorMode).toBe(EMAIL_CREATE_MODES.HTML_EDITOR);
        });
      });
    });

    describe('templateId resolution (lines 209-213)', () => {
      it('should call getTemplateDetails with templateId from params.id', async () => {
        const templateId = 'from-params-id';
        const editProps = {
          ...newFlowMockProps,
          params: { id: templateId },
          location: { pathname: '/email/edit/other', query: {} },
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: null,
            getTemplateDetailsInProgress: false,
          },
        };

        renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        await waitFor(() => {
          expect(mockEmailActions.getTemplateDetails).toHaveBeenCalledWith(templateId, 'email');
        });
      });

      it('should call getTemplateDetails with templateId from location.query.id when params.id is missing', async () => {
        const templateId = 'from-query-id';
        const editProps = {
          ...newFlowMockProps,
          params: {},
          location: {
            pathname: '/email/edit/something',
            query: { id: templateId },
          },
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: null,
            getTemplateDetailsInProgress: false,
          },
        };

        renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        await waitFor(() => {
          expect(mockEmailActions.getTemplateDetails).toHaveBeenCalledWith(templateId, 'email');
        });
      });

      it('should call getTemplateDetails with templateId from location.params.id when params and query id are missing', async () => {
        const templateId = 'from-location-params-id';
        const editProps = {
          ...newFlowMockProps,
          params: {},
          location: {
            pathname: '/email/edit/fallback',
            query: {},
            params: { id: templateId },
          },
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: null,
            getTemplateDetailsInProgress: false,
          },
        };

        renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        await waitFor(() => {
          expect(mockEmailActions.getTemplateDetails).toHaveBeenCalledWith(templateId, 'email');
        });
      });

      it('should call getTemplateDetails with templateId extracted from pathname /edit/ID when no params or query id', async () => {
        const templateId = 'extracted-from-pathname';
        const editProps = {
          ...newFlowMockProps,
          params: {},
          location: {
            pathname: `/email/edit/${templateId}`,
            query: {},
          },
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: null,
            getTemplateDetailsInProgress: false,
          },
        };

        renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        await waitFor(() => {
          expect(mockEmailActions.getTemplateDetails).toHaveBeenCalledWith(templateId, 'email');
        });
      });

      it('should not call getTemplateDetails when pathname includes /edit/ but has no id segment', async () => {
        const editProps = {
          ...newFlowMockProps,
          params: {},
          location: {
            pathname: '/email/edit/',
            query: {},
          },
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: null,
            getTemplateDetailsInProgress: false,
          },
        };

        renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        await waitFor(() => {
          expect(mockEmailActions.getTemplateDetails).not.toHaveBeenCalled();
        }, { timeout: 500 });
      });
    });

    describe('Edit Flow - BEE Editor Template', () => {
      it('should call getTemplateDetails and set BEE editor for BEE template', async () => {
        const templateId = 'bee-template-123';
        const beeTemplateData = {
          _id: templateId,
          name: 'BEE Template',
          versions: {
            base: {
              activeTab: 'en',
              en: {
                is_drag_drop: true,
                drag_drop_id: 'drag-drop-123',
              },
            },
          },
        };

        const editProps = {
          ...newFlowMockProps,
          params: { id: templateId },
          location: {
            pathname: `/email/edit/${templateId}`,
            query: { id: templateId },
          },
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: null,
            getTemplateDetailsInProgress: false,
            isBeeEnabled: true,
          },
        };

        const { result, rerender } = renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        // Verify getTemplateDetails is called
        await waitFor(() => {
          expect(mockEmailActions.getTemplateDetails).toHaveBeenCalledWith(templateId, 'email');
        });

        // Simulate template data loaded
        rerender({
          ...editProps,
          Email: {
            ...editProps.Email,
            templateDetails: beeTemplateData,
            getTemplateDetailsInProgress: false,
            isBeeEnabled: true,
          },
        });

        await waitFor(() => {
          const emailProps = result.current.emailProps;
          expect(emailProps.editor).toBe('BEE');
          expect(emailProps.selectedEditorMode).toBe(null);
        });
      });

      it('should detect BEE template from templateData prop with base.is_drag_drop (library mode)', async () => {
        const beeTemplateData = {
          _id: 'bee-template-456',
          name: 'BEE Template',
          base: {
            is_drag_drop: true,
            drag_drop_id: 'drag-drop-456',
          },
        };

        const editProps = {
          ...newFlowMockProps,
          templateData: beeTemplateData,
          location: {
            pathname: '/email/edit',
            query: { type: 'embedded', module: 'library' },
          },
          Email: {
            ...newFlowMockProps.Email,
            isBeeEnabled: true,
          },
        };

        const { result } = renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        await waitFor(() => {
          const emailProps = result.current.emailProps;
          expect(emailProps.editor).toBe('BEE');
          expect(emailProps.selectedEditorMode).toBe(null);
        });
      });

      it('should detect BEE template with language-specific is_drag_drop (actual API format)', async () => {
        // This matches the actual API response format shown by the user
        const beeTemplateData = {
          _id: 'bee-template-lang',
          name: 'BEE Template',
          versions: {
            base: {
              activeTab: 'en',
              en: {
                is_drag_drop: true,
                drag_drop_id: '',
                lang_id: 69,
                iso_code: 'en',
                language: 'English',
              },
            },
          },
        };

        const editProps = {
          ...newFlowMockProps,
          templateData: beeTemplateData,
          Email: {
            ...newFlowMockProps.Email,
            isBeeEnabled: true,
          },
        };

        const { result } = renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        await waitFor(() => {
          const emailProps = result.current.emailProps;
          expect(emailProps.editor).toBe('BEE');
          expect(emailProps.selectedEditorMode).toBe(null);
        });
      });

      it('should fallback to HTML editor if BEE template but BEE is disabled', async () => {
        const beeTemplateData = {
          _id: 'bee-template-disabled',
          name: 'BEE Template',
          versions: {
            base: {
              activeTab: 'en',
              en: {
                is_drag_drop: true,
              },
            },
          },
        };

        const editProps = {
          ...newFlowMockProps,
          templateData: beeTemplateData,
          Email: {
            ...newFlowMockProps.Email,
            isBeeEnabled: false, // BEE disabled
          },
        };

        const { result } = renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        await waitFor(() => {
          const emailProps = result.current.emailProps;
          // Should fallback to HTML editor when BEE is disabled
          expect(emailProps.editor).toBe('HTML');
          expect(emailProps.selectedEditorMode).toBe(EMAIL_CREATE_MODES.HTML_EDITOR);
        });
      });
    });

    describe('Edit Flow - API Call Verification', () => {
      it('should NOT call getTemplateDetails if template data already exists', async () => {
        const templateId = 'existing-template';
        const existingTemplateData = {
          _id: templateId,
          name: 'Existing Template',
          versions: {
            base: {
              activeTab: 'en',
              en: {
                is_drag_drop: false,
              },
            },
          },
        };

        const editProps = {
          ...newFlowMockProps,
          params: { id: templateId },
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: existingTemplateData, // Already loaded
            getTemplateDetailsInProgress: false,
          },
        };

        renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        // Wait a bit to ensure effect runs
        await waitFor(() => {
          // Should NOT call getTemplateDetails since data already exists
          expect(mockEmailActions.getTemplateDetails).not.toHaveBeenCalled();
        }, { timeout: 1000 });
      });

      it('should NOT call getTemplateDetails if templateData prop is provided', async () => {
        const templateData = {
          _id: 'prop-template',
          base: {
            is_drag_drop: false,
          },
        };

        const editProps = {
          ...newFlowMockProps,
          params: { id: 'prop-template' },
          templateData, // Provided via prop
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: null,
          },
        };

        renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        // Wait a bit to ensure effect runs
        await waitFor(() => {
          // Should NOT call getTemplateDetails since templateData prop is provided
          expect(mockEmailActions.getTemplateDetails).not.toHaveBeenCalled();
        }, { timeout: 1000 });
      });

      it('should NOT call getTemplateDetails if already loading', async () => {
        const templateId = 'loading-template';

        const editProps = {
          ...newFlowMockProps,
          params: { id: templateId },
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: null,
            getTemplateDetailsInProgress: true, // Already loading
          },
        };

        renderHook((props) => useEmailWrapper(props), {
          initialProps: editProps,
        });

        // Wait a bit to ensure effect runs
        await waitFor(() => {
          // Should NOT call getTemplateDetails since already loading
          expect(mockEmailActions.getTemplateDetails).not.toHaveBeenCalled();
        }, { timeout: 1000 });
      });

      it('should NOT call getTemplateDetails when isEditEmail is false (create flow)', async () => {
        const templateId = 'create-flow-id';
        const createFlowProps = {
          ...newFlowMockProps,
          isEditEmail: false,
          params: { id: templateId },
          location: {
            pathname: `/email/edit/${templateId}`,
            query: { id: templateId },
          },
          Email: {
            ...newFlowMockProps.Email,
            templateDetails: null,
            getTemplateDetailsInProgress: false,
          },
        };

        renderHook((props) => useEmailWrapper(props), {
          initialProps: createFlowProps,
        });

        await waitFor(() => {
          expect(mockEmailActions.getTemplateDetails).not.toHaveBeenCalled();
        }, { timeout: 1000 });
      });
    });
  });

  describe('getStepFromTemplateStep (tested indirectly through behavior)', () => {
    it('should handle numeric step 1 (MODE_SELECTION)', () => {
      const { result } = renderHook(() => useEmailWrapper({
        ...mockProps,
        step: 1,
      }));

      // When step is 1 (MODE_SELECTION), isShowEmailCreate should be false
      // This tests that getStepFromTemplateStep converts 1 to MODE_SELECTION
      expect(result.current.isShowEmailCreate).toBe(false);
    });

    it('should handle numeric step 2 (TEMPLATE_SELECTION)', () => {
      const { result } = renderHook(() => useEmailWrapper({
        ...mockProps,
        step: 2,
        emailCreateMode: EMAIL_CREATE_MODES.EDITOR,
      }));

      // When step is 2 (TEMPLATE_SELECTION), isShowEmailCreate should be false
      expect(result.current.isShowEmailCreate).toBe(false);
    });

    it('should handle numeric step 3 (CREATE_TEMPLATE_CONTENT)', () => {
      const { result } = renderHook(() => useEmailWrapper({
        ...mockProps,
        step: 3,
        emailCreateMode: EMAIL_CREATE_MODES.EDITOR,
        SelectedEdmDefaultTemplate: { id: 'template1' },
      }));

      // When step is 3 (CREATE_TEMPLATE_CONTENT) and template is selected, isShowEmailCreate should be true
      expect(result.current.isShowEmailCreate).toBe(true);
    });

    it('should handle string step value', () => {
      const { result } = renderHook(() => useEmailWrapper({
        ...mockProps,
        step: STEPS.CREATE_TEMPLATE_CONTENT,
        emailCreateMode: EMAIL_CREATE_MODES.EDITOR,
        SelectedEdmDefaultTemplate: { id: 'template1' },
      }));

      // String step should work the same way
      expect(result.current.isShowEmailCreate).toBe(true);
    });

    it('should default to MODE_SELECTION when step is null or undefined', () => {
      const { result: result1 } = renderHook(() => useEmailWrapper({
        ...mockProps,
        step: null,
      }));

      // Should default to MODE_SELECTION behavior
      expect(result1.current.isShowEmailCreate).toBe(false);

      const { result: result2 } = renderHook(() => useEmailWrapper({
        ...mockProps,
        step: undefined,
      }));

      expect(result2.current.isShowEmailCreate).toBe(false);
    });
  });

  describe('Template mode selection logic', () => {
    it('should set HTML_EDITOR mode when HTML_EDITOR is selected and supportCKEditor is false', () => {
      const { hasSupportCKEditor } = require('../../../utils/common');
      hasSupportCKEditor.mockReturnValueOnce(false);

      const { result } = renderHook(() => useEmailWrapper({
        ...mockProps,
        emailCreateMode: EMAIL_CREATE_MODES.HTML_EDITOR,
        modeContent: { id: 'mode1' },
        step: STEPS.CREATE_TEMPLATE_CONTENT,
      }));

      expect(result.current.emailProps.selectedEditorMode).toBe(EMAIL_CREATE_MODES.HTML_EDITOR);
    });

    // Note: DRAG_DROP and EDITOR mode selection logic is complex and depends on multiple conditions
    // These are tested through integration tests and actual component usage
    // The logic is covered in existing tests that test the full flow
  });
});
