import { test, expect, Page } from '@playwright/test';

/**
 * Mobile layout tests — verify correct element positioning on small screens.
 * Tests run at iPhone 14 viewport (390x844) across all 3 web admin panels.
 */

const MOBILE_VIEWPORT = { width: 390, height: 844 };
const TABLET_VIEWPORT = { width: 768, height: 1024 };

const PLATFORM_URL = process.env.E2E_PLATFORM_ADMIN_URL || 'http://localhost:3003';
const WEB_ADMIN_URL = process.env.E2E_WEB_ADMIN_URL || 'http://localhost:3001';
const CLUB_ADMIN_URL = process.env.E2E_CLUB_ADMIN_URL || 'http://localhost:3002';

/** Set fake auth tokens for all 3 apps */
async function bypassAuth(page: Page, url: string) {
  await page.goto(`${url}/login`, { waitUntil: 'domcontentloaded' });
  await page.evaluate(() => {
    // Platform admin token
    localStorage.setItem('fitcrm_platform_access_token', '__e2e_test_token__');
    localStorage.setItem('fitcrm_platform_refresh_token', '__e2e_test_refresh__');
    // Web admin token
    localStorage.setItem('fitcrm_access_token', '__e2e_test_token__');
    localStorage.setItem('fitcrm_refresh_token', '__e2e_test_refresh__');
    // Club admin token
    localStorage.setItem('fitcrm_club_access_token', '__e2e_test_token__');
    localStorage.setItem('fitcrm_club_refresh_token', '__e2e_test_refresh__');
  });
}

/** Check if we got redirected to login (API rejected test token) */
function onLoginPage(page: Page): boolean {
  return page.url().includes('/login');
}

/* ─────────────── Platform Admin — Themes page mobile ─────────────── */

test.describe('Темы оформления — мобильная адаптация', () => {
  test.beforeEach(async ({ page }) => {
    await page.setViewportSize(MOBILE_VIEWPORT);
    await bypassAuth(page, PLATFORM_URL);
  });

  test('Сетка тем: 1 колонка на мобильном экране', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/settings/themes`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    // Grid should be single-column on mobile (390px)
    const grid = page.locator('[data-testid="themes-grid"]');
    await expect(grid).toBeVisible({ timeout: 5000 });

    const gridStyle = await grid.evaluate((el) => getComputedStyle(el).gridTemplateColumns);
    // Single column = one track value (e.g., "390px" or similar)
    const columnCount = gridStyle.split(/\s+/).length;
    expect(columnCount).toBe(1);
  });

  test('Сетка тем: 2 колонки на планшете', async ({ page }) => {
    await page.setViewportSize(TABLET_VIEWPORT);
    await page.goto(`${PLATFORM_URL}/settings/themes`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    const grid = page.locator('[data-testid="themes-grid"]');
    await expect(grid).toBeVisible({ timeout: 5000 });

    const gridStyle = await grid.evaluate((el) => getComputedStyle(el).gridTemplateColumns);
    // Two columns = two track values
    const columnCount = gridStyle.split(/\s+/).length;
    expect(columnCount).toBe(2);
  });

  test('Карточки тем: кнопки не обрезаются на мобильном', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/settings/themes`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    // Check first theme card actions container
    const firstActions = page.locator('[data-testid^="theme-actions-"]').first();
    await expect(firstActions).toBeVisible({ timeout: 5000 });

    // Get all buttons inside the actions area
    const buttons = firstActions.locator('button, div[class*="flex"]');
    const buttonCount = await buttons.count();
    expect(buttonCount).toBeGreaterThanOrEqual(1);

    // Verify each button is fully visible (not clipped)
    for (let i = 0; i < buttonCount; i++) {
      const btn = buttons.nth(i);
      const isVisible = await btn.isVisible();
      if (!isVisible) continue;

      const box = await btn.boundingBox();
      if (!box) continue;

      // Button must be within viewport width
      expect(box.x).toBeGreaterThanOrEqual(0);
      expect(box.x + box.width).toBeLessThanOrEqual(MOBILE_VIEWPORT.width + 1);

      // Button should have minimum touch-target height (44px recommended, we use 36+)
      expect(box.height).toBeGreaterThanOrEqual(32);
    }
  });

  test('Карточки тем: все 10 тем видны при прокрутке', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/settings/themes`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    const themeCards = page.locator('[data-testid^="theme-card-"]');
    await expect(themeCards).toHaveCount(10);

    // Each card should be scrollable into view and visible
    for (let i = 0; i < 10; i++) {
      const card = themeCards.nth(i);
      await card.scrollIntoViewIfNeeded();
      await expect(card).toBeVisible();

      const box = await card.boundingBox();
      expect(box).not.toBeNull();
      // Card should not overflow viewport width
      expect(box!.width).toBeLessThanOrEqual(MOBILE_VIEWPORT.width);
    }
  });

  test('Модальное окно предпросмотра: адаптивное на мобильном', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/settings/themes`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    // Click "Предпросмотр" button on first theme card
    const previewBtn = page.getByRole('button', { name: /предпросмотр/i }).first();
    await expect(previewBtn).toBeVisible({ timeout: 5000 });
    await previewBtn.click();

    // Modal should appear
    await page.waitForTimeout(500);
    const modal = page.locator('.fixed.inset-0').first();
    await expect(modal).toBeVisible();

    // Modal content should fit within viewport
    const modalContent = page.locator('.fixed.inset-0 > .relative').first();
    const box = await modalContent.boundingBox();
    expect(box).not.toBeNull();
    expect(box!.width).toBeLessThanOrEqual(MOBILE_VIEWPORT.width);

    // Mobile apply button should be visible in modal
    const mobileApplyBtn = modalContent.getByRole('button', { name: /применить/i });
    const applyCount = await mobileApplyBtn.count();
    expect(applyCount).toBeGreaterThanOrEqual(1);
  });

  test('Текущая тема: бейдж не обрезается', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/settings/themes`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    // The "current theme badge" area
    const badge = page.getByText('Текущая тема:').first();
    await expect(badge).toBeVisible({ timeout: 5000 });

    const box = await badge.boundingBox();
    expect(box).not.toBeNull();
    expect(box!.x + box!.width).toBeLessThanOrEqual(MOBILE_VIEWPORT.width);
  });
});

/* ─────────────── Platform Admin — Sidebar mobile ─────────────── */

test.describe('Сайдбар платформы — мобильный вид', () => {
  test.beforeEach(async ({ page }) => {
    await page.setViewportSize(MOBILE_VIEWPORT);
    await bypassAuth(page, PLATFORM_URL);
  });

  test('Сайдбар скрыт по умолчанию на мобильном', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/dashboard`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    // Desktop sidebar should be translated off-screen on mobile
    const sidebar = page.locator('aside').first();
    const isVisible = await sidebar.isVisible().catch(() => false);

    if (isVisible) {
      // On mobile the sidebar should be off-screen (transform: translateX(-100%))
      const transform = await sidebar.evaluate((el) => getComputedStyle(el).transform);
      // If visible but transformed, it's hidden visually
      if (transform && transform !== 'none') {
        expect(transform).toContain('matrix');
      }
    }
  });

  test('Кнопка меню видна на мобильном', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/dashboard`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    // Mobile menu button (hamburger) should be visible
    const menuBtn = page.locator('button[aria-label*="еню"], button[aria-label*="enu"]').first();
    const headerMenuBtn = page.locator('header button, [class*="mobile"] button').first();

    const hasMenu = await menuBtn.isVisible().catch(() => false);
    const hasHeader = await headerMenuBtn.isVisible().catch(() => false);

    expect(hasMenu || hasHeader).toBeTruthy();
  });
});

/* ─────────────── Web Admin (Reception) — Mobile ─────────────── */

test.describe('Панель рецепции — мобильный вид', () => {
  test.beforeEach(async ({ page }) => {
    await page.setViewportSize(MOBILE_VIEWPORT);
  });

  test('Страница загружается без 500 на мобильном', async ({ page }) => {
    const response = await page.goto(WEB_ADMIN_URL, { waitUntil: 'domcontentloaded' });
    expect(response?.status()).toBeLessThan(500);
  });

  test('Логин — элементы формы в пределах viewport', async ({ page }) => {
    await page.goto(`${WEB_ADMIN_URL}/login`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(1000);

    // Check that the page doesn't have horizontal overflow
    const hasHorizontalScroll = await page.evaluate(() => {
      return document.documentElement.scrollWidth > document.documentElement.clientWidth;
    });
    expect(hasHorizontalScroll).toBe(false);
  });

  test('Сайдбар скрыт по умолчанию', async ({ page }) => {
    await bypassAuth(page, WEB_ADMIN_URL);
    await page.goto(`${WEB_ADMIN_URL}/reception`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    // On mobile, sidebar should not take visible space
    const sidebar = page.locator('aside').first();
    const box = await sidebar.boundingBox().catch(() => null);

    if (box) {
      // Sidebar should be off-screen (negative x or transformed)
      const x = box.x;
      expect(x).toBeLessThanOrEqual(0);
    }
  });
});

/* ─────────────── Club Admin — Mobile ─────────────── */

test.describe('Панель клуба — мобильный вид', () => {
  test.beforeEach(async ({ page }) => {
    await page.setViewportSize(MOBILE_VIEWPORT);
  });

  test('Страница загружается без 500 на мобильном', async ({ page }) => {
    const response = await page.goto(CLUB_ADMIN_URL, { waitUntil: 'domcontentloaded' });
    expect(response?.status()).toBeLessThan(500);
  });

  test('Нет горизонтального скролла на мобильном', async ({ page }) => {
    await page.goto(`${CLUB_ADMIN_URL}/login`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(1000);

    const hasHorizontalScroll = await page.evaluate(() => {
      return document.documentElement.scrollWidth > document.documentElement.clientWidth;
    });
    expect(hasHorizontalScroll).toBe(false);
  });

  test('Мобильный хедер виден, десктопный сайдбар скрыт', async ({ page }) => {
    await bypassAuth(page, CLUB_ADMIN_URL);
    await page.goto(`${CLUB_ADMIN_URL}/dashboard`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    // Desktop sidebar should be off-screen on mobile
    const sidebar = page.locator('aside').first();
    const sidebarBox = await sidebar.boundingBox().catch(() => null);

    if (sidebarBox) {
      expect(sidebarBox.x).toBeLessThanOrEqual(0);
    }
  });
});

/* ─────────────── Cross-service theme application ─────────────── */

test.describe('Кросс-сервисная тема — CSS переменные', () => {
  test('Platform Admin: CSS-переменные темы установлены', async ({ page }) => {
    await page.setViewportSize(MOBILE_VIEWPORT);
    await bypassAuth(page, PLATFORM_URL);

    await page.goto(`${PLATFORM_URL}/settings/themes`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    if (onLoginPage(page)) {
      test.skip(true, 'API rejected test token');
      return;
    }

    // Check that CSS variables exist on <html>
    const hasPrimary = await page.evaluate(() => {
      const v = getComputedStyle(document.documentElement).getPropertyValue('--primary').trim();
      return v !== '';
    });
    expect(hasPrimary).toBe(true);
  });

  test('Web Admin: тема применяется через ThemeProvider', async ({ page }) => {
    await page.setViewportSize(MOBILE_VIEWPORT);
    const response = await page.goto(WEB_ADMIN_URL, { waitUntil: 'domcontentloaded' });
    expect(response?.status()).toBeLessThan(500);

    // Wait for ThemeProvider to run
    await page.waitForTimeout(2000);

    // The @theme block in globals.css should set default colors even without API
    const hasBg = await page.evaluate(() => {
      const v = getComputedStyle(document.documentElement).getPropertyValue('--color-background').trim();
      return v !== '';
    });
    expect(hasBg).toBe(true);
  });

  test('Club Admin: тема применяется через ThemeProvider', async ({ page }) => {
    await page.setViewportSize(MOBILE_VIEWPORT);
    const response = await page.goto(CLUB_ADMIN_URL, { waitUntil: 'domcontentloaded' });
    expect(response?.status()).toBeLessThan(500);

    await page.waitForTimeout(2000);

    const hasBg = await page.evaluate(() => {
      const v = getComputedStyle(document.documentElement).getPropertyValue('--color-background').trim();
      return v !== '';
    });
    expect(hasBg).toBe(true);
  });
});
