import React, { useEffect, useState } from 'react';

// Import Polotno and third-party libraries
import QRCode from 'qrcode';
import { observer } from 'mobx-react-lite';
import { SectionTab } from 'polotno/side-panel';
import type { StoreType } from 'polotno/model/store';

import { useDispatch, useSelector } from 'react-redux';
import { AppDispatch, RootState } from '../../../redux/store';
import { failure, success } from '../../../redux/actions/snackbarActions';
import {
  setQrUrl,
  setUtmSource,
  setUtmMedium,
  setUtmCampaignName,
  setCustomUtms,
  clearQrFields,
  setIsQR,
  setQrDialog,
  closeQrDialog,
} from '../../../redux/actions/customQRCodeActions';
import { uploadFile } from '../../../redux/actions/templateActions';

// Utils
import { MESSAGES } from '../../../utils/message';
import { validURL } from '../../../utils/helper';
import {
  DISALLOWED_DOMAINS,
  MERGE_UTM_PARAMS,
  emojiRegex,
} from '../../../utils/constants';

//Components
import GeneralSelect from '../../../components/GenericUIBlocks/GeneralSelect';
import QRCodeModal from './V2/QRCodeModal';
import DialogV2 from '../../../components/GenericUIBlocks/Dialog/V2';

// UI Components
import Input from '../../../components/GenericUIBlocks/Input';
import Typography from '../../GenericUIBlocks/Typography';

// Icons
import CustomQRIcon from '../../../assets/images/templates/custom-qr-section-icon';
import QRCodeIcon from '../../../assets/images/templates/qr-code';

// @ts-ignore
import Edit from '../../../assets/images/templates/edit.svg';
// @ts-ignore
import Archive from '../../../assets/images/templates/archive.svg';

// @ts-ignore
import ConfirmCloseIcon from '../../../assets/images/modal-icons/confirm-close-icon';
// @ts-ignore
import Actions from '../../../assets/images/templates/actions.svg'

// styles
import './styles.scss';

interface CustomQRProps {
  store: StoreType;
  allowSenderFields: any;
  allowPropertyFields: any;
  excludedFields: any;
  currentTheme?: string | null | undefined;
  onGetQRCodes?: (payload: any) => Promise<any>;
  onDeleteQRCodes?: (id: string | number) => Promise<void>;
  onUploadQRCode?: (payload: any) => Promise<any>;
  onEditQRCode?: (payload: any) => Promise<any>;
}

const cancelDialogStylesV2 = {
  maxWidth: '567px',
  minHeight: 'auto',
  padding: '40px',
};

// define the new custom section
const CustomQRCode = {
  name: 'QR-Section',
  Tab: (props: any) => (
    <SectionTab name="QR" {...props} iconSize={20}>
      <CustomQRIcon />
    </SectionTab>
  ),

  // we need observer to update component automatically on any store changes
  Panel: observer(
    ({
      store,
      allowSenderFields,
      allowPropertyFields,
      excludedFields,
      currentTheme,
      onGetQRCodes,
      onDeleteQRCodes,
      onUploadQRCode,
      onEditQRCode,
    }: CustomQRProps) => {
      // V2 State for API-driven functionality
      const [qrCodes, setQrCodes] = useState<any[]>([]);
      const [isLoading, setIsLoading] = useState(false);
      const [isLoadingMore, setIsLoadingMore] = useState(false);
      const [currentPage, setCurrentPage] = useState(1);
      const [hasMore, setHasMore] = useState(true);
      const [activeDropdown, setActiveDropdown] = useState<
        string | number | null
      >(null);
      const [isEditing, setIsEditing] = useState(false);
      const [selectedQR, setSelectedQR] = useState<any>(null);
      const [openDeleteDialog, setOpenDeleteDialog] = useState(false);
      const [isLoadingDelete, setIsLoadingDelete] = useState(false);
      const [saveQrLoading, setSaveQrLoading] = useState(false);

      const [isActionsOpen, setIsActionsOpen] = useState<
        string | number | null
      >(null);
      const [actionsDropdownUpward, setActionsDropdownUpward] = useState(false);

      const qrCodesGridRef = React.useRef<HTMLDivElement>(null);
      const dropdownRefs = React.useRef<Map<string | number, HTMLDivElement>>(
        new Map()
      );
      const actionsRefs = React.useRef<Map<string | number, HTMLDivElement>>(
        new Map()
      );
      const loadingTimeoutRef = React.useRef<NodeJS.Timeout | null>(null);
      const isLoadingRef = React.useRef(false);

      const noteStyles = {
        fontWeight: '400',
        fontSize: '12px',
        color: '#000',
        width: '100%',
        maxWidth: '245px',
        margin: '16px 0 20px',
      };

      const itemStyle = {
        margin: 0,
        fontSize: '12px',
        fontWeight: '300',
      };

      const handleDialogChange = (model = '') => {
        if (dialog.open) {
          dispatch(closeQrDialog());
        } else {
          dispatch(setQrDialog(true, model));
        }
      };

      const handleCloseDeleteDialog = () => {
        setOpenDeleteDialog(false);
      };

      const handleOpenDeleteDialog = () => {
        setOpenDeleteDialog(true);
      };

      const handleDialogClose = (model = '') => {
        dispatch(closeQrDialog());
        setIsEditing(false);
        dispatch(setQrUrl(''));
        dispatch(setUtmSource('direct mail'));
        dispatch(setUtmMedium('QR Code'));
        dispatch(setUtmCampaignName(''));
        dispatch(setCustomUtms({}));
      };


      const dialog = useSelector((state: RootState) => state.customQRCode.dialog);
      const url = useSelector((state: RootState) => state.customQRCode.url);
      const utmSource = useSelector(
        (state: RootState) => state.customQRCode.utmSource
      );
      const utmMedium = useSelector(
        (state: RootState) => state.customQRCode.utmMedium
      );
      const utmCampaignName = useSelector(
        (state: RootState) => state.customQRCode.utmCampaignName
      );
      const customUtms = useSelector(
        (state: RootState) => state.customQRCode.customUtms
      );
      const isQR = useSelector((state: RootState) => state.customQRCode.isQR);

      const dispatch: AppDispatch = useDispatch();

      const defaultFields = useSelector(
        (state: RootState) => state.templates.defaultDynamicFields
      );

      const defaultSenderFields = useSelector(
        (state: RootState) => state.templates.defaultSenderFields
      
      );

      const customFields = useSelector(
        (state: RootState) => state.customFields.customFields
      );

      const customFieldsV2 = useSelector(
        (state: RootState) => state.customFields.customFieldsV2
      ) as Record<string, any>;

      const defaultPropertyFields = useSelector(
        (state: RootState) => state.templates.defaultPropertyFields
      );

      const excludedLabels = ['utm_c_first_name c_last_name'];

      let flattenedFieldsV2 = [];
      if (customFieldsV2.length > 0) {
        flattenedFieldsV2 = customFieldsV2?.flatMap(
          (section: { fields: any }) => section.fields
        );
      }

      const allFields = [
        ...defaultFields,
        ...customFields,
        ...flattenedFieldsV2,
        ...(allowSenderFields ? defaultSenderFields : []),
        ...(allowPropertyFields ? defaultPropertyFields : []),
        ...(allowPropertyFields
          ? [
            {
              value: 'ROS.PROPERTY_OFFER',
              key: '{{ROS.PROPERTY_OFFER}}',
              defaultValue: '$123,456.00',
            },
          ]
          : []),
      ].filter(({ key }) => !excludedFields?.includes(key));

      const utmFields = allFields
        .map(({ key }) => ({
          label: `utm_${key?.toLowerCase().replaceAll('.', '_').replaceAll(/[{}]/g, '')}`,
        }))
        .filter((utmField) => !excludedLabels.includes(utmField.label));

      const utms = ['custom_utm_1', 'custom_utm_2', 'custom_utm_3'];

      const el = store.selectedElements[0];

      const clearQRFields = () => {
        store.selectElements([]);
        dispatch(clearQrFields());
      };

      const appendUtmParameters = (utmField: string, defaultValue: string) => {
        let result = '';
        const field = MERGE_UTM_PARAMS.find((field) => field.key === utmField);
        if (field) {
          result = `${field.value}=${defaultValue}`;
        }
        return result;
      };

      const validateQRCode = () => {
        const validations = [
          { value: utmSource, label: 'UTM Source' },
          { value: utmMedium, label: 'UTM Medium' },
          { value: utmCampaignName, label: 'UTM Campaign' },
        ];

        for (const { value, label } of validations) {
          if (value.length >= 150) {
            dispatch(failure(`${label} must be less than 150 characters`));
            return false;
          }
          if (emojiRegex.test(value)) {
            dispatch(failure(`Emoji are not allowed in ${label}`));
            return false;
          }
        }

        return true;
      };

      const containsDisallowedDomains = (str: string) => {
        return DISALLOWED_DOMAINS.some((substring) => str.includes(substring));
      };

      // create svg image for QR code for input text
      const getQR = (text: string) => {
        return new Promise<string>((resolve, reject) => {
          QRCode.toDataURL(
            text || 'no-data',
            {
              type: 'image/png',
              margin: 0,
              color: {
                dark: '#000000',
                light: '#0000', // transparent background
              },
              scale: 10, // increase for higher resolution
            },
            (err: any, url: string) => {
              if (err) return reject(err);
              resolve(url); // returns base64 PNG image string
            }
          );
        });
      };

      // Converts base64 data URL to File
      const base64ToFile = (base64: string, filename: string): File => {
        const arr = base64.split(',');
        const mime = arr[0].match(/:(.*?);/)?.[1] || 'image/png';
        const bstr = atob(arr[1]);
        let n = bstr.length;
        const u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        return new File([u8arr], filename, { type: mime });
      };

      const createCustomizeURL = (url: string) => {
        let customURL = url;
        let params = [];
        if (utmSource) {
          params.push(`utm_source=${utmSource.replace(/ /g, '_')}`);
        }
        if (utmMedium) {
          params.push(`utm_medium=${utmMedium.replace(/ /g, '_')}`);
        }
        if (utmCampaignName) {
          params.push(`utm_campaign=${utmCampaignName.replace(/ /g, '_')}`);
        }

        if (customUtms[utms[0]]?.label) {
          const orignalField = `{{${customUtms[utms[0]]?.label.replace('utm_', '').replace('_', '.').toUpperCase()}}}`;
          const defaultValue = allFields.find(
            (field) => field.key === orignalField
          )?.defaultValue;
          const attachUtmKeys = appendUtmParameters(orignalField, defaultValue);
          const mergeUtmParams =
            attachUtmKeys && orignalField == '{{C.PHONE_NUMBER}}'
              ? encodeURIComponent(
                `${customUtms[utms[0]]?.label}=${defaultValue}&${attachUtmKeys}`
              ).replace(/[\s\(\)]/g, '')
              : attachUtmKeys
                ? `${customUtms[utms[0]]?.label}=${defaultValue}&${attachUtmKeys}`
                : `${customUtms[utms[0]]?.label}=${defaultValue}`;
          params.push(mergeUtmParams);
        }

        if (customUtms[utms[1]]?.label) {
          const orignalField = `{{${customUtms[utms[1]]?.label.replace('utm_', '').replace('_', '.').toUpperCase()}}}`;
          const defaultValue = allFields.find(
            (field) => field.key === orignalField
          )?.defaultValue;
          const attachUtmKeys = appendUtmParameters(orignalField, defaultValue);
          const mergeUtmParams =
            attachUtmKeys && orignalField == '{{C.PHONE_NUMBER}}'
              ? encodeURIComponent(
                `${customUtms[utms[1]]?.label}=${defaultValue}&${attachUtmKeys}`
              ).replace(/[\s\(\)]/g, '')
              : attachUtmKeys
                ? `${customUtms[utms[1]]?.label}=${defaultValue}&${attachUtmKeys}`
                : `${customUtms[utms[1]]?.label}=${defaultValue}`;
          params.push(mergeUtmParams);
        }

        if (customUtms[utms[2]]?.label) {
          const orignalField = `{{${customUtms[utms[2]]?.label.replace('utm_', '').replace('_', '.').toUpperCase()}}}`;
          const defaultValue = allFields.find(
            (field) => field.key === orignalField
          )?.defaultValue;
          const attachUtmKeys = appendUtmParameters(orignalField, defaultValue);
          const mergeUtmParams =
            attachUtmKeys && orignalField == '{{C.PHONE_NUMBER}}'
              ? encodeURIComponent(
                `${customUtms[utms[2]]?.label}=${defaultValue}&${attachUtmKeys}`
              ).replace(/[\s\(\)]/g, '')
              : attachUtmKeys
                ? `${customUtms[utms[2]]?.label}=${defaultValue}&${attachUtmKeys}`
                : `${customUtms[utms[2]]?.label}=${defaultValue}`;
          params.push(mergeUtmParams);
        }

        if (params.length > 0) {
          customURL += `/?${params.join('&')}`;
        }

        return encodeURI(customURL);
      };

      const addNewQRCode = async () => {
        if (utmCampaignName) {
          if (url) {
            if (validURL(url) && !containsDisallowedDomains(url)) {
              const isValidQR = validateQRCode();
              if (!isValidQR) return false;

              setSaveQrLoading(true);
              const randomizedId = Math.random().toString(36).substring(2, 7);
              const customQRUrl = createCustomizeURL(url);

              const src = await getQR(customQRUrl);
              if (currentTheme === 'v2' && onUploadQRCode && onGetQRCodes) {
                const file = base64ToFile(src, `${utmCampaignName}-qr.png`);
                const uploadedFile = await uploadFile(file);
                if (!uploadedFile) {
                  setSaveQrLoading(false);
                  return dispatch(failure(MESSAGES.TEMPLATE.QR_SECTION.FAILED_QR));
                }
                const payload = {
                  name: utmCampaignName,
                  qrCodeJson: {
                    name: utmCampaignName,
                    url: url,
                    qrImagePath: uploadedFile,
                    utm_source: utmSource,
                    utm_medium: utmMedium,
                    utm_campaign_name: utmCampaignName,
                    custom_utms: customUtms,
                  },
                };

                try {
                  await onUploadQRCode(payload);
                  // Reset pagination and reload from first page
                  setCurrentPage(1);
                  setHasMore(true);
                  await loadQRCodes(1, false, false);
                  handleDialogClose(); // Close modal
                  clearQRFields();
                  setSaveQrLoading(false);
                } catch (error) {
                  setSaveQrLoading(false);
                  console.error('Failed to create QR code:', error);
                }
              } else {
                store.activePage.addElement({
                  id: `qr-${randomizedId}`,
                  type: 'image',
                  name: 'qr',
                  x: 50,
                  y: 50,
                  width: 100,
                  height: 100,
                  blurRadius: 0,
                  keepRatio: true,
                  src,
                  custom: {
                    url,
                    utm_source: utmSource,
                    utm_medium: utmMedium,
                    utm_campaign_name: utmCampaignName,
                    custom_utms: customUtms,
                  },
                });
                clearQRFields();
              }
              setSaveQrLoading(false);
            } else {
              dispatch(failure(MESSAGES.TEMPLATE.QR_SECTION.INVALID_URL));
            }
          } else {
            dispatch(failure(MESSAGES.TEMPLATE.QR_SECTION.EMPTY_QR));
          }
        } else {
          dispatch(failure(MESSAGES.TEMPLATE.QR_SECTION.EMPTY_CAMPAIGN));
        }
      };

      // V2 API Functions
      const loadQRCodes = React.useCallback(
        async (page: number = 1, append: boolean = false, loading = true) => {
          if (!onGetQRCodes) return;

          if (isLoadingRef.current) return;
          isLoadingRef.current = true;

          if (page === 1 && loading) {
            setIsLoading(true);
          } else {
            setIsLoadingMore(true);
          }

          try {
            const payload = {
              page,
              pageSize: 15,
            };

            const qrCodesData = await onGetQRCodes(payload);

            if (qrCodesData && Array.isArray(qrCodesData.rows)) {
              const normalized = qrCodesData.rows.map((qr: any) => ({
                id: qr.id,
                name: qr?.qrCodeJson?.name || qr?.qrCodeJson?.utm_campaign_name || '',
                url: qr.qrCodeJson.url,
                qrImagePath: qr.qrCodeJson.qrImagePath,
                status: qr.status,
                utm_source: qr.qrCodeJson.utm_source,
                utm_medium: qr.qrCodeJson.utm_medium,
                utm_campaign_name: qr.qrCodeJson.utm_campaign_name,
                custom_utms: qr.qrCodeJson.custom_utms,
              }));

              if (append && page > 1) {
                setQrCodes((prevQrCodes) => {
                  const existingIds = new Set(
                    prevQrCodes.map((qr: any) => qr.id)
                  );
                  const newQrCodes = normalized.filter(
                    (qr: any) => !existingIds.has(qr.id)
                  );
                  return [...prevQrCodes, ...newQrCodes];
                });
              } else {
                setQrCodes(normalized);
              }

              const hasMorePages =
                qrCodesData.currentPage < qrCodesData.lastPage;
              setHasMore(hasMorePages);
              setCurrentPage(qrCodesData.currentPage);
            } else {
              if (!append) {
                setQrCodes([]);
              }
              setHasMore(false);
            }
          } catch (error) {
            console.error('Failed to load QR codes:', error);
          } finally {
            setIsLoading(false);
            setIsLoadingMore(false);
            isLoadingRef.current = false;
          }
        },
        [onGetQRCodes]
      );

      const loadMoreQRCodes = React.useCallback(async () => {
        if (!hasMore || isLoadingMore || isLoading) return;
        await loadQRCodes(currentPage + 1, true);
      }, [hasMore, isLoadingMore, isLoading, currentPage, loadQRCodes]);

      const handleScroll = React.useCallback(() => {
        if (!qrCodesGridRef.current || !hasMore || isLoadingMore || isLoading)
          return;

        const { scrollTop, scrollHeight, clientHeight } = qrCodesGridRef.current;
        const scrollPercentage = (scrollTop + clientHeight) / scrollHeight;

        if (scrollPercentage > 0.75) {
          if (loadingTimeoutRef.current) {
            clearTimeout(loadingTimeoutRef.current);
          }

          loadingTimeoutRef.current = setTimeout(() => {
            loadMoreQRCodes();
          }, 300);
        }
      }, [hasMore, isLoadingMore, isLoading, loadMoreQRCodes]);

      const handleQRCodeSelect = async (qrCode: any) => {
        let customQRUrl = '';
        let src: any = '';
        let customData = {};

        if (currentTheme === 'v2') {
          customQRUrl = createCustomizeURL(qrCode.url);
          src = qrCode.qrImagePath;
          customData = {
            url: qrCode.url,
            qrCodeInstanceId: qrCode.id,
            qrImagePath: qrCode.qrImagePath,
            utm_source: qrCode.utm_source,
            utm_medium: qrCode.utm_medium,
            utm_campaign_name: qrCode.utm_campaign_name,
            custom_utms: qrCode.custom_utms,
          }
        } else {
          customQRUrl = createCustomizeURL(qrCode.url);
          src = await getQR(customQRUrl);
          customData = {
            url: qrCode.url,
            utm_source: qrCode.utmSource,
            utm_medium: qrCode.utmMedium,
            utm_campaign_name: qrCode.utmCampaign,
            custom_utms: qrCode.customUtms,
          }
        }

        const randomizedId = Math.random().toString(36).substring(2, 7);
        store.activePage.addElement({
          id: `qr-${randomizedId}`,
          type: 'image',
          name: 'qr',
          x: 50,
          y: 50,
          width: 100,
          height: 100,
          blurRadius: 0,
          keepRatio: true,
          src,
          custom: customData,
        });
      };

      const handleDeleteQRCode = async (qrCodeId: string | number) => {
        if (!onDeleteQRCodes) return;
        setIsLoadingDelete(true);
        try {
          await onDeleteQRCodes(qrCodeId);
          setQrCodes((prev) => prev.filter((qr) => qr.id !== qrCodeId));
          setActiveDropdown(null);
          setIsActionsOpen(null);
        } catch (error) {
          console.error('Failed to delete QR code:', error);
        }
        finally {
          setIsLoadingDelete(false);
        }
      };

      const handleEditQRCode = async (qrCode: any) => {
        setIsEditing(true);
        setSelectedQR(qrCode);
        dispatch(setQrUrl(qrCode.url ?? ''));
        dispatch(setUtmSource(qrCode.utm_source ?? ''));
        dispatch(setUtmMedium(qrCode.utm_medium ?? ''));
        dispatch(setUtmCampaignName(qrCode.utm_campaign_name ?? ''));
        dispatch(setCustomUtms(qrCode.custom_utms ?? {}));

        handleDialogChange('qr-modal');
        setIsActionsOpen(null);
      };

      const toggleActions = (
        qrCodeId: string | number,
        event: React.MouseEvent
      ) => {
        event.stopPropagation();
        const isOpening = isActionsOpen !== qrCodeId;
        if (isOpening) {
          const triggerEl = actionsRefs.current.get(qrCodeId);
          const scrollContainer = qrCodesGridRef.current;
          const dropdownHeight = 80;
          if (triggerEl && scrollContainer) {
            const triggerRect = triggerEl.getBoundingClientRect();
            const containerRect = scrollContainer.getBoundingClientRect();
            const spaceBelow = containerRect.bottom - triggerRect.bottom;
            setActionsDropdownUpward(spaceBelow < dropdownHeight);
          } else {
            setActionsDropdownUpward(false);
          }
        }
        setIsActionsOpen(isActionsOpen === qrCodeId ? null : qrCodeId);
      };

      // if selection is changed we need to update input value
      const updateQRCode = async () => {
        if (url) {
          if (validURL(url) && !containsDisallowedDomains(url)) {
            const isValidQR = validateQRCode();
            if (!isValidQR) return false;

            setSaveQrLoading(true);
            const customQRUrl = createCustomizeURL(url);
            const src = await getQR(customQRUrl);

            if (currentTheme === 'v2' && onEditQRCode && onGetQRCodes) {
              const file = base64ToFile(src, `${utmCampaignName}-qr.png`);
              const uploadedFile = await uploadFile(file);
              const payload = {
                name: utmCampaignName,
                id: selectedQR?.id,
                qrCodeJson: {
                  name: utmCampaignName,
                  url: url,
                  qrImagePath: uploadedFile,
                  utm_source: utmSource || null,
                  utm_medium: utmMedium || null,
                  utm_campaign_name: utmCampaignName,
                  custom_utms: customUtms,
                },
              };

              try {
                await onEditQRCode(payload);
                // Reset pagination and reload from first page
                setCurrentPage(1);
                setHasMore(true);
                await loadQRCodes(1, false, false);
                handleDialogClose(); // Close modal
                clearQRFields();
                setSaveQrLoading(false);
              } catch (error) {
                setSaveQrLoading(false);
                console.error('Failed to create QR code:', error);
              }
            } else if (el?.name === 'qr' && url) {
              el.set({
                src,
                custom: {
                  url,
                  utm_source: utmSource,
                  utm_medium: utmMedium,
                  utm_campaign_name: utmCampaignName,
                  custom_utms: customUtms,
                },
              });
              clearQRFields();
              setSaveQrLoading(false);
            }
          } else {
            dispatch(failure(MESSAGES.TEMPLATE.QR_SECTION.INVALID_URL));
          }
        } else {
          dispatch(failure(MESSAGES.TEMPLATE.QR_SECTION.EMPTY_QR));
        }
      };

      // Handler to update dropdown values
      const handleSelect = (utmKey: string, value: any) => {
        const updatedUtms = { ...customUtms };
        if (value === null) {
          delete updatedUtms[utmKey];
        } else {
          updatedUtms[utmKey] = value;
        }
        dispatch(setCustomUtms(updatedUtms));
      };

      // if selection is changed we need to update input value
      useEffect(() => {
        if (el?.name === 'qr' && currentTheme !== 'v2') {
          dispatch(setIsQR(el?.name === 'qr'));
          dispatch(setQrUrl(el?.custom?.url || el?.custom?.value || ''));
          dispatch(setUtmSource(el?.custom?.utm_source || 'direct mail'));
          dispatch(setUtmMedium(el?.custom?.utm_medium || 'QR Code'));
          dispatch(setUtmCampaignName(el?.custom?.utm_campaign_name || ''));
          if (Object.values(el?.custom?.custom_utms || {}).length) {
            dispatch(setCustomUtms(el?.custom?.custom_utms));
          } else {
            dispatch(setCustomUtms({}));
          }
        } else if (isQR && el?.name !== 'qr') {
          dispatch(clearQrFields());
        }
      }, [isQR, el]);

      // Handle click outside to close actions menu
      useEffect(() => {
        const handleClickOutside = (event: MouseEvent) => {
          // Close actions if clicking outside the currently open actions container
          if (isActionsOpen !== null) {
            const actionsElement = actionsRefs.current.get(isActionsOpen);
            if (
              actionsElement &&
              !actionsElement.contains(event.target as Node)
            ) {
              setIsActionsOpen(null);
            }
          }

          // V2: Handle dropdowns
          if (activeDropdown) {
            const dropdownElement = dropdownRefs.current.get(activeDropdown);
            if (
              dropdownElement &&
              !dropdownElement.contains(event.target as Node)
            ) {
              setActiveDropdown(null);
            }
          }
        };

        if (isActionsOpen !== null || activeDropdown !== null) {
          document.addEventListener('mousedown', handleClickOutside);
        }

        return () => {
          document.removeEventListener('mousedown', handleClickOutside);
        };
      }, [isActionsOpen, activeDropdown]);

      // V2: Load QR codes on mount if callbacks are provided
      useEffect(() => {
        if (onGetQRCodes) {
          loadQRCodes(1, false);
        }
      }, [onGetQRCodes, loadQRCodes]);

      // V2: Setup scroll event listener on the list container
      useEffect(() => {
        const listElement = qrCodesGridRef.current;
        if (listElement && onGetQRCodes) {
          listElement.addEventListener('scroll', handleScroll);
          return () => {
            listElement.removeEventListener('scroll', handleScroll);
            if (loadingTimeoutRef.current) {
              clearTimeout(loadingTimeoutRef.current);
            }
          };
        }
      }, [
        hasMore,
        isLoadingMore,
        isLoading,
        currentPage,
        handleScroll,
        onGetQRCodes,
      ]);

      return (
        <>
          {currentTheme === 'v2' ? (
            <>
              <div
                className="qr-section-v2-container"
                style={{
                  padding: '14px',
                }}
              >
                <div
                  className="qr-code-wrapper qr-code-wrapper-sticky"
                  onClick={() => handleDialogChange('qr-modal')}
                >
                  <QRCodeIcon />
                  <button className="qr-submit-btn-new">Create QR-Code</button>
                </div>
                <Typography variant="h6" style={noteStyles}>
                  {MESSAGES.TEMPLATE.QR_SECTION.QR_NOTE}
                </Typography>

                {/* V2 QR Codes List when callbacks are provided */}
                {onGetQRCodes && (
                  <div
                    className="qr-codes-list-scroll"
                    ref={qrCodesGridRef}
                  >
                    <div className="qr-codes-grid">
                    {isLoading ? (
                      <div className="loading-state">Loading QR codes...</div>
                    ) : qrCodes.length === 0 ? (
                      <div className="empty-state">No QR codes created yet</div>
                    ) : (
                      <>
                        {qrCodes.map((qrCode) => (
                          <div key={qrCode.id} className="qr-card" onClick={() => handleQRCodeSelect(qrCode)}>
                            <img
                              src={qrCode.qrImagePath}
                              alt="code"
                              style={{ width: '30px', height: '30px' }}
                            />
                            <div
                              className="qr-card-content"
                            >
                              <Typography
                                style={{
                                  fontWeight: '600',
                                  fontSize: '12px',
                                  color: '#545454',
                                  margin: 0,
                                }}
                              >
                                {qrCode.name}
                              </Typography>
                              <Typography
                                style={{
                                  fontWeight: '400',
                                  fontSize: '12px',
                                  color: '#54545499',
                                  margin: 0,
                                }}
                              >
                                {qrCode.status}
                              </Typography>
                            </div>
                            {(onEditQRCode || onDeleteQRCodes) && <div
                              className="actions-container"
                              ref={(el) => {
                                if (el) actionsRefs.current.set(qrCode.id, el);
                              }}
                            >
                              <div
                                className="actions"
                                onClick={(e) => { toggleActions(qrCode.id, e); e.stopPropagation(); }}
                              >
                                <img src={Actions} alt='actions' />
                              </div>
                              {/* Actions */}
                              {isActionsOpen === qrCode.id && (
                                <div
                                  className={`actions-wrapper${actionsDropdownUpward ? ' actions-wrapper-up' : ''}`}
                                >
                                  {onEditQRCode && (
                                    <div
                                      className="action-item"
                                      onClick={(e) => {
                                        e.stopPropagation();
                                        handleEditQRCode(qrCode);
                                      }}
                                    >
                                      <img src={Edit} alt="edit" />
                                      <Typography style={itemStyle}>
                                        Edit
                                      </Typography>
                                    </div>
                                  )}
                                  {onDeleteQRCodes && (
                                    <div
                                      className="action-item"
                                      onClick={(e) => {
                                        e.stopPropagation();
                                        handleOpenDeleteDialog();
                                        setSelectedQR(qrCode.id);
                                      }}
                                    >
                                      <img src={Archive} alt="Archive" />
                                      <Typography style={itemStyle}>
                                        Archive
                                      </Typography>
                                    </div>
                                  )}
                                </div>
                              )}
                            </div>}
                          </div>
                        ))}
                        {/* Loading indicator for pagination */}
                        {isLoadingMore && (
                          <div className="loading-more">
                            <div className="loading-state">
                              Loading more QR codes...
                            </div>
                          </div>
                        )}
                      </>
                    )}
                    </div>
                  </div>
                )}
              </div>
              {dialog.open && (
                <QRCodeModal
                  show={dialog.open}
                  utms={utms}
                  utmFields={utmFields}
                  isEditing={isEditing}
                  handleSelect={handleSelect}
                  handleDialogChange={handleDialogChange}
                  handleClose={handleDialogClose}
                  setUtmCampaignName={setUtmCampaignName}
                  setQrUrl={setQrUrl}
                  setUtmSource={setUtmSource}
                  setUtmMedium={setUtmMedium}
                  setCustomUtms={setCustomUtms}
                  addNewQRCode={isEditing ? updateQRCode : addNewQRCode}
                  loading={saveQrLoading}
                />
              )}
              {openDeleteDialog && (
                <DialogV2
                  icon={<ConfirmCloseIcon fill='var(--primary-color)' />}
                  customStyles={cancelDialogStylesV2}
                  open={openDeleteDialog}
                  handleClose={handleCloseDeleteDialog}
                  title='Delete QR Code'
                  subHeading=''
                  description='Are you sure you want to delete this QR code?'
                  onSubmit={() => {
                    handleDeleteQRCode(selectedQR);
                    handleCloseDeleteDialog();
                  }}
                  onCancel={handleCloseDeleteDialog}
                  cancelText='No'
                  submitText='Yes'
                  isGallery={false}
                  loading={isLoadingDelete}
                />)}
            </>
          ) : (
            <>
              <button
                className="qr-submit-btn"
                onClick={isQR ? updateQRCode : addNewQRCode}
              >
                {isQR
                  ? MESSAGES.TEMPLATE.QR_SECTION.UPDATE_BUTTON
                  : MESSAGES.TEMPLATE.QR_SECTION.SUBMIT_BUTTON}
              </button>
              <div className="qr-input-wrapper">
                <label>QR URL*:</label>
                <Input
                  type="text"
                  onChange={(e) => {
                    dispatch(setQrUrl(e.target.value));
                  }}
                  placeholder={MESSAGES.TEMPLATE.QR_SECTION.QR_PLACEHOLDER}
                  value={url}
                  qrField={true}
                />
              </div>
              <div className="qr-input-wrapper">
                <label>UTM Source:</label>
                <Input
                  type="text"
                  onChange={(e) => {
                    dispatch(setUtmSource(e.target.value));
                  }}
                  placeholder={'Enter UTM Source'}
                  value={utmSource}
                  qrField={true}
                />
              </div>
              <div className="qr-input-wrapper">
                <label>UTM Medium:</label>
                <Input
                  type="text"
                  onChange={(e) => {
                    dispatch(setUtmMedium(e.target.value));
                  }}
                  placeholder={'Enter UTM Medium'}
                  value={utmMedium}
                  qrField={true}
                />
              </div>
              <div className="qr-input-wrapper">
                <label>UTM Campaign Name*:</label>
                <Input
                  type="text"
                  onChange={(e) => {
                    dispatch(setUtmCampaignName(e.target.value));
                  }}
                  placeholder={'Enter UTM Campaign Name'}
                  value={utmCampaignName}
                  qrField={true}
                />
              </div>
              {utms?.map((utm, idx) => {
                return (
                  <div className="qr-input-wrapper" key={idx}>
                    <label>{utm.toUpperCase().replace(/\_/g, ' ')}:</label>
                    <GeneralSelect
                      placeholder={`Search / Select Custom UTM ${idx + 1}`}
                      options={utmFields as any}
                      setSelectedValue={(value: any) =>
                        handleSelect(utm, value)
                      }
                      selectedValue={customUtms[utm] || (null as any)}
                      builderSelect={true}
                      clearField={true}
                      search={true}
                      qrField={true}
                      isError={false}
                      gallerySelect={false}
                    />
                  </div>
                );
              })}
            </>
          )}
        </>
      );
    }
  ),
};

export default CustomQRCode;
