import { getSetting } from '@woocommerce/settings';
import { createElement, useState, useEffect } from '@wordpress/element';
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
import { __ } from '@wordpress/i18n';

// ============================================
// Configuration & Constants
// ============================================

const identifier = 'ipag-gateway_boleto';
const settings = getSetting(`${identifier}_data`, {});
const labelText = settings.title || 'Pague com Boleto Bancário';
const defaultDescription = 'Confirm your order to view the boleto.';
const rawDescription = settings.description || defaultDescription;
const contentText =
  rawDescription === defaultDescription
    ? __(defaultDescription, 'ipag-gateway')
    : rawDescription;

const DIGITS_ONLY = /\D/g;

function isValidDocument(document) {
  const digits = (document || '').replace(DIGITS_ONLY, '');

  if (digits.length === 11) {
    return window.isCpf ? window.isCpf(digits) : true;
  } else if (digits.length === 14) {
    return window.isCnpj ? window.isCnpj(digits) : true;
  }

  return false;
}

// ============================================
// UI Components
// ============================================

const Label = ({ components }) => {
  const { PaymentMethodLabel } = components;

  return createElement(
    'div',
    { className: 'ipag-label-with-badge' },
    createElement(PaymentMethodLabel, {
      className: 'ipag-gateway-boleto-label',
      text: labelText,
    }),
    createElement('img', {
      src: settings.assets_url
        ? `${settings.assets_url}../images/ipag.png`
        : '/wp-content/plugins/ipag-gateway/images/ipag.png',
      alt: 'iPag',
      className: 'ipag-label-badge',
      title: 'Pagamentos seguros com iPag',
    }),
  );
};

const Content = ({ eventRegistration, emitResponse }) => {
  const [document, setDocument] = useState('');
  const [errors, setErrors] = useState({
    document: '',
  });

  const { onPaymentSetup } = eventRegistration;
  const requirePagSeguro = !!settings.requirePagSeguro;
  const requireDocument = settings.require_document === 'yes';

  const emitResponseError = emitResponse?.responseTypes?.ERROR;
  const emitResponseSuccess = emitResponse?.responseTypes?.SUCCESS;
  const emitResponseNoticePayments = emitResponse?.noticeContexts?.PAYMENTS;

  useEffect(() => {
    const unsubscribe = onPaymentSetup(() => {
      const validationErrors = {};

      // Validate document if required
      if (requireDocument) {
        const documentDigits = document.replace(DIGITS_ONLY, '');

        if (!documentDigits) {
          validationErrors.document = 'CPF/CNPJ é obrigatório';
        } else if (
          documentDigits.length !== 11 &&
          documentDigits.length !== 14
        ) {
          validationErrors.document =
            'CPF deve ter 11 dígitos ou CNPJ deve ter 14 dígitos';
        } else if (!isValidDocument(documentDigits)) {
          validationErrors.document =
            documentDigits.length === 11 ? 'CPF inválido' : 'CNPJ inválido';
        }
      }

      // Validate PagSeguro hash if required
      if (requirePagSeguro && !window.ipagBoletoHash) {
        validationErrors.pagseguro =
          'Erro ao carregar dados do PagSeguro. Tente novamente.';
      }

      if (Object.keys(validationErrors).length > 0) {
        setErrors(validationErrors);

        return {
          type: emitResponse.responseTypes.ERROR,
          message: 'Por favor, corrija os erros no formulário.',
          messageContext: emitResponse.noticeContexts.PAYMENTS,
        };
      }

      setErrors({});

      const paymentData = {
        ipag_woo_payments_blocks: 'yes',
        ipag_boleto_document: document.replace(DIGITS_ONLY, ''),
      };

      if (window.ipagBoletoHash) {
        paymentData.boleto_hashpagseguro = window.ipagBoletoHash;
      }

      return {
        type: emitResponseSuccess,
        meta: {
          paymentMethodData: paymentData,
        },
      };
    });

    return unsubscribe;
  }, [
    document,
    onPaymentSetup,
    requireDocument,
    requirePagSeguro,
    emitResponseError,
    emitResponseSuccess,
    emitResponseNoticePayments,
  ]);

  const handleDocumentInput = (e) => {
    const v = String(e.target.value).replace(DIGITS_ONLY, '');

    if (errors.document) {
      setErrors((prev) => ({ ...prev, document: '' }));
    }

    if (v.length > 11) {
      setDocument(window.maskCnpj(v));
      return;
    }

    setDocument(window.maskCpf(v));
  };

  return createElement(
    'div',
    { className: 'ipag-gateway-credit-form' },
    createElement(
      'div',
      { className: 'ipag-boleto-description' },
      createElement('p', {}, contentText),
    ),

    requireDocument &&
      createElement(
        'p',
        {
          style: { marginTop: '1.25rem' },
          className:
            'form-row' + (errors.document ? ' woocommerce-invalid' : ''),
        },
        createElement(
          'label',
          { htmlFor: 'ipag_boleto_document' },
          __('CPF/CNPJ', 'ipag-gateway'),
          createElement(
            'abbr',
            { className: 'required', title: 'Digite seu CPF ou CNPJ' },
            '*',
          ),
        ),
        createElement('input', {
          type: 'text',
          className:
            'input-text input-ipag' +
            (errors.document ? ' woocommerce-invalid' : ''),
          name: 'ipag_boleto_document',
          id: 'ipag_boleto_document',
          maxLength: 18,
          placeholder: __('Digite seu CPF ou CNPJ', 'ipag-gateway'),
          inputMode: 'numeric',
          value: document,
          onInput: handleDocumentInput,
        }),
        errors.document &&
          createElement(
            'span',
            {
              className: 'woocommerce-error',
              role: 'alert',
            },
            errors.document,
          ),
      ),
  );
};

// ============================================
// Payment Method Registration
// ============================================

registerPaymentMethod({
  name: identifier,
  label: createElement(Label),
  content: createElement(Content),
  edit: createElement(Content),
  canMakePayment: () => true,
  ariaLabel: labelText,
  shouldSavePaymentMethod: () => false,
});
