/**
 * KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
 * Copyright 2025 by Keenthemes Inc
 */

import KTData from '../../helpers/data';
import KTDom from '../../helpers/dom';
import KTComponent from '../component';
import { KTCollapseInterface, KTCollapseConfigInterface } from './types';

export class KTCollapse extends KTComponent implements KTCollapseInterface {
	protected override _name: string = 'collapse';
	protected override _defaultConfig: KTCollapseConfigInterface = {
		hiddenClass: 'hidden',
		activeClass: 'active',
		target: '',
	};
	protected override _config: KTCollapseConfigInterface = this._defaultConfig;
	protected _isAnimating: boolean = false;
	protected _targetElement: HTMLElement;

	constructor(element: HTMLElement, config?: KTCollapseConfigInterface) {
		super();

		if (KTData.has(element as HTMLElement, this._name)) return;

		this._init(element);
		this._buildConfig(config);

		this._targetElement = this._getTargetElement();
		if (!this._targetElement) {
			return;
		}

		this._handlers();
	}

	private _getTargetElement(): HTMLElement | null {
		return (
			KTDom.getElement(
				this._element.getAttribute('data-kt-collapse') as string,
			) || KTDom.getElement(this._getOption('target') as string)
		);
	}

	protected _isOpen(): boolean {
		return this._targetElement.classList.contains(
			this._getOption('activeClass') as string,
		);
	}

	protected _handlers(): void {
		this._element.addEventListener('click', (event: Event) => {
			event.preventDefault();

			this._toggle();
		});
	}

	protected _expand(): void {
		if (this._isAnimating || this._isOpen()) {
			return;
		}

		const payload = { cancel: false };
		this._fireEvent('expand', payload);
		this._dispatchEvent('expand', payload);
		if (payload.cancel === true) {
			return;
		}

		if (this._element) {
			this._element.setAttribute('aria-expanded', 'true');
			this._element.classList.add(this._getOption('activeClass') as string);
		}
		this._targetElement.classList.remove(
			this._getOption('hiddenClass') as string,
		);
		this._targetElement.classList.add(this._getOption('activeClass') as string);

		this._targetElement.style.height = '0px';
		this._targetElement.style.overflow = 'hidden';
		KTDom.reflow(this._targetElement);
		this._targetElement.style.height = `${this._targetElement.scrollHeight}px`;
		this._isAnimating = true;

		KTDom.transitionEnd(this._targetElement, () => {
			this._isAnimating = false;
			this._targetElement.style.height = '';
			this._targetElement.style.overflow = '';

			this._fireEvent('expanded');
			this._dispatchEvent('expanded');
		});
	}

	protected _collapse(): void {
		if (this._isAnimating || !this._isOpen()) {
			return;
		}

		const payload = { cancel: false };
		this._fireEvent('collapse', payload);
		this._dispatchEvent('collapse', payload);
		if (payload.cancel === true) {
			return;
		}

		if (!this._element) return;
		this._element.setAttribute('aria-expanded', 'false');
		this._element.classList.remove(this._getOption('activeClass') as string);
		this._targetElement.classList.remove(
			this._getOption('activeClass') as string,
		);

		this._targetElement.style.height = `${this._targetElement.scrollHeight}px`;
		KTDom.reflow(this._targetElement);
		this._targetElement.style.height = `0px`;
		this._targetElement.style.overflow = 'hidden';
		this._isAnimating = true;

		KTDom.transitionEnd(this._targetElement, () => {
			this._isAnimating = false;
			this._targetElement.classList.add(
				this._getOption('hiddenClass') as string,
			);
			this._targetElement.style.overflow = '';

			this._fireEvent('collapsed');
			this._dispatchEvent('collapsed');
		});
	}

	protected _toggle(): void {
		const payload = { cancel: false };
		this._fireEvent('toggle', payload);
		this._dispatchEvent('toggle', payload);
		if (payload.cancel === true) {
			return;
		}

		if (this._isOpen()) {
			this._collapse();
		} else {
			this._expand();
		}
	}

	public expand(): void {
		return this._expand();
	}

	public collapse(): void {
		return this._collapse();
	}

	public isOpen(): boolean {
		return this._isOpen();
	}

	public static getInstance(element: HTMLElement): KTCollapse {
		if (!element) return null;

		if (KTData.has(element, 'collapse')) {
			return KTData.get(element, 'collapse') as KTCollapse;
		}

		if (element.getAttribute('data-kt-collapse')) {
			return new KTCollapse(element);
		}

		return null;
	}

	public static getOrCreateInstance(
		element: HTMLElement,
		config?: KTCollapseConfigInterface,
	): KTCollapse {
		return this.getInstance(element) || new KTCollapse(element, config);
	}

	public static createInstances(): void {
		const elements = document.querySelectorAll('[data-kt-collapse]');

		elements.forEach((element) => {
			new KTCollapse(element as HTMLElement);
		});
	}

	public static init(): void {
		KTCollapse.createInstances();
	}
}

if (typeof window !== 'undefined') {
	window.KTCollapse = KTCollapse;
}
