import type { ActivityCost, SpellReference } from "@initiative/domain";
import { DetailPopover } from "./detail-popover.js";
import { RichDescription } from "./rich-description.js";
import { ActivityIcon } from "./stat-block-parts.js";

interface SpellDetailPopoverProps {
	readonly spell: SpellReference;
	readonly anchorRect: DOMRect;
	readonly onClose: () => void;
}

const RANK_LABELS = [
	"Cantrip",
	"1st",
	"2nd",
	"3rd",
	"4th",
	"5th",
	"6th",
	"7th",
	"8th",
	"9th",
	"10th",
];

function formatRank(rank: number | undefined): string {
	if (rank === undefined) return "";
	return RANK_LABELS[rank] ?? `Rank ${rank}`;
}

function parseActionCost(cost: string): ActivityCost | null {
	if (cost === "free") return { number: 1, unit: "free" };
	if (cost === "reaction") return { number: 1, unit: "reaction" };
	const n = Number(cost);
	if (n >= 1 && n <= 3) return { number: n, unit: "action" };
	return null;
}

function SpellActionCost({ cost }: Readonly<{ cost: string | undefined }>) {
	if (!cost) return null;
	const activity = parseActionCost(cost);
	if (activity) {
		return (
			<span className="shrink-0 text-lg">
				<ActivityIcon activity={activity} />
			</span>
		);
	}
	return <span className="shrink-0 text-muted-foreground text-xs">{cost}</span>;
}

function SpellHeader({ spell }: Readonly<{ spell: SpellReference }>) {
	return (
		<div className="flex items-center justify-between gap-2">
			<h3 className="font-bold text-lg text-stat-heading">{spell.name}</h3>
			<SpellActionCost cost={spell.actionCost} />
		</div>
	);
}

function SpellTraits({ traits }: Readonly<{ traits: readonly string[] }>) {
	if (traits.length === 0) return null;
	return (
		<div className="flex flex-wrap gap-1">
			{traits.map((t) => (
				<span
					key={t}
					className="rounded border border-border bg-card px-1.5 py-0.5 text-foreground text-xs"
				>
					{t}
				</span>
			))}
		</div>
	);
}

function LabeledValue({
	label,
	value,
}: Readonly<{ label: string; value: string }>) {
	return (
		<>
			<span className="font-semibold">{label}</span> {value}
		</>
	);
}

function SpellRangeLine({ spell }: Readonly<{ spell: SpellReference }>) {
	const items: { label: string; value: string }[] = [];
	if (spell.range) items.push({ label: "Range", value: spell.range });
	if (spell.target) items.push({ label: "Target", value: spell.target });
	if (spell.area) items.push({ label: "Area", value: spell.area });

	if (items.length === 0) return null;
	return (
		<div>
			{items.map((item, i) => (
				<span key={item.label}>
					{i > 0 ? "; " : ""}
					<LabeledValue label={item.label} value={item.value} />
				</span>
			))}
		</div>
	);
}

function SpellMeta({ spell }: Readonly<{ spell: SpellReference }>) {
	const hasTraditions =
		spell.traditions !== undefined && spell.traditions.length > 0;
	return (
		<div className="space-y-0.5 text-xs">
			{spell.rank === undefined ? null : (
				<div>
					<span className="font-semibold">{formatRank(spell.rank)}</span>
					{hasTraditions ? (
						<span className="text-muted-foreground">
							{" "}
							({spell.traditions?.join(", ")})
						</span>
					) : null}
				</div>
			)}
			<SpellRangeLine spell={spell} />
			{spell.duration ? (
				<div>
					<LabeledValue label="Duration" value={spell.duration} />
				</div>
			) : null}
			{spell.defense ? (
				<div>
					<LabeledValue label="Defense" value={spell.defense} />
				</div>
			) : null}
		</div>
	);
}

function SpellDetailContent({ spell }: Readonly<{ spell: SpellReference }>) {
	return (
		<div className="space-y-2 text-sm">
			<SpellHeader spell={spell} />
			<SpellTraits traits={spell.traits ?? []} />
			<SpellMeta spell={spell} />
			{spell.description ? (
				<RichDescription
					text={spell.description}
					className="whitespace-pre-line text-foreground"
				/>
			) : (
				<p className="text-muted-foreground italic">
					No description available.
				</p>
			)}
			{spell.heightening ? (
				<RichDescription
					text={spell.heightening}
					className="whitespace-pre-line text-foreground text-xs"
				/>
			) : null}
		</div>
	);
}

export function SpellDetailPopover({
	spell,
	anchorRect,
	onClose,
}: Readonly<SpellDetailPopoverProps>) {
	return (
		<DetailPopover
			anchorRect={anchorRect}
			onClose={onClose}
			ariaLabel={`Spell details: ${spell.name}`}
		>
			<SpellDetailContent spell={spell} />
		</DetailPopover>
	);
}
