import { observer } from 'mobx-react';
import { Panel, PanelStyles } from '../components/panel/Panel';
import React, { CSSProperties, useEffect } from 'react';
import { BoxSizeStyles } from '../styles/defaults/themes.interface';
import { View } from '..';
import { makeAutoObservable } from 'mobx';
import { ApphouseComponent } from '../components/component.interfaces';

export interface AccordionStyles {
  container: CSSProperties;
  panel: PanelStyles;
}

export interface AccordionItem {
  id: number;
  title: string;
  content: React.ReactNode;
}
/**
 * Represents the props for the Accordion component.
 */
export interface AccordionProps extends ApphouseComponent<AccordionStyles> {
  /**
   * An array of Accordions.
   */
  items: AccordionItem[];
  /**
   * The visual size of the Accordion component.
   * @default 'm'
   */
  size?: keyof BoxSizeStyles;
  /**
   * The index of the Accordion item to be opened by default.
   * @default -1 (no Accordion item is open by default)
   */
  openIndex?: number;
  /**
   * A callback function that is called when an Accordion is expanded.
   * @param id the id of the Accordion that was expanded
   * @returns
   */
  onExpand?: (id: number) => void;
  /**
   * If true, the Accordion will have no borders.
   */
  borderless?: boolean;
  /**
   * If true, the Accordion will have no chevron icon.
   * @default false (the Accordion will have chevron icon)
   */
  hideIcon?: boolean;
}

/**
 * A class to manage the state of the Accordion component.
 */
class AccordionState {
  /**
   * The indexes of the open Accordion items.
   */
  openIndexes: number[];
  constructor() {
    /**
     * All the indexes of the Accordion items that are open.
     */
    this.openIndexes = [];
    makeAutoObservable(this);
  }
  /**
   * Sets the indexes of the Accordion item to be opened.
   * @param index The index of the Accordion item to be opened.
   */
  setOpenIndexes = (indexes: number[]) => {
    this.openIndexes = indexes;
  };

  /**
   * toggles the index of the Accordion item to be opened.
   * @param index The index of the Accordion item to be opened.
   */
  toggleOpenIndex = (index: number) => {
    if (this.openIndexes.includes(index)) {
      this.openIndexes = this.openIndexes.filter((i) => i !== index);
    } else {
      this.openIndexes = [...this.openIndexes, index];
    }
  };

  /**
   * Checks if an Accordion item is open.
   */
  isOpen = (index: number) => {
    return this.openIndexes.includes(index);
  };
}

const accordion = new AccordionState();

/**
 * The Accordion component displays a list of frequently asked questions.
 * @component
 * @param {AccordionProps} props - The props for the Accordion component.
 * @returns {React.FC} A React functional component.
 */
export const Accordion: React.FC<AccordionProps> = observer((props) => {
  const {
    size = 'm',
    openIndex = -1,
    styleOverwrites,
    borderless,
    hideIcon
  } = props;
  const { items } = props;

  useEffect(() => {
    if (openIndex === -1) {
      accordion.setOpenIndexes([]);
    } else {
      accordion.setOpenIndexes([openIndex]);
    }
  }, [openIndex]);
  return (
    <View
      orientation="vertical"
      styleOverwrites={styleOverwrites?.container}
      gutters={0}
      gap={0}
    >
      {items.map((item, i) => (
        <Panel
          size={size}
          expanded={accordion.isOpen(i)}
          hideIcon={hideIcon}
          borderless={borderless}
          onExpand={() => {
            accordion.toggleOpenIndex(i);
          }}
          styleOverwrites={styleOverwrites?.panel}
          key={item.id}
          title={item.title}
        >
          {item.content}
        </Panel>
      ))}
    </View>
  );
});
