import { expect, openSettings, test, uploadTestImage } from "./helpers";

// ---------------------------------------------------------------------------
// Login Page (unauthenticated)
// ---------------------------------------------------------------------------
test.describe("Login Page", () => {
  test.use({ storageState: { cookies: [], origins: [] } });

  test("renders split layout with form and marketing text", async ({ page }) => {
    await page.goto("/login");

    // Left side: form panel
    await expect(page.getByRole("heading", { name: /login/i })).toBeVisible();
    await expect(page.getByLabel("Username")).toBeVisible();
    await expect(page.getByLabel("Password")).toBeVisible();
    await expect(page.getByRole("button", { name: /login/i })).toBeVisible();

    // Right side: marketing text (hidden on mobile, visible on lg+)
    await expect(page.getByText("Your images. Stay yours.")).toBeVisible();
  });

  test("username and password inputs start empty", async ({ page }) => {
    await page.goto("/login");

    await expect(page.getByLabel("Username")).toHaveValue("");
    await expect(page.getByLabel("Password")).toHaveValue("");
  });

  test("login button is disabled when fields are empty", async ({ page }) => {
    await page.goto("/login");

    const loginBtn = page.getByRole("button", { name: /login/i });
    await expect(loginBtn).toBeDisabled();
  });

  test("login button enables when both fields are filled", async ({ page }) => {
    await page.goto("/login");

    const loginBtn = page.getByRole("button", { name: /login/i });
    await expect(loginBtn).toBeDisabled();

    await page.getByLabel("Username").fill("admin");
    await expect(loginBtn).toBeDisabled();

    await page.getByLabel("Password").fill("admin");
    await expect(loginBtn).toBeEnabled();
  });

  test("successful login redirects to /", async ({ page }) => {
    await page.goto("/login");

    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");
    await page.getByRole("button", { name: /login/i }).click();

    await page.waitForURL("/", { timeout: 15_000 });
    await expect(page).toHaveURL("/");
  });

  test("failed login shows error and stays on login page", async ({ page }) => {
    await page.goto("/login");

    await page.getByLabel("Username").fill("wrong-user");
    await page.getByLabel("Password").fill("wrong-pass");
    await page.getByRole("button", { name: /login/i }).click();

    await expect(page.getByText(/invalid|incorrect|error/i).first()).toBeVisible({
      timeout: 10_000,
    });
    await expect(page).toHaveURL(/\/login/);
  });

  test("pressing Enter in password field submits the form", async ({ page }) => {
    await page.goto("/login");

    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");
    await page.getByLabel("Password").press("Enter");

    await page.waitForURL("/", { timeout: 15_000 });
    await expect(page).toHaveURL("/");
  });

  test("tab order is username -> password -> login button", async ({ page }) => {
    await page.goto("/login");

    // Focus the username field first
    await page.getByLabel("Username").focus();
    await expect(page.getByLabel("Username")).toBeFocused();

    // Tab to password
    await page.keyboard.press("Tab");
    await expect(page.getByLabel("Password")).toBeFocused();

    // Fill both fields so login button becomes enabled
    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");

    // Focus password again, then Tab to login button
    await page.getByLabel("Password").focus();
    await page.keyboard.press("Tab");
    await expect(page.getByRole("button", { name: /login/i })).toBeFocused();
  });

  test("login button only fills username keeps it disabled", async ({ page }) => {
    await page.goto("/login");

    const loginBtn = page.getByRole("button", { name: /login/i });
    await page.getByLabel("Username").fill("admin");
    // Only username is filled, password is still empty
    await expect(loginBtn).toBeDisabled();

    // Now fill only password (clear username)
    await page.getByLabel("Username").fill("");
    await page.getByLabel("Password").fill("admin");
    await expect(loginBtn).toBeDisabled();
  });

  test("SnapOtter branding is visible on login page", async ({ page }) => {
    await page.goto("/login");

    await expect(page.getByText("SnapOtter").first()).toBeVisible();
  });

  test("after too many failed attempts, rate limiting kicks in", async ({ page }) => {
    await page.goto("/login");

    // Submit several failed login attempts in rapid succession
    for (let i = 0; i < 10; i++) {
      await page.getByLabel("Username").fill(`wrong-user-${i}`);
      await page.getByLabel("Password").fill(`wrong-pass-${i}`);
      await page.getByRole("button", { name: /login/i }).click();

      // Wait briefly for the response
      await page.waitForTimeout(300);
    }

    // After many rapid failures, the UI should show a rate-limit or lockout message,
    // or the login button should become temporarily disabled
    const rateLimited = page.getByText(/too many|rate limit|try again|locked|slow down/i).first();
    const disabledBtn = page.getByRole("button", { name: /login/i });

    // Either an error message about rate limiting appears, or the button is disabled
    const hasRateLimitMsg = await rateLimited.isVisible({ timeout: 5000 }).catch(() => false);
    const isDisabled = await disabledBtn.isDisabled();

    expect(hasRateLimitMsg || isDisabled).toBe(true);
  });
});

// ---------------------------------------------------------------------------
// Home Page (authenticated)
// ---------------------------------------------------------------------------
test.describe("Home Page - Before Upload", () => {
  test("shows dropzone with dashed border and upload button", async ({ loggedInPage: page }) => {
    const dropzone = page.locator("[class*='border-dashed']").first();
    await expect(dropzone).toBeVisible();
    await expect(page.getByText("Upload from computer")).toBeVisible();
  });

  test("tool panel is visible with search bar and categories", async ({ loggedInPage: page }) => {
    await expect(page.getByPlaceholder(/search/i).first()).toBeVisible();
    await expect(page.getByText("Essentials").first()).toBeVisible();
  });

  test("each tool category header is visible in tool panel", async ({ loggedInPage: page }) => {
    const toolPanel = page.locator("aside, [class*='tool-panel'], section").filter({
      hasText: "Essentials",
    });
    await expect(toolPanel.getByText("Essentials").first()).toBeVisible();
    await expect(toolPanel.getByText("Optimization").first()).toBeVisible();
  });

  test("clicking a tool in the panel navigates to its page", async ({ loggedInPage: page }) => {
    // Click on a specific tool from the panel
    const compressLink = page.getByText("Compress").first();
    await compressLink.click();
    await expect(page).toHaveURL("/compress");
  });

  test("search filters tools in tool panel", async ({ loggedInPage: page }) => {
    const searchInput = page.getByPlaceholder(/search/i).first();
    await searchInput.fill("resize");

    // Resize tool should remain visible
    await expect(page.getByText("Resize").first()).toBeVisible();
  });
});

test.describe("Home Page - After Upload", () => {
  test("shows green checkmark, filename, and file size", async ({ loggedInPage: page }) => {
    await uploadTestImage(page);

    // Green checkmark indicator
    await expect(page.locator("[class*='text-green']").first()).toBeVisible();
    // Filename
    await expect(page.getByText(/test-image/i).first()).toBeVisible();
    // File size in KB
    await expect(page.getByText(/KB/i).first()).toBeVisible();
  });

  test("shows Change file button", async ({ loggedInPage: page }) => {
    await uploadTestImage(page);

    await expect(page.getByText("Change file")).toBeVisible();
  });

  test("shows Quick Actions with 4 buttons", async ({ loggedInPage: page }) => {
    await uploadTestImage(page);

    await expect(page.getByText("Quick Actions").first()).toBeVisible();
    await expect(page.getByRole("button", { name: /resize/i }).first()).toBeVisible();
    await expect(page.getByRole("button", { name: /compress/i }).first()).toBeVisible();
    await expect(page.getByRole("button", { name: /convert/i }).first()).toBeVisible();
    await expect(page.getByRole("button", { name: /remove background/i }).first()).toBeVisible();
  });

  test("shows All Tools section with categorized list", async ({ loggedInPage: page }) => {
    await uploadTestImage(page);

    await expect(page.getByText("All Tools").first()).toBeVisible();
    // Categories should be visible within the tool list
    await expect(page.getByText("Essentials").first()).toBeVisible();
  });

  test("clicking a tool navigates to the tool page", async ({ loggedInPage: page }) => {
    await uploadTestImage(page);

    await page
      .getByRole("button", { name: /resize/i })
      .first()
      .click();
    await expect(page).toHaveURL("/resize");
  });

  test("image viewer is visible after upload", async ({ loggedInPage: page }) => {
    await uploadTestImage(page);

    // The image viewer should render the uploaded image (an <img> element)
    const img = page.locator("img").first();
    await expect(img).toBeVisible();
  });

  test("Change file button resets to dropzone state", async ({ loggedInPage: page }) => {
    await uploadTestImage(page);

    // File info should be visible
    await expect(page.getByText(/test-image/i).first()).toBeVisible();

    // Click Change file
    await page.getByText("Change file").click();
    await page.waitForTimeout(300);

    // Dropzone should reappear
    const dropzone = page.locator("[class*='border-dashed']").first();
    await expect(dropzone).toBeVisible();
    await expect(page.getByText("Upload from computer")).toBeVisible();
  });

  test("multi-upload shows file count badge", async ({ loggedInPage: page }) => {
    // Upload first image
    await uploadTestImage(page);

    // Upload a second image via the file chooser
    const fileChooserPromise = page.waitForEvent("filechooser");
    // Click "Add more files" or "Change file" to trigger file picker
    const addBtn = page.getByText(/add more|change file/i).first();
    await addBtn.click();
    const fileChooser = await fileChooserPromise;
    const { getTestImagePath } = await import("./helpers");
    await fileChooser.setFiles([getTestImagePath(), getTestImagePath()]);
    await page.waitForTimeout(500);

    // Should show a count badge or multi-file indicator
    await expect(page.getByText(/\d+ file/i).first()).toBeVisible();
  });
});

// ---------------------------------------------------------------------------
// Fullscreen Grid Page (/fullscreen)
// ---------------------------------------------------------------------------
test.describe("Fullscreen Grid Page", () => {
  test("grid renders with search bar", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");

    await expect(page.getByPlaceholder(/search/i)).toBeVisible();
  });

  test("show/hide details toggle is visible", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");

    // The toggle button text
    await expect(
      page.getByRole("button", { name: /hide details|show details/i }).first(),
    ).toBeVisible();
  });

  test("all category headers are visible", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");

    await expect(page.getByText("Essentials")).toBeVisible();
    await expect(page.getByText("Optimization")).toBeVisible();
    await expect(page.getByText("Adjustments")).toBeVisible();
    await expect(page.getByText("Watermark & Overlay")).toBeVisible();
    await expect(page.getByText("Utilities")).toBeVisible();
    await expect(page.getByText("Layout & Composition")).toBeVisible();
    await expect(page.getByText("Format & Conversion")).toBeVisible();
    await expect(page.getByText("AI Tools")).toBeVisible();
  });

  test("tool cards are links to tool pages", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");

    const resizeLink = page.getByRole("link", { name: /^Resize/ }).first();
    await expect(resizeLink).toBeVisible();

    await resizeLink.click();
    await expect(page).toHaveURL("/resize");
  });

  test("search filters tools in grid", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");

    const searchInput = page.getByPlaceholder(/search/i);
    await searchInput.fill("compress");

    await expect(page.getByRole("link", { name: /^Compress/ }).first()).toBeVisible();
    // Another unrelated tool should be hidden
    await expect(page.getByRole("link", { name: /^Resize/ })).toHaveCount(0);
  });

  test("clearing search restores all tools", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");

    const searchInput = page.getByPlaceholder(/search/i);

    // Filter first
    await searchInput.fill("compress");
    await expect(page.getByRole("link", { name: /^Resize/ })).toHaveCount(0);

    // Clear the search
    await searchInput.fill("");
    await page.waitForTimeout(300);

    // Both tools should be visible again
    await expect(page.getByRole("link", { name: /^Resize/ }).first()).toBeVisible();
    await expect(page.getByRole("link", { name: /^Compress/ }).first()).toBeVisible();
    // Category headers should reappear
    await expect(page.getByText("Essentials")).toBeVisible();
    await expect(page.getByText("Optimization")).toBeVisible();
  });

  test("show/hide details toggle changes card appearance", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");

    const toggleBtn = page.getByRole("button", { name: /hide details|show details/i }).first();
    await expect(toggleBtn).toBeVisible();

    // Click the toggle
    await toggleBtn.click();
    await page.waitForTimeout(300);

    // Toggle text should have changed
    await expect(
      page.getByRole("button", { name: /hide details|show details/i }).first(),
    ).toBeVisible();
  });
});

// ---------------------------------------------------------------------------
// Tool Page (/:toolId) - tested with "resize"
// ---------------------------------------------------------------------------
test.describe("Tool Page - Resize", () => {
  test("shows tool icon and name", async ({ loggedInPage: page }) => {
    await page.goto("/image/resize");

    await expect(page.getByText("Resize").first()).toBeVisible();
  });

  test("shows dropzone with dashed border before upload", async ({ loggedInPage: page }) => {
    await page.goto("/image/resize");

    const dropzone = page.locator("[class*='border-dashed']").first();
    await expect(dropzone).toBeVisible();
    await expect(page.getByText("Upload from computer")).toBeVisible();
  });

  test("after upload shows Files section, Settings section, and Process button", async ({
    loggedInPage: page,
  }) => {
    await page.goto("/image/resize");
    await uploadTestImage(page);

    // Files section
    await expect(page.getByText("Files").first()).toBeVisible();
    // Settings section
    await expect(page.getByText("Settings").first()).toBeVisible();
  });

  test("invalid tool ID shows not found message", async ({ loggedInPage: page }) => {
    await page.goto("/this-tool-does-not-exist-xyz");

    await expect(page.getByText("Tool not found")).toBeVisible();
  });
});

// ---------------------------------------------------------------------------
// Tool Page - Parameterized structure tests across multiple tools
// ---------------------------------------------------------------------------
const DROPZONE_TOOLS = [
  // Essentials
  { id: "resize", name: "Resize" },
  { id: "crop", name: "Crop" },
  { id: "rotate", name: "Rotate" },
  { id: "convert", name: "Convert" },
  { id: "compress", name: "Compress" },
  // Optimization
  { id: "optimize-for-web", name: "Optimize for Web" },
  { id: "strip-metadata", name: "Remove Metadata" },
  { id: "edit-metadata", name: "Edit Metadata" },
  { id: "bulk-rename", name: "Bulk Rename" },
  { id: "image-to-pdf", name: "Image to PDF" },
  { id: "favicon", name: "Favicon Generator" },
  // Adjustments
  { id: "adjust-colors", name: "Adjust Colors" },
  { id: "sharpening", name: "Sharpening" },
  { id: "replace-color", name: "Replace & Invert Color" },
  { id: "color-blindness", name: "Color Blindness Simulation" },
  // AI Tools
  { id: "remove-background", name: "Remove Background" },
  { id: "upscale", name: "Image Upscaling" },
  { id: "erase-object", name: "Object Eraser" },
  { id: "ocr", name: "OCR / Text Extraction" },
  { id: "blur-faces", name: "Face / PII Blur" },
  { id: "smart-crop", name: "Smart Crop" },
  { id: "image-enhancement", name: "Image Enhancement" },
  { id: "enhance-faces", name: "Face Enhancement" },
  { id: "colorize", name: "AI Colorization" },
  { id: "noise-removal", name: "Noise Removal" },
  { id: "red-eye-removal", name: "Red Eye Removal" },
  { id: "restore-photo", name: "Photo Restoration" },
  { id: "passport-photo", name: "Passport Photo" },
  { id: "content-aware-resize", name: "Content-Aware Resize" },
  { id: "ai-canvas-expand", name: "AI Canvas Expand" },
  { id: "transparency-fixer", name: "PNG Transparency Fixer" },
  // Watermark & Overlay
  { id: "watermark-text", name: "Text Watermark" },
  { id: "watermark-image", name: "Image Watermark" },
  { id: "text-overlay", name: "Text Overlay" },
  { id: "compose", name: "Image Composition" },
  // Utilities
  { id: "info", name: "Image Info" },
  { id: "compare", name: "Image Compare" },
  { id: "find-duplicates", name: "Find Duplicates" },
  { id: "color-palette", name: "Color Palette" },
  { id: "barcode-read", name: "Barcode Reader" },
  { id: "image-to-base64", name: "Image to Base64" },
  // Layout & Composition
  { id: "stitch", name: "Stitch / Combine" },
  { id: "split", name: "Image Splitting" },
  { id: "border", name: "Border & Frame" },
  { id: "beautify", name: "Beautify Screenshot" },
  // Format & Conversion
  { id: "svg-to-raster", name: "SVG to Raster" },
  { id: "vectorize", name: "Image to SVG" },
  { id: "gif-tools", name: "GIF Tools" },
];

const NO_DROPZONE_TOOLS = [
  { id: "qr-generate", name: "QR Code Generator" },
  { id: "meme-generator", name: "Meme Generator" },
  { id: "collage", name: "Collage" },
  { id: "pdf-to-image", name: "PDF to Image" },
];

test.describe("Tool Page - Common Structure (Dropzone Tools)", () => {
  for (const tool of DROPZONE_TOOLS) {
    test(`${tool.name} (/${tool.id}) shows tool name and dropzone`, async ({
      loggedInPage: page,
    }) => {
      await page.goto(`/${tool.id}`);

      // Tool name should be visible
      await expect(page.getByText(tool.name).first()).toBeVisible();

      // Dropzone should be visible
      const dropzone = page.locator("[class*='border-dashed']").first();
      await expect(dropzone).toBeVisible();
    });
  }
});

test.describe("Tool Page - Common Structure (No-Dropzone Tools)", () => {
  for (const tool of NO_DROPZONE_TOOLS) {
    test(`${tool.name} (/${tool.id}) shows tool name without standard dropzone`, async ({
      loggedInPage: page,
    }) => {
      await page.goto(`/${tool.id}`);

      // Tool name should be visible
      await expect(page.getByText(tool.name).first()).toBeVisible();
    });
  }
});

test.describe("Tool Page - Settings and Process Flow", () => {
  test("resize: settings panel appears after upload with process button", async ({
    loggedInPage: page,
  }) => {
    await page.goto("/image/resize");
    await uploadTestImage(page);

    await expect(page.getByText("Settings").first()).toBeVisible();
    // Process button should be visible after upload
    await expect(page.getByRole("button", { name: /process/i }).first()).toBeVisible();
  });

  test("compress: settings panel appears after upload", async ({ loggedInPage: page }) => {
    await page.goto("/image/compress");
    await uploadTestImage(page);

    await expect(page.getByText("Settings").first()).toBeVisible();
  });

  test("convert: settings panel appears after upload", async ({ loggedInPage: page }) => {
    await page.goto("/image/convert");
    await uploadTestImage(page);

    await expect(page.getByText("Settings").first()).toBeVisible();
  });

  test("resize: download link appears after processing", async ({ loggedInPage: page }) => {
    await page.goto("/image/resize");
    await uploadTestImage(page);

    // Click the process button
    const processBtn = page.getByRole("button", { name: /process/i }).first();
    await expect(processBtn).toBeVisible();
    await processBtn.click();

    // Wait for processing to complete and download link to appear
    await expect(page.getByRole("link", { name: /download/i }).first()).toBeVisible({
      timeout: 15_000,
    });
  });

  test("mobile: settings panel is collapsible on tool page", async ({ browser }) => {
    const context = await browser.newContext({
      viewport: { width: 375, height: 667 },
    });
    const page = await context.newPage();
    await page.goto("/login");
    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");
    await page.getByRole("button", { name: /login/i }).click();
    await page.waitForURL("/", { timeout: 15_000 });

    await page.goto("/image/resize");
    await uploadTestImage(page);

    // On mobile, settings may be behind a toggle button
    const settingsToggle = page.getByRole("button", { name: /settings/i }).first();
    if (await settingsToggle.isVisible({ timeout: 3000 }).catch(() => false)) {
      await settingsToggle.click();
      await page.waitForTimeout(300);
      // Settings content should be visible after clicking toggle
      await expect(page.getByText("Settings").first()).toBeVisible();
    }

    await context.close();
  });
});

// ---------------------------------------------------------------------------
// Automate Page (/automate)
// ---------------------------------------------------------------------------
test.describe("Automate Page", () => {
  test("shows pipeline builder with empty state", async ({ loggedInPage: page }) => {
    await page.goto("/automate");

    await expect(page.getByText("Pipeline Builder")).toBeVisible();
    await expect(page.getByText("No steps yet")).toBeVisible();
    await expect(
      page.getByText("Click tools from the palette to build your pipeline"),
    ).toBeVisible();
  });

  test("tool palette is visible with searchable list", async ({ loggedInPage: page }) => {
    await page.goto("/automate");

    await expect(page.getByText("Tool Palette")).toBeVisible();
    await expect(page.getByPlaceholder(/search/i).first()).toBeVisible();
  });

  test("process button is disabled when no steps are configured", async ({
    loggedInPage: page,
  }) => {
    await page.goto("/automate");

    const processBtn = page.getByRole("button", { name: /process/i }).first();
    await expect(processBtn).toBeDisabled();
  });

  test("search filters tools in the tool palette", async ({ loggedInPage: page }) => {
    await page.goto("/automate");

    const searchInput = page.getByPlaceholder(/search/i).first();
    await searchInput.fill("resize");

    // Resize should be visible in the palette
    await expect(page.getByText("Resize").first()).toBeVisible();
  });

  test("clicking a tool in palette adds it as a pipeline step", async ({ loggedInPage: page }) => {
    await page.goto("/automate");

    // The empty state should be shown
    await expect(page.getByText("No steps yet")).toBeVisible();

    // Click a tool in the palette to add it as a step
    const resizeTool = page.locator("[data-tool-id='resize']").first();
    if (await resizeTool.isVisible({ timeout: 3000 }).catch(() => false)) {
      await resizeTool.click();
    } else {
      // Fallback: click the Resize text in the palette area
      await page.getByText("Resize").first().click();
    }

    await page.waitForTimeout(500);

    // Empty state should be gone - step should be added
    await expect(page.getByText("No steps yet")).not.toBeVisible();
  });

  test("Save button appears when pipeline has steps", async ({ loggedInPage: page }) => {
    await page.goto("/automate");

    // Save button should not be visible before adding steps
    await expect(page.getByRole("button", { name: /^Save$/i })).not.toBeVisible();

    // Add a tool step
    const resizeTool = page.locator("[data-tool-id='resize']").first();
    if (await resizeTool.isVisible({ timeout: 3000 }).catch(() => false)) {
      await resizeTool.click();
    } else {
      await page.getByText("Resize").first().click();
    }
    await page.waitForTimeout(500);

    // Save button should now be visible
    await expect(page.getByRole("button", { name: /^Save$/i })).toBeVisible();
  });

  test("process button remains disabled with steps but no file", async ({ loggedInPage: page }) => {
    await page.goto("/automate");

    // Add a tool step
    const resizeTool = page.locator("[data-tool-id='resize']").first();
    if (await resizeTool.isVisible({ timeout: 3000 }).catch(() => false)) {
      await resizeTool.click();
    } else {
      await page.getByText("Resize").first().click();
    }
    await page.waitForTimeout(500);

    // Process button should still be disabled without a file
    const processBtn = page.getByRole("button", { name: /process/i }).first();
    await expect(processBtn).toBeDisabled();
  });
});

// ---------------------------------------------------------------------------
// Files Page (/files)
// ---------------------------------------------------------------------------
test.describe("Files Page", () => {
  test("renders file management layout on desktop", async ({ loggedInPage: page }) => {
    await page.goto("/files");

    // Left nav column with "My Files" heading
    await expect(page.getByText("My Files")).toBeVisible();
    // Navigation items
    await expect(page.getByRole("button", { name: /recent/i }).first()).toBeVisible();
  });
});

// ---------------------------------------------------------------------------
// Sidebar Navigation
// ---------------------------------------------------------------------------
test.describe("Sidebar Navigation", () => {
  test("sidebar has 5 top items: Tools, Grid, Automate, Editor, Files", async ({
    loggedInPage: page,
  }) => {
    const sidebar = page.locator("aside");
    await expect(sidebar).toBeVisible();

    await expect(sidebar.getByText("Tools")).toBeVisible();
    await expect(sidebar.getByText("Grid")).toBeVisible();
    await expect(sidebar.getByText("Automate")).toBeVisible();
    await expect(sidebar.getByText("Editor")).toBeVisible();
    await expect(sidebar.getByText("Files")).toBeVisible();
  });

  test("sidebar has 2 bottom items: Help, Settings", async ({ loggedInPage: page }) => {
    const sidebar = page.locator("aside");

    await expect(sidebar.getByText("Help")).toBeVisible();
    await expect(sidebar.getByText("Settings")).toBeVisible();
  });

  test("Tools link navigates to home /", async ({ loggedInPage: page }) => {
    await page.goto("/automate");
    await page.locator("aside").getByText("Tools").click();
    await expect(page).toHaveURL("/");
  });

  test("Grid link navigates to /fullscreen", async ({ loggedInPage: page }) => {
    const gridLink = page.locator("aside").getByText("Grid");
    if (await gridLink.isVisible({ timeout: 3000 }).catch(() => false)) {
      await gridLink.click();
    } else {
      await page.locator('aside a[href="/fullscreen"]').click();
    }
    await expect(page).toHaveURL("/fullscreen");
  });

  test("Automate link navigates to /automate", async ({ loggedInPage: page }) => {
    await page.locator("aside").getByText("Automate").click();
    await expect(page).toHaveURL("/automate");
  });

  test("Editor link navigates to /editor", async ({ loggedInPage: page }) => {
    await page.locator("aside").getByText("Editor").click();
    await expect(page).toHaveURL("/editor");
  });

  test("Files link navigates to /files", async ({ loggedInPage: page }) => {
    await page.locator("aside").getByText("Files").click();
    await expect(page).toHaveURL("/files");
  });

  test("active sidebar item is highlighted", async ({ loggedInPage: page }) => {
    // On home page, "Tools" should have the active styling (bg-primary)
    const toolsItem = page.locator("aside").getByText("Tools").locator("..");
    await expect(toolsItem).toHaveClass(/bg-primary/);
  });

  test("Help button opens HelpDialog modal", async ({ loggedInPage: page }) => {
    await page.locator("aside").getByText("Help").click();

    // Help dialog header
    await expect(page.getByRole("heading", { name: "Help" })).toBeVisible();
  });

  test("Settings button opens SettingsDialog modal", async ({ loggedInPage: page }) => {
    await openSettings(page);

    await expect(page.getByRole("heading", { name: "General" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Security" })).toBeVisible();
  });
});

// ---------------------------------------------------------------------------
// Footer (desktop only)
// ---------------------------------------------------------------------------
test.describe("Footer", () => {
  test("theme toggle button is visible with sun or moon icon", async ({ loggedInPage: page }) => {
    const themeBtn = page.locator("button[title='Toggle Theme']");
    await expect(themeBtn).toBeVisible();

    // Should contain an SVG icon (Sun or Moon)
    await expect(themeBtn.locator("svg")).toBeVisible();
  });

  test("theme toggle switches between sun and moon icons", async ({ loggedInPage: page }) => {
    const themeBtn = page.locator("button[title='Toggle Theme']");
    await expect(themeBtn).toBeVisible();

    const hadDark = await page.evaluate(() => document.documentElement.classList.contains("dark"));

    await themeBtn.click();
    await page.waitForTimeout(300);

    const hasDark = await page.evaluate(() => document.documentElement.classList.contains("dark"));
    expect(hasDark).not.toBe(hadDark);
  });

  test("language button is visible and shows English", async ({ loggedInPage: page }) => {
    const langBtn = page.locator("button[title='Language']");
    await expect(langBtn).toBeVisible();
    await expect(langBtn).toContainText("English");
    await expect(langBtn.locator("svg")).toBeVisible();
  });

  test("privacy link navigates to /privacy", async ({ loggedInPage: page }) => {
    const privacyLink = page.getByRole("link", { name: /privacy/i }).first();
    if (await privacyLink.isVisible({ timeout: 3000 }).catch(() => false)) {
      await privacyLink.click();
      await expect(page).toHaveURL("/privacy");
      await expect(page.getByRole("heading", { name: "Privacy Policy" })).toBeVisible();
    }
  });

  test("theme persists after page reload", async ({ loggedInPage: page }) => {
    const themeBtn = page.locator("button[title='Toggle Theme']");
    await expect(themeBtn).toBeVisible();

    // Toggle theme
    await themeBtn.click();
    await page.waitForTimeout(300);

    const themeAfterToggle = await page.evaluate(() =>
      document.documentElement.classList.contains("dark"),
    );

    // Reload the page
    await page.reload();
    await page.waitForTimeout(500);

    const themeAfterReload = await page.evaluate(() =>
      document.documentElement.classList.contains("dark"),
    );

    // Theme should persist across reload
    expect(themeAfterReload).toBe(themeAfterToggle);
  });
});

// ---------------------------------------------------------------------------
// Drag-and-Drop Upload
// ---------------------------------------------------------------------------
test.describe("Drag-and-Drop Upload", () => {
  test("dropzone accepts dropped files via DataTransfer", async ({ loggedInPage: page }) => {
    const dropzone = page.locator("section[aria-label='File drop zone']");
    await expect(dropzone).toBeVisible();

    // Verify the dropzone aria-label and interactive elements
    await expect(page.getByText("Drop files here or click the upload button")).toBeVisible();

    // Upload via the file chooser flow (same onFiles handler as drag-and-drop)
    await uploadTestImage(page);

    // After upload, the file info should appear
    await expect(page.getByText(/test-image/i).first()).toBeVisible();
  });
});

// ---------------------------------------------------------------------------
// Files Page Layout
// ---------------------------------------------------------------------------
test.describe("Files Page Layout", () => {
  test("desktop shows three-column layout with nav, list, and details", async ({
    loggedInPage: page,
  }) => {
    await page.goto("/files");

    // Left nav column with "My Files"
    await expect(page.getByText("My Files")).toBeVisible();
    // Nav items: Recent and Upload Files
    await expect(page.getByRole("button", { name: /recent/i }).first()).toBeVisible();
    await expect(page.getByRole("button", { name: /upload files/i }).first()).toBeVisible();
  });

  test("mobile shows tabbed layout with Recent and Upload tabs", async ({ browser }) => {
    const context = await browser.newContext({
      viewport: { width: 375, height: 667 },
    });
    const page = await context.newPage();
    await page.goto("/login");
    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");
    await page.getByRole("button", { name: /login/i }).click();
    await page.waitForURL("/", { timeout: 15_000 });

    await page.goto("/files");

    // Mobile tabs should be visible
    await expect(page.getByRole("button", { name: "Recent" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Upload" })).toBeVisible();

    // Desktop nav "My Files" heading should not be visible (hidden md:block)
    await expect(page.getByText("My Files")).not.toBeVisible();

    await context.close();
  });
});

// ---------------------------------------------------------------------------
// Routing Edge Cases
// ---------------------------------------------------------------------------
test.describe("Routing Edge Cases", () => {
  test("invalid tool ID shows error state", async ({ loggedInPage: page }) => {
    await page.goto("/nonexistent-tool-abc123");

    await expect(page.getByText("Tool not found")).toBeVisible();
  });

  test("legacy /brightness-contrast redirects to /adjust-colors", async ({
    loggedInPage: page,
  }) => {
    await page.goto("/brightness-contrast");

    await expect(page).toHaveURL("/image/adjust-colors");
  });

  test("legacy /saturation redirects to /adjust-colors", async ({ loggedInPage: page }) => {
    await page.goto("/saturation");

    await expect(page).toHaveURL("/image/adjust-colors");
  });

  test("legacy /color-channels redirects to /adjust-colors", async ({ loggedInPage: page }) => {
    await page.goto("/color-channels");

    await expect(page).toHaveURL("/image/adjust-colors");
  });

  test("/privacy renders the privacy policy page", async ({ loggedInPage: page }) => {
    await page.goto("/privacy");

    await expect(page.getByRole("heading", { name: "Privacy Policy" })).toBeVisible();
    await expect(page.getByText("Back")).toBeVisible();
  });

  test("/privacy Back link navigates home", async ({ loggedInPage: page }) => {
    await page.goto("/privacy");

    await page.getByText("Back").click();
    await expect(page).toHaveURL("/");
  });

  test("legacy /color-effects redirects to /adjust-colors", async ({ loggedInPage: page }) => {
    await page.goto("/color-effects");

    await expect(page).toHaveURL("/image/adjust-colors");
  });

  test("/login when already logged in redirects to /", async ({ loggedInPage: page }) => {
    // loggedInPage already has authentication via storageState
    await page.goto("/login");

    // Should redirect away from login since already authenticated
    await page.waitForURL("/", { timeout: 10_000 });
    await expect(page).toHaveURL("/");
  });
});

// ---------------------------------------------------------------------------
// Browser Back/Forward Navigation
// ---------------------------------------------------------------------------
test.describe("Browser Back/Forward Navigation", () => {
  test("browser back button returns to previous page", async ({ loggedInPage: page }) => {
    // Navigate: Home -> Fullscreen -> back should return to Home
    await page.goto("/fullscreen");
    await expect(page).toHaveURL("/fullscreen");

    await page.goBack();
    await expect(page).toHaveURL("/");
  });

  test("browser forward button returns to next page after going back", async ({
    loggedInPage: page,
  }) => {
    await page.goto("/fullscreen");
    await expect(page).toHaveURL("/fullscreen");

    await page.goBack();
    await expect(page).toHaveURL("/");

    await page.goForward();
    await expect(page).toHaveURL("/fullscreen");
  });

  test("multi-step back/forward through several pages", async ({ loggedInPage: page }) => {
    // Navigate: Home -> /automate -> /files -> back -> back -> forward
    await page.goto("/automate");
    await expect(page).toHaveURL("/automate");

    await page.goto("/files");
    await expect(page).toHaveURL("/files");

    await page.goBack();
    await expect(page).toHaveURL("/automate");

    await page.goBack();
    await expect(page).toHaveURL("/");

    await page.goForward();
    await expect(page).toHaveURL("/automate");
  });

  test("page refresh preserves route on /fullscreen", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");
    await expect(page).toHaveURL("/fullscreen");

    await page.reload();
    await expect(page).toHaveURL("/fullscreen");
    await expect(page.getByPlaceholder(/search/i)).toBeVisible();
  });

  test("page refresh preserves route on /automate", async ({ loggedInPage: page }) => {
    await page.goto("/automate");
    await expect(page).toHaveURL("/automate");

    await page.reload();
    await expect(page).toHaveURL("/automate");
    await expect(page.getByText("Pipeline Builder")).toBeVisible();
  });

  test("page refresh preserves route on tool page", async ({ loggedInPage: page }) => {
    await page.goto("/image/resize");
    await expect(page).toHaveURL("/resize");

    await page.reload();
    await expect(page).toHaveURL("/resize");
    await expect(page.getByText("Resize").first()).toBeVisible();
  });

  test("page refresh preserves route on /files", async ({ loggedInPage: page }) => {
    await page.goto("/files");
    await expect(page).toHaveURL("/files");

    await page.reload();
    await expect(page).toHaveURL("/files");
    await expect(page.getByText("My Files")).toBeVisible();
  });
});

// ---------------------------------------------------------------------------
// Mobile Navigation (375x667)
// ---------------------------------------------------------------------------
test.describe("Mobile Navigation", () => {
  test("hamburger menu toggles sidebar overlay", async ({ browser }) => {
    const context = await browser.newContext({
      viewport: { width: 375, height: 667 },
    });
    const page = await context.newPage();
    await page.goto("/login");
    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");
    await page.getByRole("button", { name: /login/i }).click();
    await page.waitForURL("/", { timeout: 15_000 });

    // Desktop sidebar should not be visible
    await expect(page.locator("aside")).not.toBeVisible();

    // Open hamburger menu
    const topBar = page.locator(".fixed").filter({ hasText: "SnapOtter" }).first();
    const hamburger = topBar.locator("button").first();
    await hamburger.click();

    // Sidebar overlay should appear with nav items
    await expect(page.getByText("Tools").nth(1)).toBeVisible();
    await expect(page.getByText("Grid")).toBeVisible();

    await context.close();
  });

  test("tapping backdrop closes sidebar overlay", async ({ browser }) => {
    const context = await browser.newContext({
      viewport: { width: 375, height: 667 },
    });
    const page = await context.newPage();
    await page.goto("/login");
    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");
    await page.getByRole("button", { name: /login/i }).click();
    await page.waitForURL("/", { timeout: 15_000 });

    // Open hamburger menu
    const topBar = page.locator(".fixed").filter({ hasText: "SnapOtter" }).first();
    const hamburger = topBar.locator("button").first();
    await hamburger.click();

    // Sidebar overlay should appear
    const backdrop = page.locator(".fixed.inset-0").first();
    await expect(backdrop).toBeVisible();

    // Click the backdrop to close
    await backdrop.click({ position: { x: 300, y: 300 } });
    await page.waitForTimeout(300);

    // Sidebar overlay should be closed (expanded sidebar nav no longer visible)
    await expect(backdrop).not.toBeVisible();

    await context.close();
  });

  test("bottom nav navigates between all main sections", async ({ browser }) => {
    const context = await browser.newContext({
      viewport: { width: 375, height: 667 },
    });
    const page = await context.newPage();
    await page.goto("/login");
    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");
    await page.getByRole("button", { name: /login/i }).click();
    await page.waitForURL("/", { timeout: 15_000 });

    const bottomNav = page.locator("nav.fixed");

    // Navigate to Automate
    await bottomNav.getByText("Automate").click();
    await expect(page).toHaveURL("/automate");

    // Navigate to Files
    await bottomNav.getByText("Files").click();
    await expect(page).toHaveURL("/files");

    // Navigate back to Tools
    await bottomNav.getByText("Tools").click();
    await expect(page).toHaveURL("/");

    await context.close();
  });

  test("bottom nav has Editor link", async ({ browser }) => {
    const context = await browser.newContext({
      viewport: { width: 375, height: 667 },
    });
    const page = await context.newPage();
    await page.goto("/login");
    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");
    await page.getByRole("button", { name: /login/i }).click();
    await page.waitForURL("/", { timeout: 15_000 });

    const bottomNav = page.locator("nav.fixed");
    await expect(bottomNav.getByText("Editor")).toBeVisible();

    await bottomNav.getByText("Editor").click();
    await expect(page).toHaveURL("/editor");

    await context.close();
  });

  test("hamburger menu Grid link navigates to /fullscreen", async ({ browser }) => {
    const context = await browser.newContext({
      viewport: { width: 375, height: 667 },
    });
    const page = await context.newPage();
    await page.goto("/login");
    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");
    await page.getByRole("button", { name: /login/i }).click();
    await page.waitForURL("/", { timeout: 15_000 });

    // Open hamburger menu
    const topBar = page.locator(".fixed").filter({ hasText: "SnapOtter" }).first();
    const hamburger = topBar.locator("button").first();
    await hamburger.click();

    // Click Grid in expanded sidebar
    await page.getByText("Grid").click();
    await expect(page).toHaveURL("/fullscreen");

    await context.close();
  });

  test("hamburger menu Automate link navigates to /automate", async ({ browser }) => {
    const context = await browser.newContext({
      viewport: { width: 375, height: 667 },
    });
    const page = await context.newPage();
    await page.goto("/login");
    await page.getByLabel("Username").fill("admin");
    await page.getByLabel("Password").fill("admin");
    await page.getByRole("button", { name: /login/i }).click();
    await page.waitForURL("/", { timeout: 15_000 });

    const topBar = page.locator(".fixed").filter({ hasText: "SnapOtter" }).first();
    const hamburger = topBar.locator("button").first();
    await hamburger.click();

    await page.getByText("Automate").nth(1).click();
    await expect(page).toHaveURL("/automate");

    await context.close();
  });
});

// ---------------------------------------------------------------------------
// Editor Page (/editor)
// ---------------------------------------------------------------------------
test.describe("Editor Page", () => {
  test("editor page renders with canvas area", async ({ loggedInPage: page }) => {
    await page.goto("/editor");

    await expect(page).toHaveURL("/editor");
    // Editor should have a canvas or main editor area
    await expect(page.getByText(/editor|canvas|draw/i).first()).toBeVisible();
  });

  test("editor page is accessible from sidebar", async ({ loggedInPage: page }) => {
    await page.locator("aside").getByText("Editor").click();
    await expect(page).toHaveURL("/editor");
  });

  test("page refresh preserves /editor route", async ({ loggedInPage: page }) => {
    await page.goto("/editor");
    await expect(page).toHaveURL("/editor");

    await page.reload();
    await expect(page).toHaveURL("/editor");
  });
});

// ---------------------------------------------------------------------------
// Settings Dialog - Tab Navigation
// ---------------------------------------------------------------------------
test.describe("Settings Dialog Tabs", () => {
  test("settings dialog shows all navigation sections", async ({ loggedInPage: page }) => {
    await openSettings(page);

    // Core sections should be listed in nav
    await expect(page.getByRole("button", { name: "General" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Security" })).toBeVisible();
    await expect(page.getByRole("button", { name: "About" })).toBeVisible();
  });

  test("clicking Security tab shows security settings", async ({ loggedInPage: page }) => {
    await openSettings(page);

    await page.getByRole("button", { name: "Security" }).click();
    await page.waitForTimeout(300);

    // Security section content should appear
    await expect(page.getByRole("heading", { name: "Security" })).toBeVisible();
  });

  test("clicking About tab shows version info", async ({ loggedInPage: page }) => {
    await openSettings(page);

    await page.getByRole("button", { name: "About" }).click();
    await page.waitForTimeout(300);

    // About section should show version
    await expect(page.getByText(/version/i).first()).toBeVisible();
  });

  test("switching between tabs preserves dialog open state", async ({ loggedInPage: page }) => {
    await openSettings(page);

    // Switch to Security
    await page.getByRole("button", { name: "Security" }).click();
    await page.waitForTimeout(200);
    await expect(page.getByRole("dialog")).toBeVisible();

    // Switch to About
    await page.getByRole("button", { name: "About" }).click();
    await page.waitForTimeout(200);
    await expect(page.getByRole("dialog")).toBeVisible();

    // Switch back to General
    await page.getByRole("button", { name: "General" }).click();
    await page.waitForTimeout(200);
    await expect(page.getByRole("dialog")).toBeVisible();
    await expect(page.getByRole("heading", { name: "General" })).toBeVisible();
  });
});

// ---------------------------------------------------------------------------
// Language Selector
// ---------------------------------------------------------------------------
test.describe("Language Selector", () => {
  test("language button opens language dropdown", async ({ loggedInPage: page }) => {
    const langBtn = page.locator("button[title='Language']");
    await expect(langBtn).toBeVisible();

    await langBtn.click();
    await page.waitForTimeout(300);

    // Language options should appear
    await expect(page.getByText(/espa|fran|deutsch|portugu/i).first()).toBeVisible();
  });

  test("selecting a language updates the button label", async ({ loggedInPage: page }) => {
    const langBtn = page.locator("button[title='Language']");
    await expect(langBtn).toContainText("English");

    await langBtn.click();
    await page.waitForTimeout(300);

    // Pick a different language and check the button updates
    const spanishOption = page.getByText(/espa/i).first();
    if (await spanishOption.isVisible({ timeout: 3000 }).catch(() => false)) {
      await spanishOption.click();
      await page.waitForTimeout(500);

      // Button should no longer say "English"
      await expect(langBtn).not.toContainText("English");

      // Reset back to English
      await langBtn.click();
      await page.waitForTimeout(300);
      await page.getByText("English").first().click();
    }
  });
});

// ---------------------------------------------------------------------------
// Fullscreen Grid - Tool Visibility
// ---------------------------------------------------------------------------
test.describe("Fullscreen Grid - AI Tool Visibility", () => {
  test("AI tools section is visible in fullscreen grid", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");

    await expect(page.getByText("AI Tools")).toBeVisible();
    // At least one AI tool should be listed
    await expect(page.getByRole("link", { name: /Remove Background/ }).first()).toBeVisible();
  });

  test("tool cards display an icon and name", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");

    // A tool card should have visible text for its name
    const resizeLink = page.getByRole("link", { name: /^Resize/ }).first();
    await expect(resizeLink).toBeVisible();

    // And it should contain an SVG icon
    await expect(resizeLink.locator("svg").first()).toBeVisible();
  });
});

// ---------------------------------------------------------------------------
// Automate Page - Additional Coverage
// ---------------------------------------------------------------------------
test.describe("Automate Page - Pipeline Management", () => {
  test("removing a pipeline step returns to empty state", async ({ loggedInPage: page }) => {
    await page.goto("/automate");

    // Add a tool step
    const resizeTool = page.locator("[data-tool-id='resize']").first();
    if (await resizeTool.isVisible({ timeout: 3000 }).catch(() => false)) {
      await resizeTool.click();
    } else {
      await page.getByText("Resize").first().click();
    }
    await page.waitForTimeout(500);

    // Step should be added
    await expect(page.getByText("No steps yet")).not.toBeVisible();

    // Remove the step (click the remove/delete button on the step)
    const removeBtn = page
      .locator("button")
      .filter({ has: page.locator("svg") })
      .filter({
        hasText: /remove|delete|x/i,
      })
      .first();
    if (await removeBtn.isVisible({ timeout: 2000 }).catch(() => false)) {
      await removeBtn.click();
      await page.waitForTimeout(300);
      await expect(page.getByText("No steps yet")).toBeVisible();
    }
  });

  test("adding multiple steps shows ordered step list", async ({ loggedInPage: page }) => {
    await page.goto("/automate");

    // Add first tool
    const resizeTool = page.locator("[data-tool-id='resize']").first();
    if (await resizeTool.isVisible({ timeout: 3000 }).catch(() => false)) {
      await resizeTool.click();
    } else {
      await page.getByText("Resize").first().click();
    }
    await page.waitForTimeout(300);

    // Add second tool
    const compressTool = page.locator("[data-tool-id='compress']").first();
    if (await compressTool.isVisible({ timeout: 3000 }).catch(() => false)) {
      await compressTool.click();
    } else {
      await page.getByText("Compress").first().click();
    }
    await page.waitForTimeout(300);

    // Both tools should be listed as steps
    await expect(page.getByText("Resize").first()).toBeVisible();
    await expect(page.getByText("Compress").first()).toBeVisible();
  });
});

// ---------------------------------------------------------------------------
// Routing - Additional Edge Cases
// ---------------------------------------------------------------------------
test.describe("Routing - Additional Edge Cases", () => {
  test("/change-password page renders for authenticated user", async ({ loggedInPage: page }) => {
    await page.goto("/change-password");

    // Should render the change password form
    await expect(page.getByText(/change password|new password/i).first()).toBeVisible();
  });

  test("navigating to /editor and back preserves home state", async ({ loggedInPage: page }) => {
    // Start at home
    await expect(page).toHaveURL("/");

    // Navigate to editor
    await page.goto("/editor");
    await expect(page).toHaveURL("/editor");

    // Navigate back
    await page.goBack();
    await expect(page).toHaveURL("/");

    // Home content should be intact
    await expect(page.getByText("Upload from computer")).toBeVisible();
  });

  test("deep-linking to a specific tool page works", async ({ loggedInPage: page }) => {
    await page.goto("/image/watermark-text");
    await expect(page).toHaveURL("/watermark-text");
    await expect(page.getByText("Text Watermark").first()).toBeVisible();
  });

  test("double navigation to same page does not break state", async ({ loggedInPage: page }) => {
    await page.goto("/fullscreen");
    await expect(page).toHaveURL("/fullscreen");

    await page.goto("/fullscreen");
    await expect(page).toHaveURL("/fullscreen");

    // Page should still work correctly
    await expect(page.getByPlaceholder(/search/i)).toBeVisible();
  });

  test("navigating from a legacy redirect to another page works", async ({
    loggedInPage: page,
  }) => {
    await page.goto("/brightness-contrast");
    await expect(page).toHaveURL("/image/adjust-colors");

    await page.goto("/fullscreen");
    await expect(page).toHaveURL("/fullscreen");

    await page.goBack();
    await expect(page).toHaveURL("/image/adjust-colors");
  });
});

// ---------------------------------------------------------------------------
// Tool Page - Mobile Structure (375x667)
// ---------------------------------------------------------------------------
test.describe("Tool Page - Mobile Structure", () => {
  const MOBILE_TOOLS = [
    { id: "resize", name: "Resize" },
    { id: "compress", name: "Compress" },
    { id: "convert", name: "Convert" },
    { id: "crop", name: "Crop" },
    { id: "watermark-text", name: "Text Watermark" },
    { id: "adjust-colors", name: "Adjust Colors" },
  ];

  for (const tool of MOBILE_TOOLS) {
    test(`mobile: ${tool.name} (/${tool.id}) shows tool name and dropzone`, async ({ browser }) => {
      const context = await browser.newContext({
        viewport: { width: 375, height: 667 },
      });
      const page = await context.newPage();
      await page.goto("/login");
      await page.getByLabel("Username").fill("admin");
      await page.getByLabel("Password").fill("admin");
      await page.getByRole("button", { name: /login/i }).click();
      await page.waitForURL("/", { timeout: 15_000 });

      await page.goto(`/${tool.id}`);

      // Tool name should be visible
      await expect(page.getByText(tool.name).first()).toBeVisible();

      // Dropzone should be visible on mobile too
      const dropzone = page.locator("[class*='border-dashed']").first();
      await expect(dropzone).toBeVisible();

      // No horizontal overflow
      const scrollWidth = await page.evaluate(() => document.documentElement.scrollWidth);
      const clientWidth = await page.evaluate(() => document.documentElement.clientWidth);
      expect(scrollWidth).toBeLessThanOrEqual(clientWidth);

      await context.close();
    });
  }
});
