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

const PLATFORM_URL = process.env.E2E_PLATFORM_ADMIN_URL || 'http://localhost:3003';

/** Set a fake auth token so AuthGuard allows page rendering */
async function bypassAuth(page: Page) {
  await page.goto(`${PLATFORM_URL}/login`, { waitUntil: 'domcontentloaded' });
  await page.evaluate(() => {
    localStorage.setItem('fitcrm_platform_access_token', '__e2e_test_token__');
    localStorage.setItem('fitcrm_platform_refresh_token', '__e2e_test_refresh__');
  });
}

/** Mock API calls to prevent 401→logout redirect when using fake tokens */
async function mockApiCalls(page: Page) {
  // Mock the theme current endpoint (public)
  await page.route('**/v1/theme/current', (route) =>
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({ themeId: 'fitpulse-orange', isExplicit: true }),
    }),
  );
  // Mock the theme save endpoint to prevent 401→logout
  await page.route('**/v1/admin/themes/active', (route) =>
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({ success: true }),
    }),
  );
  // Mock auth refresh to prevent logout cascade
  await page.route('**/v1/auth/refresh', (route) =>
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({
        accessToken: '__e2e_test_token__',
        refreshToken: '__e2e_test_refresh__',
      }),
    }),
  );
  // Mock auth profile to prevent auth checks from failing
  await page.route('**/v1/auth/profile', (route) =>
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({
        id: 'test',
        role: 'super_admin',
        phone: '+70000000001',
      }),
    }),
  );
}

test.describe('Панель суперадмина — UI', () => {
  test('Редирект на /login для неавторизованного', async ({ page }) => {
    await page.goto(PLATFORM_URL);
    await page.waitForURL(/login/);
    await expect(
      page.locator('input[type="tel"], input[name="phone"], input[placeholder*="елефон"]').first(),
    ).toBeVisible();
  });

  test('Страница логина — форма с полями телефон и пароль', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/login`);
    const phoneInput = page
      .locator('input[type="tel"], input[name="phone"], input[placeholder*="елефон"]')
      .first();
    const passwordInput = page.locator('input[type="password"]').first();
    const submitBtn = page.getByRole('button', { name: /войти/i }).first();

    await expect(phoneInput).toBeVisible();
    await expect(passwordInput).toBeVisible();
    await expect(submitBtn).toBeVisible();
  });

  test('Ошибка при неверном пароле', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/login`);
    const phoneInput = page
      .locator('input[type="tel"], input[name="phone"], input[placeholder*="елефон"]')
      .first();
    const passwordInput = page.locator('input[type="password"]').first();
    const submitBtn = page.getByRole('button', { name: /войти/i }).first();

    await phoneInput.fill('+70000000001');
    await passwordInput.fill('wrongpassword');
    await submitBtn.click();

    // Should show error
    await page.waitForTimeout(2000);
    // At least we should still be on login
    await expect(page).toHaveURL(/login/);
  });

  test('Страница /dashboard загружается (статически)', async ({ page }) => {
    const response = await page.goto(`${PLATFORM_URL}/dashboard`);
    const status = response?.status() ?? 200;
    expect(status).toBeLessThan(500);
  });

  test('Страница /clubs загружается без 500', async ({ page }) => {
    const response = await page.goto(`${PLATFORM_URL}/clubs`);
    const status = response?.status() ?? 200;
    expect(status).toBeLessThan(500);
  });

  test('Страница /licenses загружается без 500', async ({ page }) => {
    const response = await page.goto(`${PLATFORM_URL}/licenses`);
    const status = response?.status() ?? 200;
    expect(status).toBeLessThan(500);
  });

  test('Страница /monitoring загружается без 500', async ({ page }) => {
    const response = await page.goto(`${PLATFORM_URL}/monitoring`);
    const status = response?.status() ?? 200;
    expect(status).toBeLessThan(500);
  });

  test('Страница /audit загружается без 500', async ({ page }) => {
    const response = await page.goto(`${PLATFORM_URL}/audit`);
    const status = response?.status() ?? 200;
    expect(status).toBeLessThan(500);
  });

  test('Страница /documents загружается без 500', async ({ page }) => {
    const response = await page.goto(`${PLATFORM_URL}/documents`);
    const status = response?.status() ?? 200;
    expect(status).toBeLessThan(500);
  });

  test('Страница /development — редирект на /login (AuthGuard)', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/development`);
    await page.waitForLoadState('networkidle');
    const url = page.url();
    expect(url).toMatch(/login|development/);
    if (url.includes('login')) {
      await expect(page.locator('input[type="password"]').first()).toBeVisible();
    }
  });

  test('Вкладка «Тестирование» — защищена AuthGuard', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/development?tab=testing`);
    await page.waitForLoadState('networkidle');
    const url = page.url();
    expect(url).toMatch(/login|development/);
  });

  test('Документ dev-status — защищён AuthGuard', async ({ page }) => {
    const response = await page.goto(`${PLATFORM_URL}/document/dev-status`);
    const status = response?.status() ?? 200;
    expect(status).toBeLessThan(500);
    await page.waitForLoadState('networkidle');
    const url = page.url();
    expect(url).toMatch(/login|document/);
  });

  test('Страница /settings/themes загружается без 500', async ({ page }) => {
    const response = await page.goto(`${PLATFORM_URL}/settings/themes`);
    const status = response?.status() ?? 200;
    expect(status).toBeLessThan(500);
  });
});

test.describe('Система тем оформления', () => {
  test.beforeEach(async ({ page }) => {
    await mockApiCalls(page);
    await bypassAuth(page);
  });

  test('Страница тем загружается и отображает все 10 тем', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/settings/themes`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    const url = page.url();
    if (url.includes('/login')) {
      test.skip(true, 'API rejected test token — auth-dependent test');
      return;
    }

    const themeNames = [
      'FitPulse Orange',
      'Crimson Power',
      'Royal Blue',
      'Emerald Wellness',
      'Nordic Frost',
      'Pacific Teal',
      'Amethyst Light',
      'Rose Garden',
      'Sunset Coral',
      'Cloud Professional',
    ];
    for (const name of themeNames) {
      await expect(page.getByText(name, { exact: false }).first()).toBeVisible({ timeout: 5000 });
    }
  });

  test('Сайдбар содержит ссылку «Темы оформления»', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/dashboard`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    const url = page.url();
    if (url.includes('/login')) {
      test.skip(true, 'API rejected test token — auth-dependent test');
      return;
    }

    const themesLink = page.locator('a[href="/settings/themes"]');
    await expect(themesLink).toBeVisible({ timeout: 5000 });
    await expect(themesLink).toContainText('Темы оформления');
  });

  test('Клик «Применить» меняет CSS-переменные темы', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/settings/themes`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    const url = page.url();
    if (url.includes('/login')) {
      test.skip(true, 'API rejected test token — auth-dependent test');
      return;
    }

    // Active theme shows "Активна" instead of "Применить",
    // so nth(0) = first non-active theme = Crimson Power
    const allApplyBtns = page.getByRole('button', { name: /применить/i });
    const count = await allApplyBtns.count();
    expect(count).toBeGreaterThanOrEqual(1);

    await allApplyBtns.nth(0).click();

    // Wait for theme to actually change (CSS var update after React state)
    await page.waitForFunction(
      () =>
        getComputedStyle(document.documentElement)
          .getPropertyValue('--primary')
          .trim()
          .toLowerCase() === '#dc2626',
      { timeout: 10000 },
    );

    const newPrimary = await page.evaluate(() =>
      getComputedStyle(document.documentElement).getPropertyValue('--primary').trim(),
    );
    expect(newPrimary.toLowerCase()).toBe('#dc2626');
  });

  test('Тема сохраняется в localStorage', async ({ page }) => {
    await page.goto(`${PLATFORM_URL}/settings/themes`, { waitUntil: 'domcontentloaded' });
    await page.waitForTimeout(2000);

    const url = page.url();
    if (url.includes('/login')) {
      test.skip(true, 'API rejected test token — auth-dependent test');
      return;
    }

    // Click apply on first non-active theme (nth(0) = Crimson Power)
    const applyBtns = page.getByRole('button', { name: /применить/i });
    const count = await applyBtns.count();
    expect(count).toBeGreaterThanOrEqual(1);

    await applyBtns.nth(0).click();

    // Wait for localStorage to be updated
    await page.waitForFunction(() => localStorage.getItem('fitcrm-theme') === 'crimson-power', {
      timeout: 10000,
    });

    const stored = await page.evaluate(() => localStorage.getItem('fitcrm-theme'));
    expect(stored).toBe('crimson-power');
  });

  test('Тема восстанавливается после перезагрузки', async ({ page }) => {
    await page.evaluate(() => {
      localStorage.setItem('fitcrm-theme', 'royal-blue');
    });

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

    // Wait for theme to be applied from localStorage (or redirect to /login)
    await page.waitForFunction(
      () => {
        const onLogin = window.location.pathname.includes('/login');
        const themeApplied = document.documentElement.dataset.theme === 'royal-blue';
        return onLogin || themeApplied;
      },
      { timeout: 10000 },
    );

    const currentUrl = page.url();
    if (currentUrl.includes('/login')) {
      test.skip(true, 'API rejected test token — auth-dependent test');
      return;
    }

    const primary = await page.evaluate(() =>
      getComputedStyle(document.documentElement).getPropertyValue('--primary').trim(),
    );
    expect(primary.toLowerCase()).toBe('#2563eb');

    const dataTheme = await page.evaluate(() => document.documentElement.dataset.theme);
    expect(dataTheme).toBe('royal-blue');
  });

  test('Все темы светлые — data-dark всегда "false"', async ({ page }) => {
    await page.evaluate(() => {
      localStorage.setItem('fitcrm-theme', 'nordic-frost');
    });

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

    await page.waitForFunction(
      () => {
        const onLogin = window.location.pathname.includes('/login');
        const themeApplied = document.documentElement.dataset.theme === 'nordic-frost';
        return onLogin || themeApplied;
      },
      { timeout: 10000 },
    );

    const currentUrl = page.url();
    if (currentUrl.includes('/login')) {
      test.skip(true, 'API rejected test token — auth-dependent test');
      return;
    }

    const dataDark = await page.evaluate(() => document.documentElement.dataset.dark);
    expect(dataDark).toBe('false');
  });

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

    const url = page.url();
    if (url.includes('/login')) {
      test.skip(true, 'API rejected test token — auth-dependent test');
      return;
    }

    // Get initial sidebar-bg CSS variable
    const initialSidebarBg = await page.evaluate(() =>
      getComputedStyle(document.documentElement).getPropertyValue('--color-sidebar-bg').trim(),
    );

    // Click apply on first non-active theme (Crimson Power)
    const applyBtns = page.getByRole('button', { name: /применить/i });
    const count = await applyBtns.count();
    expect(count).toBeGreaterThanOrEqual(1);

    await applyBtns.nth(0).click();

    // Wait for sidebar-bg to change
    await page.waitForFunction(
      (initial: string) => {
        const current = getComputedStyle(document.documentElement)
          .getPropertyValue('--color-sidebar-bg')
          .trim();
        return current !== '' && current !== initial;
      },
      initialSidebarBg,
      { timeout: 10000 },
    );

    // Verify sidebar element actually uses the new background
    const sidebar = page.locator('aside').first();
    const sidebarBgColor = await sidebar.evaluate((el) => getComputedStyle(el).backgroundColor);
    expect(sidebarBgColor).toBeTruthy();
    expect(sidebarBgColor).not.toBe('rgba(0, 0, 0, 0)');
  });

  test('Нет дублирующихся React-ключей на странице тем', async ({ page }) => {
    const consoleWarnings: string[] = [];
    page.on('console', (msg) => {
      if (msg.type() === 'warning' && msg.text().includes('same key')) {
        consoleWarnings.push(msg.text());
      }
    });

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

    const url = page.url();
    if (url.includes('/login')) {
      test.skip(true, 'API rejected test token — auth-dependent test');
      return;
    }

    expect(consoleWarnings, `Duplicate key warnings: ${consoleWarnings.join('; ')}`).toHaveLength(
      0,
    );
  });

  test('Все страницы платформы загружаются без JS-ошибок', async ({ page }) => {
    const jsErrors: string[] = [];
    page.on('pageerror', (err) => jsErrors.push(err.message));

    const pages = [
      '/login',
      '/dashboard',
      '/clubs',
      '/licenses',
      '/monitoring',
      '/audit',
      '/documents',
      '/settings/themes',
    ];

    for (const path of pages) {
      const response = await page.goto(`${PLATFORM_URL}${path}`, {
        waitUntil: 'domcontentloaded',
        timeout: 15000,
      });
      const status = response?.status() ?? 200;
      expect(status, `${path} returned 5xx`).toBeLessThan(500);
      await page.waitForTimeout(500);
    }

    // Filter out known non-critical errors (e.g., API 401 from fetch)
    const criticalErrors = jsErrors.filter(
      (e) => !e.includes('401') && !e.includes('Сессия истекла') && !e.includes('fetch'),
    );
    expect(criticalErrors, `Unexpected JS errors: ${criticalErrors.join('; ')}`).toHaveLength(0);
  });
});
