// @vitest-environment jsdom
import "@testing-library/jest-dom/vitest";

import { combatantId } from "@initiative/domain";
import { cleanup, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, describe, expect, it, vi } from "vitest";
import { CombatantRow } from "../combatant-row";
import { PLAYER_COLOR_HEX } from "../player-icon-map";

afterEach(cleanup);

const defaultProps = {
	onRename: vi.fn(),
	onSetInitiative: vi.fn(),
	onRemove: vi.fn(),
	onSetHp: vi.fn(),
	onAdjustHp: vi.fn(),
	onSetAc: vi.fn(),
	onToggleCondition: vi.fn(),
	onToggleConcentration: vi.fn(),
};

function renderRow(
	overrides: Partial<{
		combatant: Parameters<typeof CombatantRow>[0]["combatant"];
		isActive: boolean;
		onRollInitiative: (id: ReturnType<typeof combatantId>) => void;
		onRemove: (id: ReturnType<typeof combatantId>) => void;
		onShowStatBlock: () => void;
	}> = {},
) {
	const combatant = overrides.combatant ?? {
		id: combatantId("1"),
		name: "Goblin",
		initiative: 15,
		maxHp: 10,
		currentHp: 10,
		ac: 13,
	};
	const props = {
		...defaultProps,
		combatant,
		isActive: overrides.isActive ?? false,
		onRollInitiative: overrides.onRollInitiative,
		onShowStatBlock: overrides.onShowStatBlock,
		onRemove: overrides.onRemove ?? defaultProps.onRemove,
	};
	return render(<CombatantRow {...props} />);
}

describe("CombatantRow", () => {
	it("renders combatant name", () => {
		renderRow();
		expect(screen.getByText("Goblin")).toBeInTheDocument();
	});

	it("renders initiative value", () => {
		renderRow();
		expect(screen.getByText("15")).toBeInTheDocument();
	});

	it("renders current HP", () => {
		renderRow({
			combatant: {
				id: combatantId("1"),
				name: "Goblin",
				maxHp: 10,
				currentHp: 7,
			},
		});
		expect(screen.getByText("7")).toBeInTheDocument();
	});

	it("active combatant gets active border styling", () => {
		const { container } = renderRow({ isActive: true });
		const row = container.firstElementChild;
		expect(row?.className).toContain("border-accent/40");
	});

	it("unconscious combatant (currentHp === 0) gets dimmed styling", () => {
		renderRow({
			combatant: {
				id: combatantId("1"),
				name: "Goblin",
				maxHp: 10,
				currentHp: 0,
			},
		});
		// The name area should have opacity-50
		const nameEl = screen.getByText("Goblin");
		const nameContainer = nameEl.closest(".opacity-50");
		expect(nameContainer).not.toBeNull();
	});

	it("shows '--' for current HP when no maxHp is set", () => {
		renderRow({
			combatant: {
				id: combatantId("1"),
				name: "Goblin",
			},
		});
		expect(screen.getByLabelText("No HP set")).toBeInTheDocument();
	});

	it("shows concentration icon when isConcentrating is true", () => {
		renderRow({
			combatant: {
				id: combatantId("1"),
				name: "Goblin",
				isConcentrating: true,
			},
		});
		const concButton = screen.getByRole("button", {
			name: "Toggle concentration",
		});
		expect(concButton.className).toContain("text-purple-400");
	});

	it("shows player character icon and color when set", () => {
		const { container } = renderRow({
			combatant: {
				id: combatantId("1"),
				name: "Aragorn",
				color: "red",
				icon: "sword",
			},
		});
		// The icon should be rendered with the player color
		const svgIcon = container.querySelector("svg[style]");
		expect(svgIcon).not.toBeNull();
		expect(svgIcon).toHaveStyle({ color: PLAYER_COLOR_HEX.red });
	});

	it("remove button calls onRemove after confirmation", async () => {
		const user = userEvent.setup();
		const onRemove = vi.fn();
		renderRow({ onRemove });
		const removeBtn = screen.getByRole("button", {
			name: "Remove combatant",
		});
		// First click enters confirm state
		await user.click(removeBtn);
		// Second click confirms
		const confirmBtn = screen.getByRole("button", {
			name: "Confirm remove combatant",
		});
		await user.click(confirmBtn);
		expect(onRemove).toHaveBeenCalledWith(combatantId("1"));
	});

	it("shows d20 roll button when initiative is undefined and onRollInitiative is provided", () => {
		renderRow({
			combatant: {
				id: combatantId("1"),
				name: "Goblin",
			},
			onRollInitiative: vi.fn(),
		});
		expect(
			screen.getByRole("button", { name: "Roll initiative" }),
		).toBeInTheDocument();
	});
});
