"""
Pytest configuration and fixtures for Cognitive Prism Automation Tests
"""
import sys
from pathlib import Path

# Add project root to Python path
project_root = Path(__file__).parent.parent
if str(project_root) not in sys.path:
    sys.path.insert(0, str(project_root))

import pytest
from selenium.webdriver import Chrome, Firefox, Edge
from utils.driver_manager import DriverManager
from pages.login_page import LoginPage
from config.config import SCREENSHOT_ON_FAILURE, SCREENSHOT_DIR
import os


def pytest_configure(config):
    """Register custom pytest markers"""
    config.addinivalue_line(
        "markers", "authentication: marks tests as authentication tests"
    )
    config.addinivalue_line(
        "markers", "login: marks tests as login tests"
    )
    config.addinivalue_line(
        "markers", "password_reset: marks tests as password reset tests"
    )
    config.addinivalue_line(
        "markers", "logout: marks tests as logout tests"
    )
    config.addinivalue_line(
        "markers", "integration: marks tests as integration tests"
    )
    config.addinivalue_line(
        "markers", "component: marks tests as component-level isolated tests (optional, run first)"
    )
    config.addinivalue_line(
        "markers", "profile: marks tests as profile related tests"
    )
    config.addinivalue_line(
        "markers", "assessment: marks tests as assessment flow tests"
    )
    config.addinivalue_line(
        "markers", "domain_assessment: marks tests as domain assessment tests"
    )
    config.addinivalue_line(
        "markers", "e2e: marks tests as end-to-end tests"
    )
    config.addinivalue_line(
        "markers", "complete_flow: marks tests as complete flow tests"
    )
    config.addinivalue_line(
        "markers", "final_feedback: marks tests as final feedback tests"
    )
    config.addinivalue_line(
        "markers", "domain_feedback: marks tests as domain feedback tests"
    )
    config.addinivalue_line(
        "markers", "domains_page: marks tests as domains page tests"
    )
    config.addinivalue_line(
        "markers", "assessments_page: marks tests as assessments page tests"
    )
    config.addinivalue_line(
        "markers", "load_test: marks tests as load tests"
    )
    config.addinivalue_line(
        "markers", "slow: marks tests as slow tests (may take longer)"
    )


def pytest_collection_modifyitems(config, items):
    """
    Modify test collection to ensure proper execution order.
    
    Order:
    1. Component tests (optional)
    2. Authentication tests
    3. Profile tests
    4. Assessment tests
    
    This ensures dependencies are met before running tests.
    """
    # Define execution order
    order_map = {
        "component": 0,  # Run first (optional)
        "authentication": 1,  # Run second
        "profile": 2,  # Run third
        "assessment": 3,  # Run last
    }
    
    # Sort tests by marker priority
    def get_test_priority(item):
        """Get priority based on markers"""
        for marker in item.iter_markers():
            marker_name = marker.name
            if marker_name in order_map:
                return order_map[marker_name]
        # Default priority for unmarked tests
        return 999
    
    # Sort items by priority
    items[:] = sorted(items, key=get_test_priority)


@pytest.fixture(scope="function")
def driver():
    """
    WebDriver fixture - creates and quits driver for each test
    
    Yields:
        WebDriver: WebDriver instance
    """
    driver = DriverManager.get_driver()
    yield driver
    DriverManager.quit_driver(driver)


@pytest.fixture(scope="function")
def logged_in_driver(driver):
    """
    Fixture that provides a logged-in driver
    
    Args:
        driver: WebDriver fixture
        
    Yields:
        WebDriver: Logged-in WebDriver instance
    """
    login_page = LoginPage(driver)
    login_page.login()
    yield driver


@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """
    Hook to capture screenshot on test failure
    
    Args:
        item: Test item
        call: Test call
    """
    outcome = yield
    rep = outcome.get_result()
    
    # Only take screenshot on failure
    if rep.when == "call" and rep.failed and SCREENSHOT_ON_FAILURE:
        # Get driver from fixture if available
        if "driver" in item.funcargs:
            driver = item.funcargs["driver"]
            try:
                # Ensure screenshot directory exists
                SCREENSHOT_DIR.mkdir(parents=True, exist_ok=True)
                
                # Create screenshot filename
                screenshot_name = f"{item.nodeid.replace('::', '_').replace('/', '_')}.png"
                screenshot_path = SCREENSHOT_DIR / screenshot_name
                
                # Take screenshot
                driver.save_screenshot(str(screenshot_path))
                print(f"\nScreenshot saved: {screenshot_path}")
                
                # Verify screenshot was created
                if screenshot_path.exists():
                    print(f"Screenshot verified: {screenshot_path.stat().st_size} bytes")
                else:
                    print(f"Warning: Screenshot file not found at {screenshot_path}")
            except Exception as e:
                print(f"Failed to take screenshot: {e}")
                import traceback
                traceback.print_exc()
