/**
 * @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md.
 */

import { BaseComponent } from './base-component';
import { copyToClipboard } from '../helpers/copy-to-clipboard';

/**
 * HeadingLink component.
 * Handles copying heading links to clipboard when clicked.
 */
export class HeadingLink extends BaseComponent {
	/**
	 * Creates a heading link component.
	 *
	 * @param element - The heading link DOM element
	 */
	constructor( element ) {
		super( {
			isCopied: false
		} );

		this.elements = {
			link: element,
			heading: element.closest( '.b-heading' ),
			tooltipText: null
		};

		this.timeoutId = null;
		this.originalTooltipText = null;
	}

	/**
	 * Attaches heading link functionality to all elements with js-heading-link class.
	 */
	static attach() {
		const headingLinks = document.querySelectorAll( '.js-heading-link' );

		for ( const link of headingLinks ) {
			new HeadingLink( link ).init();
		}
	}

	/**
	 * Initializes the heading link component.
	 */
	init() {
		this.elements.link.addEventListener( 'click', this.handleClick.bind( this ) );

		const tooltipId = this.elements.link.getAttribute( 'aria-labelledby' );

		if ( tooltipId ) {
			const tooltip = document.getElementById( tooltipId );
			const tooltipText = tooltip?.querySelector( '.c-tooltip-popover__text' );

			if ( tooltipText ) {
				this.elements.tooltipText = tooltipText;
				this.originalTooltipText = tooltipText.textContent;
			}
		}

		this.render();
	}

	/**
	 * Handles click events on the heading link.
	 *
	 * @param event - The click event object
	 */
	handleClick( event ) {
		event.preventDefault();

		// If the heading is not in the bottom third of the viewport,
		// prevent scrolling by stopping propagation
		const headingRect = this.elements.heading.getBoundingClientRect();

		if ( headingRect.top < window.innerHeight * 0.75 ) {
			event.stopPropagation();
		}

		const href = this.elements.link.getAttribute( 'href' );
		const absoluteUrl = new URL( window.location.href );

		// Update only the hash part of the URL
		absoluteUrl.hash = href;

		// Update the browser's URL hash
		window.history.replaceState( null, null, href );

		copyToClipboard( absoluteUrl.toString() )
			.then( () => {
				this.setState( { isCopied: true } );

				// Reset the copied state after a delay
				clearTimeout( this.timeoutId );
				this.timeoutId = setTimeout( () => {
					this.setState( { isCopied: false } );
				}, 2000 );
			} )
			.catch( error => {
				console.error( 'Failed to copy URL to clipboard:', error );
			} );
	}

	/**
	 * Renders the heading link component based on current state.
	 *
	 * @param prevState - Previous component state
	 * @param state - Current component state
	 */
	render( prevState, state = this.state ) {
		const { link, tooltipText } = this.elements;

		if ( prevState?.isCopied !== state.isCopied ) {
			if ( state.isCopied ) {
				link.setAttribute( 'aria-label', 'Link copied to clipboard!' );
				link.classList.add( 'is-copied' );

				// Update tooltip text if available
				if ( tooltipText ) {
					tooltipText.textContent = 'Copied!';
				}
			} else {
				link.removeAttribute( 'aria-label' );
				link.classList.remove( 'is-copied' );

				// Restore original tooltip text if available
				if ( tooltipText && this.originalTooltipText ) {
					tooltipText.textContent = this.originalTooltipText;
				}
			}
		}
	}
}
