import { useEffect, useRef, useState } from "react";
import { ActionBar } from "./components/action-bar.js";
import { BulkImportToasts } from "./components/bulk-import-toasts.js";
import { CombatantRow } from "./components/combatant-row.js";
import {
	PlayerCharacterSection,
	type PlayerCharacterSectionHandle,
} from "./components/player-character-section.js";
import { SettingsModal } from "./components/settings-modal.js";
import { StatBlockPanel } from "./components/stat-block-panel.js";
import { Toast } from "./components/toast.js";
import { TurnNavigation } from "./components/turn-navigation.js";
import { useEncounterContext } from "./contexts/encounter-context.js";
import { useInitiativeRollsContext } from "./contexts/initiative-rolls-context.js";
import { useSidePanelContext } from "./contexts/side-panel-context.js";
import { useActionBarAnimation } from "./hooks/use-action-bar-animation.js";
import { useAutoStatBlock } from "./hooks/use-auto-stat-block.js";
import { cn } from "./lib/utils.js";

export function App() {
	const { encounter, isEmpty } = useEncounterContext();
	const sidePanel = useSidePanelContext();
	const rolls = useInitiativeRollsContext();

	useAutoStatBlock();

	const [settingsOpen, setSettingsOpen] = useState(false);
	const playerCharacterRef = useRef<PlayerCharacterSectionHandle>(null);
	const actionBarInputRef = useRef<HTMLInputElement>(null);
	const activeRowRef = useRef<HTMLDivElement>(null);
	const actionBarAnim = useActionBarAnimation(encounter.combatants.length);

	// Close the side panel when the encounter becomes empty
	useEffect(() => {
		if (isEmpty) {
			sidePanel.dismissPanel();
		}
	}, [isEmpty, sidePanel.dismissPanel]);

	// Auto-scroll to active combatant when turn changes
	const activeIndex = encounter.activeIndex;
	useEffect(() => {
		if (activeIndex >= 0) {
			activeRowRef.current?.scrollIntoView({
				block: "nearest",
				behavior: "smooth",
			});
		}
	}, [activeIndex]);

	return (
		<div className="flex h-dvh flex-col">
			<div className="relative mx-auto flex min-h-0 w-full flex-1 flex-col gap-3 sm:max-w-2xl sm:px-4">
				{!!actionBarAnim.showTopBar && (
					<div
						className={cn(
							"shrink-0 pt-[env(safe-area-inset-top)] sm:pt-[max(env(safe-area-inset-top),2rem)]",
							actionBarAnim.topBarClass,
						)}
						onAnimationEnd={actionBarAnim.onTopBarExitEnd}
					>
						<TurnNavigation />
					</div>
				)}

				{isEmpty ? (
					<div className="flex min-h-0 flex-1 items-center justify-center pt-8 pb-[15%]">
						<div
							className={cn("w-full", actionBarAnim.risingClass)}
							onAnimationEnd={actionBarAnim.onRiseEnd}
						>
							<ActionBar
								inputRef={actionBarInputRef}
								onManagePlayers={() =>
									playerCharacterRef.current?.openManagement()
								}
								onOpenSettings={() => setSettingsOpen(true)}
								autoFocus
							/>
						</div>
					</div>
				) : (
					<>
						<div className="min-h-0 flex-1 overflow-y-auto">
							<div className="flex flex-col px-2 py-2">
								{encounter.combatants.map((c, i) => (
									<CombatantRow
										key={c.id}
										ref={i === encounter.activeIndex ? activeRowRef : null}
										combatant={c}
										isActive={i === encounter.activeIndex}
									/>
								))}
							</div>
						</div>

						<div
							className={cn(
								"shrink-0 pb-[env(safe-area-inset-bottom)] sm:pb-[max(env(safe-area-inset-bottom),2rem)]",
								actionBarAnim.settlingClass,
							)}
							onAnimationEnd={actionBarAnim.onSettleEnd}
						>
							<ActionBar
								inputRef={actionBarInputRef}
								onManagePlayers={() =>
									playerCharacterRef.current?.openManagement()
								}
								onOpenSettings={() => setSettingsOpen(true)}
							/>
						</div>
					</>
				)}
			</div>

			{!!sidePanel.pinnedCreatureId && sidePanel.isWideDesktop && (
				<StatBlockPanel panelRole="pinned" side="left" />
			)}

			<StatBlockPanel panelRole="browse" side="right" />

			<BulkImportToasts />

			{rolls.rollSkippedCount > 0 && (
				<Toast
					message={`${rolls.rollSkippedCount} skipped — bestiary source not loaded`}
					onDismiss={rolls.dismissRollSkipped}
					autoDismissMs={4000}
				/>
			)}

			{!!rolls.rollSingleSkipped && (
				<Toast
					message="Can't roll — bestiary source not loaded"
					onDismiss={rolls.dismissRollSingleSkipped}
					autoDismissMs={4000}
				/>
			)}

			<SettingsModal
				open={settingsOpen}
				onClose={() => setSettingsOpen(false)}
			/>
			<PlayerCharacterSection ref={playerCharacterRef} />
		</div>
	);
}
