/**
 * Posts-to-PDF frontend entry point.
 *
 * Finds every `.pdfdraft-download-pdf-wrap` container injected by ButtonInjector.php
 * and mounts a React <DownloadButton> inside it.
 *
 * Core elements are registered here so the PDF exporter can call toHTML()
 * on each element type during generation.
 */
import { registerCategories, registerElements } from '@/editor/registry';
import {
	downloadPostPdf,
	type PostPdfGlobal,
} from '@/editor/posts-to-pdf/generatePdfFromPost';
import { useElementsStore } from '@pdfdraft/elements';
import React from 'react';
import { createRoot } from 'react-dom/client';
import { DownloadButton } from './DownloadButton';

declare global {
	interface Window {
		__PDFDRAFT_DYNAMIC_PDFS__?: Record<string, PostPdfGlobal>;
	}
}

const isDevelopment = process.env.NODE_ENV === 'development';
const DYNAMIC_DOWNLOAD_STYLE_ID = 'pdfdraft-dynamic-download-styles';

function ensureDynamicDownloadStyles(): void {
	if (document.getElementById(DYNAMIC_DOWNLOAD_STYLE_ID)) return;

	const style = document.createElement('style');
	style.id = DYNAMIC_DOWNLOAD_STYLE_ID;
	style.textContent = `
[data-pdfdraft-download]{text-align:center;box-sizing:border-box;}
.pdfdraft-dl-spinner{display:none;width:1em;height:1em;border:.15em solid currentColor;border-top-color:transparent;border-radius:50%;animation:pdfdraft-spin .65s linear infinite;vertical-align:middle;margin-left:.45em;}
[data-pdfdraft-download].pdfdraft-loading{opacity:.7;pointer-events:none;cursor:default;}
[data-pdfdraft-download].pdfdraft-loading .pdfdraft-dl-spinner{display:inline-block;}
@keyframes pdfdraft-spin{to{transform:rotate(360deg);}}
`;
	document.head.appendChild(style);
}

function ensureDynamicDownloadSpinner(btn: HTMLElement): void {
	if (btn.querySelector('.pdfdraft-dl-spinner')) return;

	const label = (btn.textContent ?? '').trim() || 'Download PDF';
	btn.textContent = '';

	const text = document.createElement('span');
	text.className = 'pdfdraft-dl-text';
	text.textContent = label;

	const spinner = document.createElement('span');
	spinner.className = 'pdfdraft-dl-spinner';
	spinner.setAttribute('aria-hidden', 'true');

	btn.append(text, spinner);
}

function ensureCoreElementsRegistered(): void {
	const { get, getCategory } = useElementsStore.getState().actions;
	if (getCategory('core') && get('text')) {
		return;
	}

	try {
		registerCategories();
		registerElements();
	} catch {
	}
}

// Register core element serializers (needed for PDF rendering)
ensureCoreElementsRegistered();

function mountButtons(): void {
	const wraps = document.querySelectorAll<HTMLElement>('.pdfdraft-posts-to-pdf-wrap');

	document.querySelectorAll<HTMLElement>('[data-pdfdraft-dynamic-download="1"]').forEach((btn) => {
		if (btn.dataset.pdfdraftMounted === '1') return;

		const configId = btn.dataset.pdfdraftConfigId ?? '';
		const config = configId ? window.__PDFDRAFT_DYNAMIC_PDFS__?.[configId] : undefined;
		if (!config) return;

		ensureDynamicDownloadStyles();
		ensureDynamicDownloadSpinner(btn);
		btn.dataset.pdfdraftMounted = '1';
		btn.addEventListener('click', (event) => {
			event.preventDefault();
			if (btn.classList.contains('pdfdraft-loading')) return;

			btn.classList.add('pdfdraft-loading');
			btn.setAttribute('aria-busy', 'true');
			void downloadPostPdf(config, Number(btn.dataset.postId || config.postId || 0))
				.catch(() => {})
				.finally(() => {
					btn.classList.remove('pdfdraft-loading');
					btn.removeAttribute('aria-busy');
				});
		});
	});

	wraps.forEach((wrap) => {
		const btn = wrap.querySelector<HTMLElement>(
			'button[data-post-id]:not([data-pdfdraft-dynamic-download])',
		);
		if (!btn) {
			// Some shortcode variants intentionally render a direct download <a>
			// (for template_id/design_id), so React mounting is not required.
			return;
		}

		const postId     = parseInt(btn.dataset.postId ?? '0', 10);
		const datasetText = (btn.dataset.buttonText ?? '').trim();
		const innerText   = (btn.textContent ?? '').trim();
		const buttonText  = datasetText || innerText || 'Download PDF';
		const cssClass    = btn.dataset.cssClass ?? '';

		// Replace the server-rendered button with a React-controlled one
		btn.remove();

		const root = createRoot(wrap);
		root.render(
			<DownloadButton
				postId={postId}
				buttonText={buttonText}
				className={cssClass}
			/>,
		);
	});
}

// Mount immediately if DOM is ready, otherwise wait for DOMContentLoaded
if (document.readyState === 'loading') {
	document.addEventListener('DOMContentLoaded', mountButtons);
} else {
	mountButtons();
}
