import React from 'react';
import { __ } from '@wordpress/i18n';
import { SettingsSkeleton } from './settings-skeleton';
import {
	PostsToPdfSettings,
	type PostsToPdfSettingsHandle,
} from './posts-to-pdf/PostsToPdfSettings';
import { LoadingButton } from '@pdfdraft/ui/components/loading-button';
import { toast } from 'sonner';

// ─── Global type augmentation ─────────────────────────────────────────────────

declare global {
	interface Window {
		/**
		 * Save-function registry: each settings section (built-in or addon) registers
		 * a keyed async save function here. The header Save button calls all of them.
		 */
		__pdfdraftSaveFunctions?: Map<string, () => Promise<boolean>>;
		/**
		 * Localized data injected by PHP via wp_localize_script for the settings page.
		 * Contains addon sections registered via the `pdfdraft_settings_sections` filter.
		 */
		__PDFDRAFT_SETTINGS__?: {
			sections: AddonSection[];
		};
	}
}

// ─── Types ────────────────────────────────────────────────────────────────────

interface BuiltInSection {
	key: string;
	label: string;
	children?: never;
}

interface AddonSection {
	key: string;
	label: string;
	/** Sub-sections shown as nested nav items in the sidebar. */
	children?: Array<{ key: string; label: string }>;
}

type NavSection = BuiltInSection | AddonSection;

// ─── Constants ────────────────────────────────────────────────────────────────

const WP_ADMIN_BAR  = 32;
const HEADER_HEIGHT = 53;
const STICKY_TOP    = WP_ADMIN_BAR + HEADER_HEIGHT;

const BUILT_IN_SECTIONS: BuiltInSection[] = [
	{ key: 'posts-to-pdf', label: __('Posts to PDF', 'pdfdraft') },
];

const ADDON_SECTIONS: AddonSection[] =
	window.__PDFDRAFT_SETTINGS__?.sections ?? [];

const ALL_SECTIONS: NavSection[] = [...BUILT_IN_SECTIONS, ...ADDON_SECTIONS];

/**
 * Fired when a sidebar nav item (or child item) is clicked.
 * Addon sections listen for this to switch their internal active view.
 *
 * detail: { section: string; child: string | null }
 */
const NAV_EVENT = 'pdfdraft:settings:nav';

// ─── Styles ───────────────────────────────────────────────────────────────────

const headerStyle: React.CSSProperties = {
	position:     'sticky',
	top:          WP_ADMIN_BAR,
	zIndex:       50,
	display:      'flex',
	alignItems:   'stretch',
	borderBottom: '1px solid #e2e4e7',
	background:   '#fff',
	height:       `${HEADER_HEIGHT}px`,
	padding:      '0',
};

const sidebarStyle = (top: number, viewportH: number): React.CSSProperties => ({
	position:    'sticky',
	top,
	alignSelf:   'flex-start',
	width:       '220px',
	flexShrink:  0,
	height:      `${viewportH - top}px`,
	overflowY:   'auto',
	borderRight: '1px solid #e2e4e7',
	background:  '#fff',
});

// ─── Hooks ────────────────────────────────────────────────────────────────────

function useViewportHeight(): number {
	const [height, setHeight] = React.useState(() => window.innerHeight);
	React.useEffect(() => {
		const onResize = () => setHeight(window.innerHeight);
		window.addEventListener('resize', onResize);
		return () => window.removeEventListener('resize', onResize);
	}, []);
	return height;
}

// ─── Nav components ───────────────────────────────────────────────────────────

/** Top-level clickable sidebar nav item. */
function NavButton({
	active,
	onClick,
	children,
}: {
	active: boolean;
	onClick: () => void;
	children: React.ReactNode;
}) {
	return (
		<button
			type="button"
			onClick={onClick}
			style={{
				display:         'flex',
				width:           '100%',
				alignItems:      'center',
				gap:             '8px',
				borderRadius:    '6px',
				padding:         '10px 14px',
				fontSize:        '13px',
				fontWeight:      500,
				border:          'none',
				cursor:          active ? 'default' : 'pointer',
				textAlign:       'left',
				backgroundColor: active ? '#f0f6fc' : 'transparent',
				color:           active ? 'hsl(var(--primary))' : '#1d2327',
				marginBottom:    2,
				transition:      'background-color 0.1s',
			}}
		>
			{children}
		</button>
	);
}

/** Collapsible group header for sections that have children. */
function NavGroupToggle({
	expanded,
	onToggle,
	children,
}: {
	expanded: boolean;
	onToggle: () => void;
	children: React.ReactNode;
}) {
	return (
		<button
			type="button"
			onClick={onToggle}
			style={{
				display:         'flex',
				width:           '100%',
				alignItems:      'center',
				justifyContent:  'space-between',
				borderRadius:    '6px',
				padding:         '10px 14px',
				fontSize:        '13px',
				fontWeight:      500,
				border:          'none',
				cursor:          'pointer',
				textAlign:       'left',
				backgroundColor: 'transparent',
				color:           '#1d2327',
				marginBottom:    2,
				transition:      'background-color 0.1s',
			}}
			onMouseEnter={(e) => { e.currentTarget.style.backgroundColor = '#f0f0f1'; }}
			onMouseLeave={(e) => { e.currentTarget.style.backgroundColor = 'transparent'; }}
		>
			<span>{children}</span>
			<svg
				width="14"
				height="14"
				viewBox="0 0 24 24"
				fill="none"
				stroke="currentColor"
				strokeWidth="2.5"
				strokeLinecap="round"
				strokeLinejoin="round"
				style={{
					flexShrink: 0,
					color:      '#9ca3af',
					transform:  expanded ? 'rotate(180deg)' : 'rotate(0deg)',
					transition: 'transform 0.2s ease',
				}}
			>
				<polyline points="6 9 12 15 18 9" />
			</svg>
		</button>
	);
}

/** Indented child nav item rendered beneath a group label. */
function NavChildButton({
	active,
	onClick,
	children,
}: {
	active: boolean;
	onClick: () => void;
	children: React.ReactNode;
}) {
	return (
		<button
			type="button"
			onClick={onClick}
			style={{
				display:         'flex',
				width:           '100%',
				alignItems:      'center',
				gap:             '6px',
				borderRadius:    '6px',
				padding:         '8px 14px 8px 24px',
				fontSize:        '13px',
				fontWeight:      active ? 600 : 500,
				border:          'none',
				cursor:          active ? 'default' : 'pointer',
				textAlign:       'left',
				backgroundColor: active ? '#f0f6fc' : 'transparent',
				color:           active ? 'hsl(var(--primary))' : '#50575e',
				marginBottom:    2,
				transition:      'background-color 0.1s',
			}}
		>
			{children}
		</button>
	);
}

// ─── Logo ─────────────────────────────────────────────────────────────────────

function PDFDraftLogo() {
	return (
		<div
			style={{
				display:     'flex',
				alignItems:  'center',
				gap:         '8px',
				padding:     '0 20px',
				borderRight: '1px solid #e2e4e7',
				flexShrink:  0,
			}}
		>
			<svg width="26" height="30" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
				<path d="M22.5 11.797c0 .902.844 1.64 1.875 1.64H35V35.86c0 .909-.836 1.64-1.875 1.64h-21.38l3.55-5.786q.12-.214.358-.315a.87.87 0 0 1 .511-.048 7.3 7.3 0 0 0 3.435-.22 7.1 7.1 0 0 0 2.954-1.749 6.8 6.8 0 0 0 1.755-2.876 6.4 6.4 0 0 0 .142-3.322 1 1 0 0 0-.443-.676 1.14 1.14 0 0 0-.778-.176q-.423.051-.732.404l-2.627 3.898q-.379.504-1.05.571a1.65 1.65 0 0 1-1.198-.325l-2.593-1.943a1.53 1.53 0 0 1-.622-1.026q-.098-.63.334-1.17.434-.54 1.614-1.7 1.18-1.161 1.642-1.704.276-.378.208-.784a1.13 1.13 0 0 0-.386-.683q-.317-.275-.787-.246-1.56.076-2.947.775a6.8 6.8 0 0 0-2.327 1.902 6.7 6.7 0 0 0-1.426 3.465 6.7 6.7 0 0 0 .61 3.645.95.95 0 0 1 .05.495.7.7 0 0 1-.227.413L5 33.911V4.141C5 3.23 5.836 2.5 6.875 2.5H22.5z" fill="#E50001"/>
				<path d="M25.477 2.5c.5 0 .976.17 1.328.478l7.648 6.7c.352.307.547.725.547 1.155v.63H24.416V2.5z" fill="#E50001"/>
			</svg>
			<span style={{ fontSize: '15px', fontWeight: 700, color: '#1d2327', letterSpacing: '-0.01em' }}>
				PDFDraft
			</span>
		</div>
	);
}

// ─── Main settings page ───────────────────────────────────────────────────────

/**
 * Compute the default active section and child from the sections list.
 * Built-in sections have no children; addon sections may have children.
 */
function getDefaultActive(): { section: string; child: string | null } {
	const first = ALL_SECTIONS[0];
	if (!first) return { section: 'posts-to-pdf', child: null };
	const firstChild = (first as AddonSection).children?.[0]?.key ?? null;
	return { section: first.key, child: firstChild };
}

export function SettingsPage() {
	const [isBooting, setIsBooting]   = React.useState(true);
	const [isSaving, setIsSaving]     = React.useState(false);
	const [activeSection, setActiveSection] = React.useState(getDefaultActive().section);
	const [activeChild, setActiveChild]     = React.useState<string | null>(getDefaultActive().child);
	const postsToPdfRef = React.useRef<PostsToPdfSettingsHandle | null>(null);
	const viewportHeight = useViewportHeight();

	// Short boot delay so skeleton only flashes on slow connections.
	React.useEffect(() => {
		const timer = window.setTimeout(() => setIsBooting(false), 150);
		return () => window.clearTimeout(timer);
	}, []);

	// Register Posts to PDF save function in the global registry.
	React.useEffect(() => {
		window.__pdfdraftSaveFunctions ??= new Map();
		window.__pdfdraftSaveFunctions.set('posts-to-pdf', async () => {
			if (!postsToPdfRef.current) return true;
			return postsToPdfRef.current.save();
		});
		return () => {
			window.__pdfdraftSaveFunctions?.delete('posts-to-pdf');
		};
	}, []);

	/** Navigate to a top-level section (no children). */
	const handleNavSection = React.useCallback((sectionKey: string) => {
		setActiveSection(sectionKey);
		setActiveChild(null);
		window.dispatchEvent(
			new CustomEvent(NAV_EVENT, { detail: { section: sectionKey, child: null } }),
		);
	}, []);

	/** Navigate to a child within a parent section. */
	const handleNavChild = React.useCallback((sectionKey: string, childKey: string) => {
		setActiveSection(sectionKey);
		setActiveChild(childKey);
		window.dispatchEvent(
			new CustomEvent(NAV_EVENT, { detail: { section: sectionKey, child: childKey } }),
		);
	}, []);

	// Header Save — calls every registered save function.
	const handleHeaderSave = React.useCallback(async () => {
		setIsSaving(true);
		try {
			const fns = [...(window.__pdfdraftSaveFunctions?.values() ?? [])];
			if (fns.length === 0) return;
			const results = await Promise.all(fns.map((fn) => fn()));
			if (results.every(Boolean)) {
				toast.success(__('Settings saved.', 'pdfdraft'));
			} else {
				toast.error(__('Failed to save settings.', 'pdfdraft'));
			}
		} finally {
			setIsSaving(false);
		}
	}, []);

	// Ctrl/Cmd + S shortcut.
	React.useEffect(() => {
		const onKeyDown = (event: KeyboardEvent) => {
			if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') {
				event.preventDefault();
				void handleHeaderSave();
			}
		};
		window.addEventListener('keydown', onKeyDown);
		return () => window.removeEventListener('keydown', onKeyDown);
	}, [handleHeaderSave]);

	if (isBooting) {
		return <SettingsSkeleton />;
	}

	return (
		<div style={{ width: '100%' }}>
			{/* ── Header ──────────────────────────────────────────────────── */}
			<div style={headerStyle}>
				<PDFDraftLogo />
				<div
					style={{
						display:    'flex',
						alignItems: 'center',
						padding:    '0 20px',
						position:   'relative',
					}}
				>
					<span style={{ fontSize: '14px', fontWeight: 500, color: 'hsl(var(--primary))' }}>
						{__('Settings', 'pdfdraft')}
					</span>
					<span
						style={{
							position:     'absolute',
							bottom:       0,
							left:         '20px',
							right:        '20px',
							height:       '2px',
							background:   'hsl(var(--primary))',
							borderRadius: '1px 1px 0 0',
						}}
					/>
				</div>
				<div style={{ display: 'flex', alignItems: 'center', padding: '0 24px', marginLeft: 'auto' }}>
					<LoadingButton
						size="sm"
						loading={isSaving}
						disabled={isSaving}
						onClick={handleHeaderSave}
					>
						{__('Save', 'pdfdraft')}
					</LoadingButton>
				</div>
			</div>

			{/* ── Body ────────────────────────────────────────────────────── */}
			<div style={{ display: 'flex', alignItems: 'flex-start' }}>
				{/* Sidebar nav */}
				<aside style={sidebarStyle(STICKY_TOP, viewportHeight)}>
					<nav style={{ padding: '12px 8px' }}>
						{ALL_SECTIONS.map((s) => {
							const addon = s as AddonSection;
							const hasChildren = addon.children && addon.children.length > 0;

							if (!hasChildren) {
								// Plain top-level item (e.g. Posts to PDF).
								return (
									<NavButton
										key={s.key}
										active={activeSection === s.key}
										onClick={() => handleNavSection(s.key)}
									>
										{s.label}
									</NavButton>
								);
							}

							// Section with children — clicking the parent activates the first child directly.
							const firstChild = addon.children![0];
							if (!firstChild) return null;
							return (
								<NavButton
									key={s.key}
									active={activeSection === s.key}
									onClick={() => handleNavChild(s.key, firstChild.key)}
								>
									{s.label}
								</NavButton>
							);
						})}
					</nav>
				</aside>

				{/* Content area */}
				<main style={{ flex: 1, minHeight: 0 }}>
					{/* Posts to PDF — always mounted, shown/hidden via display. */}
					<div style={{ display: activeSection === 'posts-to-pdf' ? 'block' : 'none' }}>
						<PostsToPdfSettings
							ref={postsToPdfRef}
							onSavingChange={() => {
								/* saving state handled centrally via isSaving */
							}}
						/>
					</div>

					{/*
					 * Addon section slots — always in the DOM so external React roots
					 * survive re-renders. Visibility toggled via `display`, never by
					 * conditional rendering (which would unmount the external React root).
					 */}
					{ADDON_SECTIONS.map((s) => (
						<div
							key={s.key}
							id={`pdfdraft-settings-section--${s.key}`}
							style={{ display: activeSection === s.key ? 'block' : 'none' }}
						/>
					))}
				</main>
			</div>
		</div>
	);
}
