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

const { ModuleContainer, StyleContainer, elementClassnames } = window?.divi?.module || {};

const getPreviewConfig = () => {
  if (window?.BRWWLDivi5Preview) {
    return window.BRWWLDivi5Preview;
  }
  const scriptSrc = document?.currentScript?.src;
  if (!scriptSrc) {
    return {};
  }
  const params = new URL(scriptSrc).searchParams;
  return {
    ajaxUrl: decodeURIComponent(params.get('brwwl_ajax_url') || ''),
    action: params.get('brwwl_action') || '',
    nonce: params.get('brwwl_nonce') || '',
  };
};

const previewConfig = getPreviewConfig();

const getAttributeValue = (attrs, attrName) => {
  if (!attrs) return undefined;
  if (typeof attrs?.asMutable === 'function') attrs = attrs.asMutable({ deep: true });
  let attr = attrs[attrName];
  if (typeof attr?.asMutable === 'function') attr = attr.asMutable({ deep: true });
  if (attr?.innerContent?.desktop?.value !== undefined) return attr.innerContent.desktop.value;
  if (attr?.innerContent?.desktop !== undefined && typeof attr.innerContent.desktop !== 'object') return attr.innerContent.desktop;
  if (attr !== undefined && typeof attr !== 'object') return attr;
  return undefined;
};

const isAddToCartVisible = (context = {}) => {
  const type = getAttributeValue(context.attrs, 'widget_type');
  return type !== undefined && type !== 'default';
};

const normalizeMetadataFields = (metadata) => {
  if (metadata.name !== 'brwwl/wish-wait-products') return metadata;
  const field = metadata?.attributes?.add_to_cart?.settings?.innerContent?.item;
  if (field) {
    field.show_if = {
      widget_type: ['image', 'image_title', 'image_title_price', 'title', 'title_price', 'slider', 'slider_title'],
    };
    field.visible = isAddToCartVisible;
  }
  return metadata;
};

const Placeholder = ({ title, children }) => (
  <div style={{ padding: '2em 0', background: '#6c2eb9', color: '#fff', fontSize: '12px', fontWeight: '600', textAlign: 'center', borderRadius: '1em' }}>
    <h3 style={{ color: '#000', fontWeight: '900' }}>{title}</h3>
    {children}
  </div>
);

const initializePreview = (moduleName) => {
  if (!window.jQuery) return;
  const $ = window.jQuery;
  if (moduleName === 'brwwl/wish-wait-products' && typeof $.fn.unslider === 'function') {
    $('.brcs_slider').not('.brwwl_divi5_slider_ready').unslider({
      arrows: { prev: '<a class="unslider-arrow prev"></a>', next: '<a class="unslider-arrow next"></a>' },
      autoplay: true,
    }).addClass('brwwl_divi5_slider_ready');
  }
  if (moduleName === 'brwwl/wish-wait-list') {
    $('.berocket_ww_container').each(function initList() {
      const $container = $(this);
      const $list = $container.find('.berocket_ww_list');
      const $items = $container.find('.berocket_ww_ul_container');
      const $showAll = $container.find('.berocket_ww_show_all');
      if ($showAll.length && $container.height() + 20 < $items.height()) {
        $showAll.show();
      } else if (!$showAll.length) {
        $list.css({ maxHeight: 'initial' });
      }
    });
  }
};

const WishWaitPreview = ({ attrs, metadata }) => {
  const [state, setState] = useState({ html: '', isLoading: true, error: '' });
  const attrsKey = useMemo(() => JSON.stringify(attrs ?? {}), [attrs]);

  useEffect(() => {
    if (!previewConfig.ajaxUrl || !previewConfig.action || !previewConfig.nonce) {
      setState({ html: '', isLoading: false, error: `${metadata.title} is not displayed in Builder` });
      return undefined;
    }
    const controller = new AbortController();
    const body = new FormData();
    body.append('action', previewConfig.action);
    body.append('nonce', previewConfig.nonce);
    body.append('module_name', metadata.name);
    body.append('attrs', attrsKey);
    setState((current) => ({ ...current, isLoading: true, error: '' }));
    fetch(previewConfig.ajaxUrl, { body, method: 'POST', credentials: 'same-origin', signal: controller.signal })
      .then((response) => response.json())
      .then((response) => {
        if (!response?.success) throw new Error(response?.data?.message || `${metadata.title} is not displayed in Builder`);
        setState({ html: response?.data?.html || '', isLoading: false, error: '' });
      })
      .catch((error) => {
        if (error.name !== 'AbortError') setState({ html: '', isLoading: false, error: error.message || `${metadata.title} is not displayed in Builder` });
      });
    return () => controller.abort();
  }, [attrsKey, metadata.name, metadata.title]);

  useEffect(() => {
    if (!state.isLoading && !state.error && state.html) initializePreview(metadata.name);
  }, [state.html, state.isLoading, state.error, metadata.name]);

  if (state.isLoading) return <div className="et-fb-loader-wrapper"><div className="et-fb-loader" /></div>;
  if (state.error || !state.html) return <Placeholder title={metadata.title}>{state.error || `${metadata.title} has no content to display`}</Placeholder>;
  return <div dangerouslySetInnerHTML={{ __html: state.html }} />;
};

export const createWishWaitModule = (moduleMetadata, styleAttrs) => {
  const metadata = normalizeMetadataFields(moduleMetadata);
  const ModuleStyles = ({ elements, settings, mode, state, noStyleTag }) => (
    <StyleContainer mode={mode} state={state} noStyleTag={noStyleTag}>
      {elements.style({ attrName: 'module', styleProps: { disabledOn: { disabledModuleVisibility: settings?.disabledModuleVisibility } } })}
      {styleAttrs.map((attrName) => <React.Fragment key={attrName}>{elements.style({ attrName })}</React.Fragment>)}
    </StyleContainer>
  );
  const ModuleScriptData = ({ elements }) => <React.Fragment>{elements.scriptData({ attrName: 'module' })}</React.Fragment>;
  const moduleClassnames = ({ classnamesInstance, attrs }) => classnamesInstance.add(elementClassnames({ attrs: attrs?.module?.decoration ?? {} }));
  return {
    metadata,
    renderers: {
      edit: ({ attrs, id, name, elements }) => (
        <ModuleContainer attrs={attrs} elements={elements} id={id} moduleClassName={metadata.moduleClassName} name={name}
          scriptDataComponent={ModuleScriptData} stylesComponent={ModuleStyles} classnamesFunction={moduleClassnames}>
          {elements.styleComponents({ attrName: 'module' })}
          {styleAttrs.map((attrName) => <React.Fragment key={attrName}>{elements.styleComponents({ attrName })}</React.Fragment>)}
          <div className="et_pb_module_inner"><WishWaitPreview attrs={attrs} metadata={metadata} /></div>
        </ModuleContainer>
      ),
    },
    placeholderContent: {
      module: { meta: { adminLabel: { desktop: { value: metadata.title } } } },
      ...metadata.defaultAttrs,
    },
  };
};
