import { expect, type Page } from "@playwright/test";
import { authFile, navigateTo, test } from "./fixtures";

/**
 * Medications Page E2E Tests
 *
 * Verifies the medication list, add/edit form, CRUD operations,
 * and form validation.
 */
test.describe("Medications Page", () => {
	test.use({ storageState: authFile });

	const visibleMedForm = (page: Page) => page.locator("form.form-grid:visible").first();

	async function openMedicationForm(page: Page) {
		await navigateTo(page, "/medications");
		const nameField = visibleMedForm(page).getByLabel(/(Commercial Name|form\.commercialName)/i);
		if (await nameField.isVisible().catch(() => false)) return;

		const newEntryButton = page.getByRole("button", { name: /(new (entry|medication)|form\.newEntry)/i });
		if (await newEntryButton.isVisible().catch(() => false)) {
			await newEntryButton.click();
			await expect(nameField).toBeVisible({ timeout: 5000 });
		}
	}

	test("should display medications page", async ({ page }) => {
		await navigateTo(page, "/medications");

		// Medications tab should be active
		await expect(page.locator('button.pill.primary:has-text("Medications")')).toBeVisible();
	});

	test("should show medication list or empty state", async ({ page }) => {
		await navigateTo(page, "/medications");

		// Should show either medication entries or the new medication form
		const listTitle = page.locator("h2").filter({ hasText: /(Medication list|form\.medicationList)/i });
		const formTitle = page.locator("h2").filter({ hasText: /(New (entry|medication)|form\.newEntry)/i });

		const hasList = await listTitle.isVisible().catch(() => false);
		const hasForm = await formTitle.isVisible().catch(() => false);

		expect(hasList || hasForm).toBeTruthy();
	});

	test("should display the medication form with required fields", async ({ page }) => {
		await openMedicationForm(page);
		const form = visibleMedForm(page);

		const commercialName = form.getByLabel(/(Commercial Name|form\.commercialName)/i);
		await expect(commercialName).toBeVisible();

		// Package type selector should exist
		await expect(form.getByText(/(Package Type|form\.packageType)/i)).toBeVisible();

		// Tabbed form should expose navigation to Package/Schedule sections
		await expect(page.getByRole("tab", { name: /Package/i })).toBeVisible();
		await expect(page.getByRole("tab", { name: /Schedule/i })).toBeVisible();
	});

	test("should fill in medication details", async ({ page }) => {
		await openMedicationForm(page);
		const form = visibleMedForm(page);

		const nameField = form.getByLabel(/(Commercial Name|form\.commercialName)/i);
		await nameField.fill("Test Aspirin");
		await expect(nameField).toHaveValue("Test Aspirin");

		const genericField = form.getByLabel(/(Generic Name|form\.genericName)/i);
		await genericField.fill("Acetylsalicylic acid");
		await expect(genericField).toHaveValue("Acetylsalicylic acid");
	});

	test("should have stock inventory fields", async ({ page }) => {
		await openMedicationForm(page);
		const form = visibleMedForm(page);
		await page.getByRole("tab", { name: /Package/i }).click();

		// Package tab should expose stock-related fields for at least one package mode.
		const packsField = form.getByLabel(/(^Packs$|form\.packs)/i).first();
		const totalField = form.getByText(/(Total \(pills\)|Total Capacity|form\.totalCapacity)/i).first();

		const hasPacks = await packsField.isVisible().catch(() => false);
		const hasTotal = await totalField.isVisible().catch(() => false);

		expect(hasPacks || hasTotal).toBeTruthy();
	});

	test("should expose all supported package type options", async ({ page }) => {
		await openMedicationForm(page);
		const form = visibleMedForm(page);
		const packageSelect = form.locator("select.package-type-select");
		await expect(packageSelect).toBeVisible();

		const optionValues = await packageSelect
			.locator("option")
			.evaluateAll((options) => options.map((option) => (option as HTMLOptionElement).value));

		expect(optionValues).toEqual(expect.arrayContaining(["blister", "bottle", "tube", "liquid_container"]));
	});

	test("should have intake schedule with add button", async ({ page }) => {
		await openMedicationForm(page);
		const form = visibleMedForm(page);
		await page.getByRole("tab", { name: /Schedule/i }).click();

		// Intake schedule section
		await expect(page.getByRole("tab", { name: /Schedule/i, selected: true })).toBeVisible();

		// Should have at least one intake entry
		await expect(
			form.getByText(/(Usage \(pills\)|Every \(days\)|form\.blisters\.usage|form\.blisters\.everyDays)/i).first()
		).toBeVisible();

		// Should have an add intake button
		const addIntake = form.getByRole("button", { name: /(Intake|form\.blisters\.addIntake)/i });
		await expect(addIntake).toBeVisible();
	});

	test("should have save and cancel buttons", async ({ page }) => {
		await openMedicationForm(page);
		const form = visibleMedForm(page);

		// Fill in a name to make the form dirty
		await form.getByLabel(/(Commercial Name|form\.commercialName)/i).fill("Test");

		// Save button
		const saveButton = page.getByRole("button", { name: /Save|Add Medication/i });
		await expect(saveButton).toBeVisible();
	});

	test("should prevent navigation with unsaved changes", async ({ page }) => {
		await openMedicationForm(page);
		const form = visibleMedForm(page);

		// Fill in the form to create unsaved changes
		await form.getByLabel(/(Commercial Name|form\.commercialName)/i).fill("Unsaved Medication");

		// Try to navigate away
		await page.locator('button.pill:has-text("Dashboard")').click();

		// Should show unsaved changes warning modal
		const modal = page.locator(".confirm-modal-overlay, .modal-overlay");
		const hasWarning = await modal.isVisible().catch(() => false);

		if (hasWarning) {
			// Cancel to stay on page
			const cancelBtn = page.getByRole("button", { name: /Cancel|Stay/i });
			if (await cancelBtn.isVisible().catch(() => false)) {
				await cancelBtn.click();
			}
		}
	});
});
