import Loader from "./loader.js";
import { showErrorModal, showSuccessModal } from "./modals.js";
import fetchData from "../http/http.js";

class Form {
   static hideFormErrors(form) {
      form.querySelectorAll(".js-required").forEach((field) => {
         this.clearFieldError(field, form);
      });
   }

   static initRules(form, formData) {
      const requiredFields = form.querySelectorAll(".js-required");

      if (requiredFields.length) {
         const required = {};
         requiredFields.forEach((el) => {
            required[el.name] = JSON.parse(el.dataset.rules);
         });

         const strRules = JSON.stringify(required);

         formData.append("validate_rules", strRules);
      }

      return formData;
   }

   static showFormErrors(errors, form) {
      const errorContainer = form.querySelector(".error-text");

      if (!errorContainer) return;

      errorContainer.innerHTML = "";

      Object.values(errors).forEach((text) => {
         const item = document.createElement("div");

         item.textContent = text;

         errorContainer.append(item);
      });
   }

   static initForms(defaultForms = null) {
      const forms = defaultForms || document.querySelectorAll(".js-form");
      forms.forEach((form) => {
         this.initFieldListeners(form);

         form.addEventListener("submit", (event) => {
            this.formSubmitHandler(event, {
               beforeSend: (formData) => {
                  Loader.showButtonLoader(form);
               },
               finallySend: () => {
                  Loader.hideButtonLoader(form);
               },
            });
         });
      });

      document.querySelectorAll("#category-filter input[type=checkbox]").forEach((input) => {
         input.addEventListener("change", function () {
            console.log(input);

            const form = document.getElementById("category-filter");
            const event = new Event("change", { bubbles: true });
            form.dispatchEvent(event);
         });
      });
   }

   static initFieldListeners(form) {
      const fields = form.querySelectorAll(".js-required");

      fields.forEach((field) => {
         field.addEventListener("input", () => {
            this.clearFieldError(field, form);
         });
      });
   }

   static clearFieldError(field, form) {
      const parent = field.parentElement;

      parent.classList.remove("error");

      const hasErrors = form.querySelectorAll(".error").length > 0;
      if (!hasErrors) {
         const errorContainer = form.querySelector(".error-text");
         if (errorContainer) errorContainer.innerHTML = "";
      }
   }

   static fieldValidators = {
      fio: (value, rules) => {
         if (!value) return "Укажите ваше имя";
         if (value.length < Number(rules.minLength || 2)) return "Имя не короче 2 символов";
         return null;
      },
      phone: (value) => {
         if (!value) return "Введите номер телефона";
         if (value.replace(/\D/g, "").length !== 11) return "Введите корректный номер телефона";
         return null;
      },
      email: (value) => {
         if (!value) return "Введите email";
         if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return "Введите корректный email";
         return null;
      },
   };

   static validateForm(form) {
      let isValid = true;
      const errors = {};

      form.querySelectorAll(".js-required").forEach((field) => {
         const rules = JSON.parse(field.dataset.rules || "{}");
         const value = field.value.trim();
         const fieldName = field.name;

         const validator = this.fieldValidators[fieldName] ?? ((v) => (!v ? "Поле обязательно для заполнения" : null));

         const error = validator(value, rules);

         if (error) {
            isValid = false;
            errors[fieldName] = error;
            field.parentElement.classList.add("error");
         }
      });

      this.showFormErrors(errors, form);

      return isValid;
   }

   /**
    *
    * @param {Event} e
    */
   static async formSubmitHandler(e, callBack = null) {
      e.preventDefault();

      const form = e.target;
      let formData = new FormData(form);

      this.hideFormErrors(form);

      if (!this.validateForm(form)) return;

      formData = this.initRules(form, formData);
      formData.append("action", form.dataset.action ?? "form_submit");

      console.log([...formData.entries()]);

      const props = {
         bubbles: true,
      };

      callBack?.beforeSend?.(formData);
      const dataCallTouch = Object.fromEntries(formData);

      try {
         const response = await fetchData(formData);
         if (response.success) {
            form.reset();
            this.handleSuccess(form, response, formData, callBack);
         } else {
            this.handleError(response, form, callBack);
         }
      } finally {
         callBack?.finallySend?.();
      }
   }

   static handleSuccess(form, response, formData, callBack) {
      if (callBack?.afterSend) {
         callBack.afterSend(response);
         return;
      }

      // закрываем попап если открыт
      lightbox?.close();
      showSuccessModal();

      document.dispatchEvent(
         new CustomEvent("lz-form-submit-success", {
            bubbles: true,
            detail: {
               form,
               response,
               action: form.dataset.action,
               dataCallTouch: Object.fromEntries(formData),
            },
         }),
      );
   }

   static handleError(response, form, callBack) {
      if (callBack?.afterError) {
         callBack.afterError(response);
         return;
      }

      const errors = response.data;
      if (errors?.message) showErrorModal();
      this.showFormErrors(errors, form);
   }
}

export { Form };
