import toggle from "../../scripts/modules/toggleUtil";

interface FeatureAccordionConfig {
  bodiesSelector: string;
  buttonSelector: string;
  imageSelector: string;
}

const defaultConfig: FeatureAccordionConfig = {
  bodiesSelector: ".accordion__body",
  buttonSelector: "[data-feature-accordion-toggle]",
  imageSelector: "[data-feature-accordion-image]",
};

export default class FeatureAccordion {
  private element: HTMLElement;
  private config: FeatureAccordionConfig;
  private bodies: HTMLElement[] = [];
  private buttons: HTMLElement[] = [];
  private images: HTMLElement[] = [];
  private activeId: string | null = null;

  constructor(element: HTMLElement, config?: Partial<FeatureAccordionConfig>) {
    this.element = element;
    this.config = { ...defaultConfig, ...config };
    (this.element as any).ODS_FeatureAccordion = this;
    this.init();
    return this;
  }

  private init(): void {
    this.bodies = Array.from(
      this.element.querySelectorAll(this.config.bodiesSelector),
    );
    this.buttons = Array.from(
      this.element.querySelectorAll(this.config.buttonSelector),
    );

    this.generateImagesFromDataAttributes();

    this.setActive(0);

    this.buttons.forEach((button) => {
      button.addEventListener("click", this.onClick);
    });
  }

  private generateImagesFromDataAttributes(): void {
    const desktopPreview = this.element.querySelector(
      ".feature-accordion__preview.show-md",
    );

    if (!desktopPreview) return;

    const existingImages = desktopPreview.querySelectorAll(
      this.config.imageSelector,
    );

    if (existingImages.length > 0) {
      this.images = Array.from(existingImages) as HTMLElement[];
      return;
    }

    this.images = [];

    this.buttons.forEach((button) => {
      const imageUrl = button.getAttribute("data-image-url");
      const imageAlt = button.getAttribute("data-image-alt") || "";
      const imageSrcSet = button.getAttribute("data-image-srcset");

      if (!imageUrl) return;

      const img = document.createElement("img");
      img.setAttribute("data-feature-accordion-image", "");
      img.src = imageUrl;
      img.alt = imageAlt;
      if (imageSrcSet) {
        img.srcset = imageSrcSet;
      }

      desktopPreview.appendChild(img);
      this.images.push(img);

      const bodyId = button.getAttribute("aria-controls");
      if (bodyId) {
        const body = document.getElementById(bodyId);
        if (body) {
          let mobilePreview = body.querySelector(
            ".feature-accordion__preview.hide-md",
          );

          if (!mobilePreview) {
            mobilePreview = document.createElement("div");
            mobilePreview.className = "feature-accordion__preview hide-md";
            body.appendChild(mobilePreview);
          }

          const mobileImg = document.createElement("img");
          mobileImg.setAttribute("data-feature-accordion-image", "");
          mobileImg.src = imageUrl;
          mobileImg.alt = imageAlt;
          mobileImg.className = "feature-accordion__image--mobile";
          if (imageSrcSet) {
            mobileImg.srcset = imageSrcSet;
          }

          mobilePreview.appendChild(mobileImg);
        }
      }
    });
  }

  private onClick = (e: Event): void => {
    const button = e.currentTarget as HTMLElement;
    const index = this.buttons.indexOf(button);
    this.setActive(index);
  };

  private setActive(index: number): void {
    if (index < 0 || index >= this.buttons.length) return;
    this.activeId = this.buttons[index].getAttribute("id");

    this.bodies.forEach((body) => {
      body.setAttribute("hidden", "");
      body.classList.remove("is-active");
    });

    this.buttons.forEach((btn) => {
      const item = btn.closest(".feature-accordion__item");
      item?.classList.remove("is-active");

      toggle({
        element: btn,
        attribute: "aria-expanded",
        value: "false",
      });
    });

    const activeBtn = this.buttons[index];
    const activeControls = activeBtn.getAttribute("aria-controls");
    const activeBody = activeControls
      ? document.getElementById(activeControls)
      : null;
    const activeItem = activeBtn.closest(".feature-accordion__item");

    if (activeBody) {
      activeBody.removeAttribute("hidden");
      activeBody.classList.add("is-active");
    }

    if (activeItem) {
      activeItem.classList.add("is-active");
    }

    toggle({
      element: activeBtn,
      attribute: "aria-expanded",
      value: "true",
    });

    this.images.forEach((img, imgIndex) => {
      img.classList.toggle("hide", imgIndex !== index);
    });
  }

  destroy(): void {
    this.buttons.forEach((button) => {
      button.removeEventListener("click", this.onClick);
    });
  }

  update(): void {
    this.destroy();
    this.init();
  }

  static getInstance(el: HTMLElement): FeatureAccordion | null {
    return el && (el as any).ODS_FeatureAccordion
      ? (el as any).ODS_FeatureAccordion
      : null;
  }
}
