import { CLASS_ACCORDION_TOGGLE, CLASS_MENU_SECTION } from "./constants";

const MOBILE_MEDIA_QUERY = "(max-width: 479.98px)";

interface FooterSection {
  element: HTMLElement;
  toggle: HTMLButtonElement | null;
  panel: HTMLElement | null;
}

export default class Footer {
  element!: HTMLElement;
  sections!: FooterSection[];
  mediaQueryList!: MediaQueryList;
  onToggleClick!: (event: Event) => void;
  onMediaQueryChange!: () => void;

  constructor(element: HTMLElement) {
    if ((element as any).ODS_Footer) {
      return (element as any).ODS_Footer;
    }

    this.element = element;
    this.sections = [];
    this.mediaQueryList = window.matchMedia(MOBILE_MEDIA_QUERY);

    this.onToggleClick = this.handleToggleClick.bind(this);
    this.onMediaQueryChange = this.syncViewportState.bind(this);

    (this.element as any).ODS_Footer = this;

    this.init();
    return this;
  }

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

  init(): void {
    this.sections = Array.from(
      this.element.querySelectorAll(
        `[data-footer-section].${CLASS_MENU_SECTION}`,
      ),
    ).map((section) => {
      const toggle = section.querySelector(
        `.${CLASS_ACCORDION_TOGGLE}`,
      ) as HTMLButtonElement | null;
      const panelId = toggle?.getAttribute("aria-controls");
      const panel = panelId
        ? (this.element.querySelector(`#${panelId}`) as HTMLElement | null)
        : null;

      if (toggle) {
        toggle.addEventListener("click", this.onToggleClick);
      }

      return {
        element: section as HTMLElement,
        toggle,
        panel,
      };
    });

    this.mediaQueryList.addEventListener("change", this.onMediaQueryChange);

    this.syncViewportState();
  }

  private setSectionState(section: FooterSection, isExpanded: boolean): void {
    if (!section.toggle || !section.panel) return;

    section.toggle.setAttribute("aria-expanded", String(isExpanded));
    section.panel.hidden = !isExpanded;
  }

  private syncViewportState(): void {
    const isMobile = this.mediaQueryList.matches;

    this.sections.forEach((section, index) => {
      if (!section.toggle || !section.panel) return;

      if (!isMobile) {
        this.setSectionState(section, true);
        section.element.removeAttribute("data-footer-mobile-initialized");
        return;
      }

      const isInitialized =
        section.element.getAttribute("data-footer-mobile-initialized") ===
        "true";

      if (!isInitialized) {
        this.setSectionState(section, index === 0);
        section.element.setAttribute("data-footer-mobile-initialized", "true");
        return;
      }

      const isExpanded =
        section.toggle.getAttribute("aria-expanded") === "true";
      this.setSectionState(section, isExpanded);
    });
  }

  private handleToggleClick(event: Event): void {
    if (!this.mediaQueryList.matches) return;

    const toggle = event.currentTarget as HTMLButtonElement;
    const section = this.sections.find((item) => item.toggle === toggle);

    if (!section || !section.toggle) return;

    const isExpanded = section.toggle.getAttribute("aria-expanded") === "true";
    this.setSectionState(section, !isExpanded);
  }

  destroy(): void {
    this.sections.forEach((section) => {
      if (!section.toggle) return;
      section.toggle.removeEventListener("click", this.onToggleClick);
    });

    this.mediaQueryList.removeEventListener("change", this.onMediaQueryChange);
  }

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