// eslint-disable-next-line jsx-a11y/href-no-hash
import { useCallback, useEffect, useRef } from 'react';
import {
  ANDROID, DEEP_LINK, GIF, IMAGE, IOS, VIDEO,
} from '../constants';
import { NONE } from '../../Whatsapp/constants';

/**
 * Custom hook to manage content synchronization between Android and iOS platforms
 * @param {Object} params Configuration parameters
 * @param {boolean} params.sameContent Whether sync is enabled
 * @param {Function} params.setAndroidContent Android content setter
 * @param {Function} params.setIosContent iOS content setter
 * @param {Function} params.validateTitle Title validation function
 * @param {Function} params.validateMessage Message validation function
 * @param {Function} params.setAndroidTitleError Android title error setter
 * @param {Function} params.setAndroidMessageError Android message error setter
 * @param {Function} params.setIosTitleError iOS title error setter
 * @param {Function} params.setIosMessageError iOS message error setter
 * @param {Object} params.androidContent Current Android content
 * @param {Object} params.iosContent Current iOS content
 * @param {Function} params.updateOnMpushImageReUpload Image re-upload handler
 * @param {Function} params.updateOnMpushVideoReUpload Video re-upload handler
 * @param {Object} params.changeSourceRef Ref to track last changed platform
 */
const DEBOUNCE_DELAY = 500;

/**
 * Get platform-specific content and setters
 * @param {string} platform - ANDROID or IOS
 * @param {Object} config - Configuration object containing content and setters
 * @returns {Object} Platform-specific content and setters
 */
const getPlatformContent = (platform, {
  androidContent,
  iosContent,
  setAndroidContent,
  setIosContent,
  changeSourceRef,
}) => {
  const isAndroid = platform === ANDROID;
  const result = {
    setContent: isAndroid ? setAndroidContent : setIosContent,
    otherSetContent: isAndroid ? setIosContent : setAndroidContent,
    otherContent: isAndroid ? iosContent : androidContent,
    currentContent: isAndroid ? androidContent : iosContent,
    targetPlatform: isAndroid ? IOS : ANDROID,
  };

  // Add updateChangeSource if changeSourceRef is provided
  if (changeSourceRef && Object.prototype.hasOwnProperty.call(changeSourceRef, 'current')) {
    result.updateChangeSource = () => {
      // Create a new object to avoid mutating the parameter directly
      const ref = { ...changeSourceRef, current: isAndroid ? ANDROID.toLowerCase() : IOS.toLowerCase() };
      Object.assign(changeSourceRef, ref);
    };
  }

  return result;
};

const usePlatformSync = ({
  setAndroidContent,
  setIosContent,
  validateTitle,
  validateMessage,
  setAndroidTitleError,
  setAndroidMessageError,
  setIosTitleError,
  setIosMessageError,
  androidContent,
  iosContent,
  updateOnMpushImageReUpload,
  updateOnMpushVideoReUpload,
  sameContent,
  changeSourceRef,
}) => {
  // Debounce refs
  const debounceTimeoutRef = useRef(null);

  // Debounced sync effect
  useEffect(() => {
    if (!sameContent || !changeSourceRef?.current) return undefined;
    if (debounceTimeoutRef.current) clearTimeout(debounceTimeoutRef.current);
    debounceTimeoutRef.current = setTimeout(() => {
      if (changeSourceRef.current === ANDROID.toLowerCase()) {
        setIosContent(androidContent);
      } else if (changeSourceRef.current === IOS.toLowerCase()) {
        setAndroidContent(iosContent);
      }
    }, DEBOUNCE_DELAY);
    return () => {
      if (debounceTimeoutRef.current) clearTimeout(debounceTimeoutRef.current);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [androidContent, iosContent, sameContent]);

  // Utility to deeply sync content between platforms (except platform-specific fields)
  const deepSyncContent = useCallback((sourceContent, targetContent, targetPlatform) => {
    // Deep copy all fields except platform-specific ones
    const synced = {
      ...targetContent,
      ...sourceContent,
      // For buttons, remap platform property
      buttons: Array.isArray(sourceContent?.buttons)
        ? sourceContent?.buttons?.map((btn) => ({
          ...btn,
          platform: targetPlatform,
        }))
        : [],
    };
    return synced;
  }, []);

  // Handle title changes
  const handleTitleChange = useCallback((platform, value) => {
    const {
      setContent,
      otherSetContent,
      otherContent,
      currentContent,
      targetPlatform,
      updateChangeSource,
    } = getPlatformContent(platform, {
      androidContent,
      iosContent,
      setAndroidContent,
      setIosContent,
      changeSourceRef,
    });

    const setError = platform === ANDROID ? setAndroidTitleError : setIosTitleError;
    const otherSetError = platform === ANDROID ? setIosTitleError : setAndroidTitleError;

    if (updateChangeSource) {
      updateChangeSource();
    }

    const newContent = { ...currentContent, title: value };
    setContent(newContent);
    setError(validateTitle(value));

    if (sameContent) {
      const synced = deepSyncContent(newContent, otherContent, targetPlatform);
      otherSetContent(synced);
      otherSetError(validateTitle(value));
    }
  }, [setAndroidContent, setIosContent, setAndroidTitleError, setIosTitleError, validateTitle, changeSourceRef, sameContent, androidContent, iosContent, deepSyncContent]);

  // Handle message changes
  const handleMessageChange = useCallback((platform, value) => {
    const {
      setContent,
      otherSetContent,
      otherContent,
      currentContent,
      targetPlatform,
      updateChangeSource,
    } = getPlatformContent(platform, {
      androidContent,
      iosContent,
      setAndroidContent,
      setIosContent,
      changeSourceRef,
    });

    const setError = platform === ANDROID ? setAndroidMessageError : setIosMessageError;
    const otherSetError = platform === ANDROID ? setIosMessageError : setAndroidMessageError;

    if (updateChangeSource) {
      updateChangeSource();
    }

    const newContent = { ...currentContent, message: value };
    setContent(newContent);
    setError(validateMessage(value));

    if (sameContent) {
      const synced = deepSyncContent(newContent, otherContent, targetPlatform);
      otherSetContent(synced);
      otherSetError(validateMessage(value));
    }
  }, [setAndroidContent, setIosContent, setAndroidMessageError, setIosMessageError, validateMessage, changeSourceRef, sameContent, androidContent, iosContent, deepSyncContent]);

  // Handle media type changes
  const handleMediaTypeChange = useCallback((platform, value) => {
    const {
      setContent,
      otherSetContent,
      otherContent,
      currentContent,
      targetPlatform,
    } = getPlatformContent(platform, {
      androidContent,
      iosContent,
      setAndroidContent,
      setIosContent,
    });

    const previousMediaType = currentContent.mediaType;
    if (previousMediaType !== value) {
      if ((previousMediaType === VIDEO || previousMediaType === GIF)
          && (value === IMAGE || value === NONE)) {
        updateOnMpushVideoReUpload();
      } else if ((previousMediaType === VIDEO && value === GIF)
                 || (previousMediaType === GIF && value === VIDEO)) {
        updateOnMpushVideoReUpload();
      } else if (previousMediaType === IMAGE
                 && (value === VIDEO || value === GIF)) {
        updateOnMpushImageReUpload();
      }
    }

    const newContent = { ...currentContent, mediaType: value };
    setContent(newContent);

    if (sameContent) {
      const synced = deepSyncContent(newContent, otherContent, targetPlatform);
      otherSetContent(synced);
    }
  }, [sameContent, setAndroidContent, setIosContent, updateOnMpushImageReUpload, updateOnMpushVideoReUpload, androidContent, iosContent, deepSyncContent]);

  // Handle tag selection
  const handleTagSelect = useCallback((platform, tag, isTitle) => {
    const {
      setContent,
      otherSetContent,
      otherContent,
      currentContent,
      targetPlatform,
    } = getPlatformContent(platform, {
      androidContent,
      iosContent,
      setAndroidContent,
      setIosContent,
    });

    const otherSetError = platform === ANDROID ? setIosTitleError : setAndroidTitleError;
    const field = isTitle ? 'title' : 'message';
    let setError;
    let validate;
    if (isTitle) {
      setError = platform === ANDROID ? setAndroidTitleError : setIosTitleError;
      validate = validateTitle;
    } else {
      setError = platform === ANDROID ? setAndroidMessageError : setIosMessageError;
      validate = validateMessage;
    }

    const newValue = `${(currentContent[field] || '')}{{${tag}}}`;
    const newContent = { ...currentContent, [field]: newValue };
    setContent(newContent);
    setError(validate(newValue));

    if (sameContent) {
      const synced = deepSyncContent(newContent, otherContent, targetPlatform);
      otherSetContent(synced);
      otherSetError(validate(newValue));
    }
  }, [androidContent, iosContent, setAndroidContent, setIosContent, setAndroidTitleError, setIosTitleError, setAndroidMessageError, setIosMessageError, validateTitle, validateMessage, sameContent, deepSyncContent]);

  // Handle CTA/button changes
  const handleButtonChange = useCallback((platform, buttons) => {
    const {
      setContent,
      otherSetContent,
      otherContent,
      currentContent,
      targetPlatform,
    } = getPlatformContent(platform, {
      androidContent,
      iosContent,
      setAndroidContent,
      setIosContent,
    });

    const newContent = { ...currentContent, buttons };
    setContent(newContent);

    if (sameContent) {
      const mappedButtons = Array.isArray(buttons)
        ? buttons.map((btn) => ({
          ...btn,
          platform: targetPlatform,
        }))
        : [];
      const synced = deepSyncContent({ ...newContent, buttons: mappedButtons }, otherContent, targetPlatform);
      otherSetContent(synced);
    }
  }, [androidContent, iosContent, setAndroidContent, setIosContent, sameContent, deepSyncContent]);

  // Handle action on click changes
  const handleActionOnClickChange = useCallback((platform, checked) => {
    const {
      setContent,
      otherSetContent,
      otherContent,
      currentContent,
      targetPlatform,
    } = getPlatformContent(platform, {
      androidContent,
      iosContent,
      setAndroidContent,
      setIosContent,
    });

    const newContent = {
      ...currentContent,
      actionOnClick: checked,
      // Reset link type and values when unchecking
      ...(checked ? {} : {
        linkType: DEEP_LINK,
        deepLinkValue: "",
        deepLinkKeysValue: [],
        externalLinkValue: "",
      }),
    };
    setContent(newContent);

    if (sameContent) {
      const synced = deepSyncContent(newContent, otherContent, targetPlatform);
      otherSetContent(synced);
    }
  }, [androidContent, iosContent, setAndroidContent, setIosContent, sameContent, deepSyncContent]);

  // Handle link type changes
  const handleLinkTypeChange = useCallback((platform, linkType) => {
    const {
      setContent,
      otherSetContent,
      otherContent,
      currentContent,
      targetPlatform: platformTarget,
    } = getPlatformContent(platform, {
      androidContent,
      iosContent,
      setAndroidContent,
      setIosContent,
    });

    const newContent = {
      ...currentContent,
      linkType,
      deepLinkValue: '',
      externalLinkValue: '',
      deepLinkKeysValue: [],
    };
    setContent(newContent);

    if (sameContent) {
      const synced = deepSyncContent(newContent, otherContent, platformTarget);
      otherSetContent(synced);
    }
  }, [androidContent, iosContent, setAndroidContent, setIosContent, sameContent, deepSyncContent]);

  return {
    handleTitleChange,
    handleMessageChange,
    handleTagSelect,
    handleMediaTypeChange,
    handleButtonChange,
    handleActionOnClickChange,
    handleLinkTypeChange,
  };
};

export default usePlatformSync;
