"""Tests for the E2E duplication checker."""

from pathlib import Path

import pytest

from stablestack.checkers.testing.e2e_duplication import E2EDuplicationChecker
from stablestack.models import Severity


@pytest.fixture
def checker():
    return E2EDuplicationChecker()


@pytest.fixture
def temp_ts_file(tmp_path):
    """Create a temporary TypeScript test file."""
    def _create(content: str, name: str = "example.spec.ts"):
        file_path = tmp_path / name
        file_path.write_text(content)
        return file_path
    return _create


class TestE2EDuplicationChecker:
    """Tests for E2EDuplicationChecker."""

    def test_detects_duplicated_login_helper(self, checker, temp_ts_file):
        """Should detect duplicated login helper function."""
        code = '''
import { test } from '@playwright/test';

async function login(page, email, password) {
  await page.goto('/login');
  await page.fill('input[type="email"]', email);
}

test('my test', async ({ page }) => {
  await login(page, 'test@example.com', 'password');
});
'''
        path = temp_ts_file(code)
        findings = checker.check_file(path, code)

        assert len(findings) >= 1
        assert any("login helper" in f.message.lower() for f in findings)
        assert any(f.severity == Severity.ERROR for f in findings)

    def test_detects_duplicated_wait_helper(self, checker, temp_ts_file):
        """Should detect duplicated wait helper function."""
        code = '''
async function waitForIdleRunner(page) {
  await page.waitForSelector('.ready');
}
'''
        path = temp_ts_file(code)
        findings = checker.check_file(path, code)

        assert len(findings) >= 1
        assert any("wait helper" in f.message.lower() for f in findings)

    def test_detects_hardcoded_test_email(self, checker, temp_ts_file):
        """Should detect hardcoded test email."""
        code = '''
const TEST_EMAIL = "test@example.com";
const testEmail = 'another@test.com';
'''
        path = temp_ts_file(code)
        findings = checker.check_file(path, code)

        assert len(findings) >= 2
        assert any("email" in f.message.lower() for f in findings)

    def test_detects_hardcoded_test_password(self, checker, temp_ts_file):
        """Should detect hardcoded test password."""
        code = '''
const TEST_PASSWORD = "secretpassword123";
'''
        path = temp_ts_file(code)
        findings = checker.check_file(path, code)

        assert len(findings) >= 1
        assert any("password" in f.message.lower() for f in findings)

    def test_detects_inline_selectors(self, checker, temp_ts_file):
        """Should detect inline selectors."""
        code = '''
await page.locator('input[type="email"]').fill('test@example.com');
await page.locator('input[type=password]').fill('password');
'''
        path = temp_ts_file(code)
        findings = checker.check_file(path, code)

        assert len(findings) >= 2
        assert any("selector" in f.message.lower() for f in findings)

    def test_detects_hardcoded_timeout(self, checker, temp_ts_file):
        """Should detect hardcoded timeout values."""
        code = '''
await page.waitForSelector('.element', { timeout: 10000 });
await page.goto('/page', { timeout: 30000 });
'''
        path = temp_ts_file(code)
        findings = checker.check_file(path, code)

        assert len(findings) >= 2
        assert any("timeout" in f.message.lower() for f in findings)

    def test_detects_test_skip(self, checker, temp_ts_file):
        """Should detect forbidden test.skip()."""
        code = '''
test.skip('broken test', async ({ page }) => {
  // This test is broken
});
'''
        path = temp_ts_file(code)
        findings = checker.check_file(path, code)

        assert len(findings) >= 1
        assert any("skip" in f.message.lower() for f in findings)
        assert any(f.severity == Severity.ERROR for f in findings)

    def test_detects_test_only(self, checker, temp_ts_file):
        """Should detect test.only() left in code."""
        code = '''
test.only('focused test', async ({ page }) => {
  // Only this test will run
});
'''
        path = temp_ts_file(code)
        findings = checker.check_file(path, code)

        assert len(findings) >= 1
        assert any("only" in f.message.lower() for f in findings)
        assert any(f.severity == Severity.ERROR for f in findings)

    def test_detects_describe_only(self, checker, temp_ts_file):
        """Should detect describe.only() left in code."""
        code = '''
describe.only('focused suite', () => {
  test('test 1', async ({ page }) => {});
});
'''
        path = temp_ts_file(code)
        findings = checker.check_file(path, code)

        assert len(findings) >= 1
        assert any("only" in f.message.lower() for f in findings)

    def test_allows_clean_test_file(self, checker, temp_ts_file):
        """Should pass for clean test files using helpers."""
        code = '''
import { test, expect } from '@playwright/test';
import { login, SELECTORS, TIMEOUTS, TEST_CREDENTIALS } from './helpers';

test('login flow', async ({ page }) => {
  await login(page, TEST_CREDENTIALS.email, TEST_CREDENTIALS.password);
  await page.waitForSelector(SELECTORS.DASHBOARD, { timeout: TIMEOUTS.NAVIGATION });
  await expect(page.locator(SELECTORS.WELCOME_MESSAGE)).toBeVisible();
});
'''
        path = temp_ts_file(code)
        findings = checker.check_file(path, code)

        # Should have no findings for this clean file
        assert len(findings) == 0

    def test_skips_helper_files(self, checker, temp_ts_file):
        """Should skip helper files."""
        code = '''
// This is the helpers file, definitions are OK here
export async function login(page, email, password) {
  await page.goto('/login');
}

export const TEST_CREDENTIALS = {
  email: 'test@example.com',
  password: 'testpass123',
};
'''
        path = temp_ts_file(code, name="helpers.ts")
        assert checker.should_skip_file(path) is True

    def test_skips_non_test_files(self, checker, temp_ts_file):
        """Should skip non-test/spec files."""
        code = '''
const config = { timeout: 10000 };
'''
        path = temp_ts_file(code, name="config.ts")
        assert checker.should_skip_file(path) is True

    def test_checks_spec_files(self, checker, temp_ts_file):
        """Should check .spec.ts files."""
        path = temp_ts_file("", name="login.spec.ts")
        assert checker.should_skip_file(path) is False

    def test_checks_test_files(self, checker, temp_ts_file):
        """Should check .test.ts files."""
        path = temp_ts_file("", name="login.test.ts")
        assert checker.should_skip_file(path) is False
