import { renderHook } from '@testing-library/react';
import { act } from 'react';
import { useImageUpload } from './useImageUpload';
import { IMAGE_UPLOAD_METHODS } from '../../constants';

describe('useImageUpload', () => {
  const mockClearWebPushAsset = jest.fn();
  const mockUploadWebPushAsset = jest.fn();

  const mockWebPushActions = {
    clearWebPushAsset: mockClearWebPushAsset,
    uploadWebPushAsset: mockUploadWebPushAsset,
  };

  const defaultWebPush = {};

  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('Initialization', () => {
    it('should initialize with default upload method', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      expect(result.current.uploadMethod).toBe(IMAGE_UPLOAD_METHODS.UPLOAD_IMAGE);
      expect(result.current.imageSrc).toBe('');
      expect(result.current.imageUrl).toBe('');
      expect(result.current.isValidating).toBe(false);
      expect(result.current.isUploading).toBe(false);
    });

    it('should initialize with custom upload method', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
          initialUploadMethod: IMAGE_UPLOAD_METHODS.ADD_IMAGE_URL,
        })
      );

      expect(result.current.uploadMethod).toBe(IMAGE_UPLOAD_METHODS.ADD_IMAGE_URL);
    });
  });

  describe('Upload Method Changes', () => {
    it('should change upload method', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      const event = {
        target: {
          value: IMAGE_UPLOAD_METHODS.ADD_IMAGE_URL,
        },
      };

      act(() => {
        result.current.handleUploadMethodChange(event);
      });

      expect(result.current.uploadMethod).toBe(IMAGE_UPLOAD_METHODS.ADD_IMAGE_URL);
      expect(result.current.imageSrc).toBe('');
      expect(result.current.imageUrl).toBe('');
    });

    it('should clear imageSrc and imageUrl when upload method changes', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      act(() => {
        result.current.setImageSrc('path/to/image.jpg');
        result.current.setImageUrl('https://example.com/image.jpg');
      });

      const event = {
        target: {
          value: IMAGE_UPLOAD_METHODS.ADD_IMAGE_URL,
        },
      };

      act(() => {
        result.current.handleUploadMethodChange(event);
      });

      expect(result.current.imageSrc).toBe('');
      expect(result.current.imageUrl).toBe('');
    });
  });

  describe('Image Source Management', () => {
    it('should set image source', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      act(() => {
        result.current.setImageSrc('path/to/image.jpg');
      });

      expect(result.current.imageSrc).toBe('path/to/image.jpg');
    });

    it('should clear asset when setting image source', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      act(() => {
        result.current.setUpdateImageSrc('path/to/image.jpg');
      });

      expect(mockClearWebPushAsset).toHaveBeenCalledWith(0);
      expect(result.current.imageSrc).toBe('path/to/image.jpg');
    });

    it('should use correct index when clearing asset', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 1,
        })
      );

      act(() => {
        result.current.setUpdateImageSrc('path/to/image.jpg');
      });

      expect(mockClearWebPushAsset).toHaveBeenCalledWith(1);
    });

    it('should update on re-upload', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      act(() => {
        result.current.setImageSrc('path/to/image.jpg');
      });

      act(() => {
        result.current.updateOnReUpload();
      });

      expect(result.current.imageSrc).toBe('');
    });
  });

  describe('Image URL Management', () => {
    it('should set image URL', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      act(() => {
        result.current.setImageUrl('https://example.com/image.jpg');
      });

      expect(result.current.imageUrl).toBe('https://example.com/image.jpg');
    });

    it('should clear imageSrc when URL changes', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      act(() => {
        result.current.setImageSrc('path/to/image.jpg');
      });

      act(() => {
        result.current.handleUrlChange('https://example.com/image.jpg');
      });

      expect(result.current.imageSrc).toBe('');
    });

    it('should not clear imageSrc when URL is the same', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      // First set imageSrc to a non-empty value
      act(() => {
        result.current.setImageSrc('path/to/image.jpg');
      });

      // Then set imageUrl
      act(() => {
        result.current.setImageUrl('https://example.com/image.jpg');
      });

      // Capture the non-empty imageSrc
      const nonEmptyImageSrc = result.current.imageSrc;
      expect(nonEmptyImageSrc).toBe('path/to/image.jpg');
      expect(nonEmptyImageSrc).not.toBe('');

      // Call handleUrlChange with the same URL
      act(() => {
        result.current.handleUrlChange('https://example.com/image.jpg');
      });

      // Verify imageSrc is preserved (not cleared)
      expect(result.current.imageSrc).toBe(nonEmptyImageSrc);
      expect(result.current.imageSrc).toBe('path/to/image.jpg');
    });
  });

  describe('Asset Upload', () => {
    it('should call uploadWebPushAsset with correct parameters', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      const file = new File(['test'], 'test.jpg', { type: 'image/jpeg' });
      const type = 'image';
      const fileParams = { width: 100, height: 100 };

      act(() => {
        result.current.uploadAsset(file, type, fileParams);
      });

      expect(mockUploadWebPushAsset).toHaveBeenCalledWith(file, type, fileParams, 0);
    });

    it('should use correct index for upload', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 1,
        })
      );

      const file = new File(['test'], 'test.jpg', { type: 'image/jpeg' });

      act(() => {
        result.current.uploadAsset(file, 'image', {});
      });

      expect(mockUploadWebPushAsset).toHaveBeenCalledWith(file, 'image', {}, 1);
    });
  });

  describe('Validation and Upload State', () => {
    it('should update validation state', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      act(() => {
        result.current.handleValidationStateChange(true);
      });

      expect(result.current.isValidating).toBe(true);

      act(() => {
        result.current.handleValidationStateChange(false);
      });

      expect(result.current.isValidating).toBe(false);
    });

    it('should update upload state', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: defaultWebPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      act(() => {
        result.current.handleUploadStateChange(true);
      });

      expect(result.current.isUploading).toBe(true);

      act(() => {
        result.current.handleUploadStateChange(false);
      });

      expect(result.current.isUploading).toBe(false);
    });
  });

  describe('Restoring Image from Uploaded Asset', () => {
    it('should restore image from uploadedAssetData0', () => {
      const webPush = {
        uploadedAssetData0: {
          metaInfo: {
            secure_file_path: 'secure/path/to/image.jpg',
          },
        },
      };

      const { result } = renderHook(() =>
        useImageUpload({
          webPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      expect(result.current.imageSrc).toBe('secure/path/to/image.jpg');
    });

    it('should restore image from uploadedAssetData for index 0', () => {
      const webPush = {
        uploadedAssetData: {
          metaInfo: {
            secure_file_path: 'secure/path/to/image.jpg',
          },
        },
      };

      const { result } = renderHook(() =>
        useImageUpload({
          webPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      expect(result.current.imageSrc).toBe('secure/path/to/image.jpg');
    });

    it('should restore image from uploadedAssetData{index} for non-zero index', () => {
      const webPush = {
        uploadedAssetData1: {
          metaInfo: {
            secure_file_path: 'secure/path/to/brand-icon.jpg',
          },
        },
      };

      const { result } = renderHook(() =>
        useImageUpload({
          webPush,
          webPushActions: mockWebPushActions,
          index: 1,
        })
      );

      expect(result.current.imageSrc).toBe('secure/path/to/brand-icon.jpg');
    });

    it('should not restore image when secure_file_path is missing', () => {
      const webPush = {
        uploadedAssetData0: {
          metaInfo: {},
        },
      };

      const { result } = renderHook(() =>
        useImageUpload({
          webPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      expect(result.current.imageSrc).toBe('');
    });

    it('should not restore image when metaInfo is missing', () => {
      const webPush = {
        uploadedAssetData0: {},
      };

      const { result } = renderHook(() =>
        useImageUpload({
          webPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      expect(result.current.imageSrc).toBe('');
    });

    it('should not restore image when uploadedAssetData is missing', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: {},
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      expect(result.current.imageSrc).toBe('');
    });

    it('should update image when webPush changes', () => {
      const { result, rerender } = renderHook(
        ({ webPush }) =>
          useImageUpload({
            webPush,
            webPushActions: mockWebPushActions,
            index: 0,
          }),
        {
          initialProps: {
            webPush: {},
          },
        }
      );

      expect(result.current.imageSrc).toBe('');

      const newWebPush = {
        uploadedAssetData0: {
          metaInfo: {
            secure_file_path: 'new/path/to/image.jpg',
          },
        },
      };

      rerender({ webPush: newWebPush });

      expect(result.current.imageSrc).toBe('new/path/to/image.jpg');
    });

    it('should preserve image when webPush asset data is removed (edit mode compatibility)', () => {
      const webPush = {
        uploadedAssetData0: {
          metaInfo: {
            secure_file_path: 'secure/path/to/image.jpg',
          },
        },
      };

      const { result, rerender } = renderHook(
        ({ webPush }) =>
          useImageUpload({
            webPush,
            webPushActions: mockWebPushActions,
            index: 0,
          }),
        {
          initialProps: {
            webPush,
          },
        }
      );

      expect(result.current.imageSrc).toBe('secure/path/to/image.jpg');

      // Image should persist when asset data is removed (e.g., in edit mode)
      rerender({ webPush: {} });

      expect(result.current.imageSrc).toBe('secure/path/to/image.jpg');
    });
  });

  describe('Edge Cases', () => {
    it('should handle empty secure_file_path', () => {
      const webPush = {
        uploadedAssetData0: {
          metaInfo: {
            secure_file_path: '',
          },
        },
      };

      const { result } = renderHook(() =>
        useImageUpload({
          webPush,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      expect(result.current.imageSrc).toBe('');
    });

    it('should handle null webPush', () => {
      const { result } = renderHook(() =>
        useImageUpload({
          webPush: null,
          webPushActions: mockWebPushActions,
          index: 0,
        })
      );

      expect(result.current.imageSrc).toBe('');
    });
  });
});

