import { test, expect } from '@playwright/test';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = dirname(fileURLToPath(import.meta.url));

async function loadCube(page: import('@playwright/test').Page) {
  await page.locator('#file-input').setInputFiles(resolve(__dirname, '../fixtures/cube.obj'));
  await page.waitForTimeout(3000);
}

test.describe('UI Layout', () => {
  test('all main elements are visible on load', async ({ page }) => {
    await page.goto('/');
    await expect(page.locator('[data-testid="menu-bar"]')).toBeVisible({ timeout: 10000 });
    await expect(page.locator('[data-testid="toolbar-row-1"]')).toBeVisible();
    await expect(page.locator('[data-testid="project-panel"]')).toBeVisible();
    await expect(page.locator('[data-testid="status-bar"]')).toBeVisible();
    await expect(page.locator('canvas').first()).toBeVisible();
  });

  test('Filters menu has multiple categories', async ({ page }) => {
    await page.goto('/');
    await page.click('[data-testid="menu-Filters"]');
    await expect(page.locator('text=Smoothing').first()).toBeVisible();
    await expect(page.locator('text=Cleaning and Repairing').first()).toBeVisible();
    await expect(page.locator('text=Remeshing').first()).toBeVisible();
  });

  test('Edit menu has Undo option', async ({ page }) => {
    await page.goto('/');
    await page.click('[data-testid="menu-Edit"]');
    await expect(page.locator('text=Undo').first()).toBeVisible();
  });
});

test.describe('Layers', () => {
  test('Project panel shows layer after loading file', async ({ page }) => {
    await page.goto('/');
    await page.locator('canvas').first().waitFor({ state: 'visible', timeout: 10000 });
    await loadCube(page);
    await expect(page.locator('[data-testid="layer-item"]').first()).toBeVisible({ timeout: 10000 });
  });

  test('loading second file adds a layer', async ({ page }) => {
    await page.goto('/');
    await page.locator('canvas').first().waitFor({ state: 'visible', timeout: 10000 });
    await loadCube(page);
    await page.locator('#file-input').setInputFiles(resolve(__dirname, '../fixtures/cube.stl'));
    await page.waitForTimeout(3000);
    await page.waitForTimeout(2000);
    const items = page.locator('[data-testid="layer-item"]');
    await expect(items).toHaveCount(2, { timeout: 15000 });
  });
});

test.describe('Filter Panel via Menu', () => {
  test('Smoothing filters accessible from menu', async ({ page }) => {
    await page.goto('/');
    await page.click('[data-testid="menu-Filters"]');
    await page.locator('[data-testid="menu-bar"]').locator('text=Smoothing').click();
    await expect(page.locator('text=Laplacian Smooth').first()).toBeVisible();
  });
});

test.describe('Keyboard shortcuts', () => {
  test('number keys switch render mode', async ({ page }) => {
    await page.goto('/');
    await page.locator('canvas').first().waitFor({ state: 'visible', timeout: 10000 });
    await page.keyboard.press('3');
    await page.waitForTimeout(300);
    await expect(page.locator('[data-testid="mode-wireframe"]')).toHaveAttribute('data-active', 'true');
  });
});

test.describe('Responsive', () => {
  test('menu bar visible on narrow viewport', async ({ page }) => {
    await page.setViewportSize({ width: 600, height: 800 });
    await page.goto('/');
    await expect(page.locator('[data-testid="menu-bar"]')).toBeVisible({ timeout: 10000 });
  });
});

test.describe('Error Handling', () => {
  test('unsupported format shows error toast', async ({ page }) => {
    await page.goto('/');
    await page.locator('canvas').first().waitFor({ state: 'visible', timeout: 10000 });
    await page.locator('#file-input').setInputFiles({
      name: 'model.fbx', mimeType: 'application/octet-stream', buffer: Buffer.from('fake'),
    });
    await page.waitForTimeout(1000);
    await expect(page.locator('[data-testid="error-toast"]')).toBeVisible();
  });

  test('success toast shown on file load', async ({ page }) => {
    await page.goto('/');
    await page.locator('canvas').first().waitFor({ state: 'visible', timeout: 10000 });
    await loadCube(page);
    await expect(page.locator('[data-testid="error-toast"]')).toBeVisible();
  });
});
