import {
  createElement,
  Fragment,
  useEffect,
  useMemo,
  useState,
} from "@wordpress/element";
import { useDispatch, useSelect } from "@wordpress/data";
import { __ } from "@wordpress/i18n";
import { registerCheckoutBlock } from "@woocommerce/blocks-checkout";
import { CheckboxControl } from "@woocommerce/blocks-components";
import { CART_STORE_KEY, PAYMENT_STORE_KEY } from "@woocommerce/block-data";
import { getSetting } from "@woocommerce/settings";
import Modal from "react-modal";
import { decodeEntities } from "@wordpress/html-entities";
import metadata from "./block.json";
import { contractInputSelector, renderContracts } from "./contracts";

const validationId = "sozlesme-onay";

const Contracts = ({ checkoutExtensionData }) => {
  const { setExtensionData } = checkoutExtensionData;
  const { setValidationErrors, clearValidationError } = useDispatch(
    "wc/store/validation",
  );
  const settings = getSetting("irem_data", {});
  const approvalRequired = Number(settings.sozlesme_ozellik_3 ?? 1) === 1;
  const firstTitle =
    settings.birinci_sozlesme_link_ismi ||
    __("Distance Sales Contract", "wc-korkmaz-contract");
  const conjunction = settings.ve_metin || __("and", "wc-korkmaz-contract");
  const secondTitle =
    settings.ikinci_sozlesme_link_ismi ||
    __("Preliminary Information Form", "wc-korkmaz-contract");
  const approvalText =
    settings.son_metin || __("I have read and agree.", "wc-korkmaz-contract");
  const firstTemplate = decodeEntities(
    settings.gsozlesmebir ||
      __(
        "The first contract text has not been added yet.",
        "wc-korkmaz-contract",
      ),
  );
  const secondTemplate = decodeEntities(
    settings.gsozlesmeiki ||
      __(
        "The second contract text has not been added yet.",
        "wc-korkmaz-contract",
      ),
  );
  const [modalOpen, setModalOpen] = useState(false);
  const [modalContent, setModalContent] = useState("");
  const [modalTitle, setModalTitle] = useState("");
  const [approved, setApproved] = useState(false);
  const [inputRevision, setInputRevision] = useState(0);
  const { validationError, validationErrorId } = useSelect(
    (select) => {
      const store = select("wc/store/validation");
      return {
        validationError: store.getValidationError(validationId),
        validationErrorId: store.getValidationErrorId(validationId),
      };
    },
    [],
  );
  const hasError = Boolean(validationError?.message && !validationError.hidden);
  const cart = useSelect((select) => select(CART_STORE_KEY)?.getCartData(), []);
  const paymentMethod = useSelect(
    (select) => select(PAYMENT_STORE_KEY).getActivePaymentMethod(),
    [],
  );
  const [firstContract, secondContract] = useMemo(
    () => cart
      ? renderContracts([firstTemplate, secondTemplate], cart, settings, paymentMethod)
      : [firstTemplate, secondTemplate],
    [cart, firstTemplate, secondTemplate, settings, paymentMethod, inputRevision],
  );

  useEffect(() => {
    setExtensionData("irem", "billing_satis_sozlesme", firstContract);
    setExtensionData("irem", "billing_mesafeli_sozlesme", secondContract);
    setExtensionData("irem", "sozlesme_onay", approved ? "1" : "0");
  }, [setExtensionData, firstContract, secondContract, approved]);

  useEffect(() => {
    if (!approvalRequired || approved) {
      clearValidationError(validationId);
    } else {
      setValidationErrors({
        [validationId]: {
          message: __(
            "You must accept the contracts to continue.",
            "wc-korkmaz-contract",
          ),
          hidden: true,
        },
      });
    }
    // Do not depend on the error object: checkout reveals it on submit. Watching
    // it would recreate a hidden error and can trigger a store update loop.
    return () => clearValidationError(validationId);
  }, [approvalRequired, approved, setValidationErrors, clearValidationError]);

  useEffect(() => {
    const onInput = (event) => {
      if (event.target?.matches?.(contractInputSelector)) {
        setInputRevision((value) => value + 1);
      }
    };
    document.addEventListener("input", onInput, true);
    document.addEventListener("change", onInput, true);
    return () => {
      document.removeEventListener("input", onInput, true);
      document.removeEventListener("change", onInput, true);
    };
  }, []);

  const openContract = (event, content, title) => {
    event.preventDefault();
    const template = document.createElement("template");
    template.innerHTML = content;
    template.content
      .querySelectorAll("script,iframe,object,embed,link,meta")
      .forEach((node) => node.remove());
    template.content.querySelectorAll("*").forEach((node) => {
      Array.from(node.attributes).forEach((attribute) => {
        if (
          /^on/i.test(attribute.name) ||
          /^javascript:/i.test(attribute.value.trim())
        ) {
          node.removeAttribute(attribute.name);
        }
      });
    });
    setModalContent(template.innerHTML);
    setModalTitle(title);
    setModalOpen(true);
  };

  const closeModal = () => setModalOpen(false);
  return (
    <>
      <div className="ozel-sozlesmeler-wrapper">
        <CheckboxControl
          id="ozel_sozlesmeler"
          label={
            <>
              <a
                href="#korkmaz-contract-first"
                className="kc-block-contract-link"
                aria-haspopup="dialog"
                onClick={(event) => openContract(event, firstContract, firstTitle)}
              >
                {firstTitle}
              </a>{" "}
              {conjunction}{" "}
              <a
                href="#korkmaz-contract-second"
                className="kc-block-contract-link"
                aria-haspopup="dialog"
                onClick={(event) => openContract(event, secondContract, secondTitle)}
              >
                {secondTitle}
              </a>{" "}
              {approvalText}
            </>
          }
          checked={approved}
          onChange={setApproved}
          // WooCommerce focuses the first invalid field after failed checkout.
          // CheckboxControl adds .has-error and aria-invalid through this prop.
          hasError={hasError}
          aria-describedby={hasError ? validationErrorId : undefined}
        />
        {hasError && (
          <div
            id={validationErrorId}
            className="wc-block-components-validation-error"
            role="alert"
          >
            {validationError.message}
          </div>
        )}
      </div>
      <Modal
        isOpen={modalOpen}
        contentLabel={modalTitle}
        onRequestClose={closeModal}
        appElement={document.querySelector(".wp-block-woocommerce-checkout")}
        className="kc-block-contract-modal"
        overlayClassName="kc-block-contract-overlay"
      >
        <div className="kc-block-contract-modal__header">
          <button type="button" onClick={closeModal}>
            {__("Close", "wc-korkmaz-contract")}
          </button>
        </div>
        <div className="kc-block-contract-modal__content" dangerouslySetInnerHTML={{ __html: modalContent }} />
      </Modal>
    </>
  );
};

// A named PHP placeholder preserves the editor position; WooCommerce owns
// rendering and validation through its official checkout extension API.
registerCheckoutBlock({ metadata, component: Contracts });
