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

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

const ModuleStyles = ({ elements, settings, mode, state, noStyleTag }) => (
  <StyleContainer mode={mode} state={state} noStyleTag={noStyleTag}>
    {elements.style({
      attrName: 'module',
      styleProps: { disabledOn: { disabledModuleVisibility: settings?.disabledModuleVisibility } },
    })}
  </StyleContainer>
);

const ModuleScriptData = ({ elements }) => (
  <React.Fragment>{elements.scriptData({ attrName: 'module' })}</React.Fragment>
);

const moduleClassnames = ({ classnamesInstance, attrs }) => {
  classnamesInstance.add(elementClassnames({ attrs: attrs?.module?.decoration ?? {} }));
};

const option = (label) => ({ label });

const getPreviewConfig = () => {
  if (window?.BRForceSellDivi5Preview) {
    return window.BRForceSellDivi5Preview;
  }
  const scriptSrc = document?.currentScript?.src;
  if (!scriptSrc) {
    return {};
  }
  const params = new URL(scriptSrc).searchParams;
  let products = {};
  try {
    products = JSON.parse(decodeURIComponent(params.get('brfs_products') || '{}'));
  } catch (error) {
    products = {};
  }
  return {
    ajaxUrl: decodeURIComponent(params.get('brfs_ajax_url') || ''),
    action: params.get('brfs_action') || '',
    nonce: params.get('brfs_nonce') || '',
    products,
  };
};

const previewConfig = getPreviewConfig();
const productOptions = Object.entries(previewConfig.products ?? {}).reduce((result, [value, label]) => ({
  ...result,
  [value]: option(label),
}), {});

const normalizeMetadataFields = (metadata) => {
  const productField = metadata?.attributes?.product_id?.settings?.innerContent?.item;
  if (productField) {
    productField.component = {
      ...productField.component,
      name: 'divi/select',
      props: {
        ...(productField.component?.props ?? {}),
        options: Object.keys(productOptions).length
          ? productOptions
          : { current: option('Current Product'), latest: option('Latest Product') },
      },
    };
  }
  return metadata;
};

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

const ForceSellPreview = ({ attrs }) => {
  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: 'Force Sell 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('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 || 'Force Sell 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 || 'Force Sell not displayed in Builder' });
        }
      });
    return () => controller.abort();
  }, [attrsKey]);

  if (state.isLoading) {
    return <div className="et-fb-loader-wrapper"><div className="et-fb-loader" /></div>;
  }
  if (state.error || !state.html) {
    return <Placeholder>{state.error || 'Force Sell not displayed in Builder'}</Placeholder>;
  }
  return <div dangerouslySetInnerHTML={{ __html: state.html }} />;
};

export const createForceSellModule = (metadata) => ({
  metadata: normalizeMetadataFields(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' })}
        <div className="et_pb_module_inner"><ForceSellPreview attrs={attrs} /></div>
      </ModuleContainer>
    ),
  },
  placeholderContent: {
    module: { meta: { adminLabel: { desktop: { value: metadata.title } } } },
    ...metadata.defaultAttrs,
  },
});
