# -*- coding: utf-8 -*-
"""E2E tests for global connection management features.

Tests the MesApi client, Toast notifications, and page functionality
using Playwright.

Run with: pytest tests/e2e/ --headed (to see browser)
"""

import pytest
import re
from playwright.sync_api import Page, expect


@pytest.mark.e2e
class TestPortalPage:
    """E2E tests for the Portal page."""

    def test_portal_loads_successfully(self, page: Page, app_server: str):
        """Portal page should load without errors."""
        page.goto(app_server)

        # Wait for page to load
        expect(page.locator('h1')).to_contain_text('MES 報表入口')

    def test_portal_has_all_tabs(self, page: Page, app_server: str):
        """Portal should have all navigation tabs."""
        page.goto(app_server)

        # Check released tabs exist
        expect(page.locator('.tab:has-text("WIP 即時概況")')).to_be_visible()
        expect(page.locator('.tab:has-text("設備即時概況")')).to_be_visible()
        expect(page.locator('.tab:has-text("設備歷史績效")')).to_be_visible()
        expect(page.locator('.tab:has-text("設備維修查詢")')).to_be_visible()
        expect(page.locator('.tab:has-text("批次追蹤工具")')).to_be_visible()

    def test_portal_tab_switching(self, page: Page, app_server: str):
        """Portal tabs should switch iframe content."""
        page.goto(app_server)

        # Click on a different tab
        page.locator('.tab:has-text("設備即時概況")').click()

        # Verify the tab is active
        expect(page.locator('.tab:has-text("設備即時概況")')).to_have_class(re.compile(r'active'))

    def test_portal_health_popup_clickable(self, page: Page, app_server: str):
        """Health status pill should toggle popup visibility on click."""
        page.goto(app_server)

        popup = page.locator('#healthPopup')
        expect(popup).not_to_have_class(re.compile(r'show'))

        page.locator('#healthStatus').click()
        expect(popup).to_have_class(re.compile(r'show'))


@pytest.mark.e2e
class TestToastNotifications:
    """E2E tests for Toast notification system."""

    def test_toast_container_exists(self, page: Page, app_server: str):
        """Toast container should be present in the DOM."""
        page.goto(f"{app_server}/wip-overview")

        # Toast container should exist in DOM (hidden when empty, which is expected)
        page.wait_for_selector('#mes-toast-container', state='attached', timeout=5000)

    def test_toast_info_display(self, page: Page, app_server: str):
        """Toast.info() should display info notification."""
        page.goto(f"{app_server}/wip-overview")

        # Execute Toast.info() in browser context
        page.evaluate("Toast.info('Test info message')")

        # Verify toast appears
        toast = page.locator('.mes-toast-info')
        expect(toast).to_be_visible()
        expect(toast).to_contain_text('Test info message')

    def test_toast_success_display(self, page: Page, app_server: str):
        """Toast.success() should display success notification."""
        page.goto(f"{app_server}/wip-overview")

        page.evaluate("Toast.success('Operation successful')")

        toast = page.locator('.mes-toast-success')
        expect(toast).to_be_visible()
        expect(toast).to_contain_text('Operation successful')

    def test_toast_error_display(self, page: Page, app_server: str):
        """Toast.error() should display error notification."""
        page.goto(f"{app_server}/wip-overview")

        page.evaluate("Toast.error('An error occurred')")

        toast = page.locator('.mes-toast-error')
        expect(toast).to_be_visible()
        expect(toast).to_contain_text('An error occurred')

    def test_toast_error_with_retry(self, page: Page, app_server: str):
        """Toast.error() with retry callback should show retry button."""
        page.goto(f"{app_server}/wip-overview")

        page.evaluate("Toast.error('Connection failed', { retry: () => console.log('retry clicked') })")

        # Verify retry button exists
        retry_btn = page.locator('.mes-toast-retry')
        expect(retry_btn).to_be_visible()
        expect(retry_btn).to_contain_text('重試')

    def test_toast_loading_display(self, page: Page, app_server: str):
        """Toast.loading() should display loading notification."""
        page.goto(f"{app_server}/wip-overview")

        page.evaluate("Toast.loading('Loading data...')")

        toast = page.locator('.mes-toast-loading')
        expect(toast).to_be_visible()

    def test_toast_dismiss(self, page: Page, app_server: str):
        """Toast.dismiss() should remove toast."""
        page.goto(f"{app_server}/wip-overview")

        # Create and dismiss a toast
        toast_id = page.evaluate("Toast.info('Will be dismissed')")
        page.evaluate(f"Toast.dismiss({toast_id})")

        # Wait for animation
        page.wait_for_timeout(500)

        # Toast should be gone
        expect(page.locator('.mes-toast-info')).not_to_be_visible()

    def test_toast_max_limit(self, page: Page, app_server: str):
        """Toast system should enforce max 5 toasts."""
        page.goto(f"{app_server}/wip-overview")

        # Create 7 toasts
        for i in range(7):
            page.evaluate(f"Toast.info('Toast {i}')")

        # Should only have 5 toasts visible
        toasts = page.locator('.mes-toast')
        expect(toasts).to_have_count(5)


@pytest.mark.e2e
class TestMesApiClient:
    """E2E tests for MesApi client."""

    def test_mesapi_exists_on_page(self, page: Page, app_server: str):
        """MesApi should be available in window scope."""
        page.goto(f"{app_server}/wip-overview")

        has_mesapi = page.evaluate("typeof MesApi !== 'undefined'")
        assert has_mesapi, "MesApi should be defined"

    def test_mesapi_has_get_method(self, page: Page, app_server: str):
        """MesApi should have get() method."""
        page.goto(f"{app_server}/wip-overview")

        has_get = page.evaluate("typeof MesApi.get === 'function'")
        assert has_get, "MesApi.get should be a function"

    def test_mesapi_has_post_method(self, page: Page, app_server: str):
        """MesApi should have post() method."""
        page.goto(f"{app_server}/wip-overview")

        has_post = page.evaluate("typeof MesApi.post === 'function'")
        assert has_post, "MesApi.post should be a function"

    def test_mesapi_request_logging(self, page: Page, app_server: str):
        """MesApi should log requests to console."""
        page.goto(f"{app_server}/wip-overview")

        # Capture console messages
        console_messages = []
        page.on("console", lambda msg: console_messages.append(msg.text))

        # Make a request (will fail but should log)
        page.evaluate("""
            (async () => {
                try {
                    await MesApi.get('/api/test-endpoint');
                } catch (e) {
                    // Expected to fail
                }
            })()
        """)

        page.wait_for_timeout(1000)

        # Check for MesApi log pattern
        mesapi_logs = [m for m in console_messages if '[MesApi]' in m]
        assert len(mesapi_logs) > 0, "MesApi should log requests with [MesApi] prefix"


@pytest.mark.e2e
class TestWIPOverviewPage:
    """E2E tests for WIP Overview page."""

    def test_wip_overview_loads(self, page: Page, app_server: str):
        """WIP Overview page should load."""
        page.goto(f"{app_server}/wip-overview")

        # Page should have the header
        expect(page.locator('body')).to_be_visible()

    def test_wip_overview_has_toast_system(self, page: Page, app_server: str):
        """WIP Overview should have Toast system loaded."""
        page.goto(f"{app_server}/wip-overview")

        has_toast = page.evaluate("typeof Toast !== 'undefined'")
        assert has_toast, "Toast should be defined on WIP Overview page"

    def test_wip_overview_has_mesapi(self, page: Page, app_server: str):
        """WIP Overview should have MesApi loaded."""
        page.goto(f"{app_server}/wip-overview")

        has_mesapi = page.evaluate("typeof MesApi !== 'undefined'")
        assert has_mesapi, "MesApi should be defined on WIP Overview page"


@pytest.mark.e2e
class TestWIPDetailPage:
    """E2E tests for WIP Detail page."""

    def test_wip_detail_loads(self, page: Page, app_server: str):
        """WIP Detail page should load."""
        page.goto(f"{app_server}/wip-detail")

        expect(page.locator('body')).to_be_visible()

    def test_wip_detail_has_toast_system(self, page: Page, app_server: str):
        """WIP Detail should have Toast system loaded."""
        page.goto(f"{app_server}/wip-detail")

        has_toast = page.evaluate("typeof Toast !== 'undefined'")
        assert has_toast, "Toast should be defined on WIP Detail page"

    def test_wip_detail_has_mesapi(self, page: Page, app_server: str):
        """WIP Detail should have MesApi loaded."""
        page.goto(f"{app_server}/wip-detail")

        has_mesapi = page.evaluate("typeof MesApi !== 'undefined'")
        assert has_mesapi, "MesApi should be defined on WIP Detail page"


@pytest.mark.e2e
class TestTablesPage:
    """E2E tests for Tables page."""

    def test_tables_page_loads(self, page: Page, app_server: str):
        """Tables page should load."""
        page.goto(f"{app_server}/tables")
        header = page.locator('h1')
        expect(header).to_be_visible()
        text = header.inner_text()
        assert (
            'MES 數據表查詢工具' in text
            or '頁面開發中' in text
        )

    def test_tables_has_toast_system(self, page: Page, app_server: str):
        """Tables page should have Toast system loaded."""
        page.goto(f"{app_server}/tables")

        has_toast = page.evaluate("typeof Toast !== 'undefined'")
        assert has_toast, "Toast should be defined on Tables page"

    def test_tables_has_mesapi(self, page: Page, app_server: str):
        """Tables page should have MesApi loaded."""
        page.goto(f"{app_server}/tables")

        has_mesapi = page.evaluate("typeof MesApi !== 'undefined'")
        assert has_mesapi, "MesApi should be defined on Tables page"


@pytest.mark.e2e
class TestResourcePage:
    """E2E tests for Resource Status page."""

    def test_resource_page_loads(self, page: Page, app_server: str):
        """Resource page should load."""
        page.goto(f"{app_server}/resource")

        expect(page.locator('body')).to_be_visible()

    def test_resource_has_toast_system(self, page: Page, app_server: str):
        """Resource page should have Toast system loaded."""
        page.goto(f"{app_server}/resource")

        has_toast = page.evaluate("typeof Toast !== 'undefined'")
        assert has_toast, "Toast should be defined on Resource page"

    def test_resource_has_mesapi(self, page: Page, app_server: str):
        """Resource page should have MesApi loaded."""
        page.goto(f"{app_server}/resource")

        has_mesapi = page.evaluate("typeof MesApi !== 'undefined'")
        assert has_mesapi, "MesApi should be defined on Resource page"


@pytest.mark.e2e
class TestExcelQueryPage:
    """E2E tests for Excel Query page."""

    def test_excel_query_page_loads(self, page: Page, app_server: str):
        """Excel Query page should load."""
        page.goto(f"{app_server}/excel-query")

        expect(page.locator('body')).to_be_visible()

    def test_excel_query_has_toast_system(self, page: Page, app_server: str):
        """Excel Query page should have Toast system loaded."""
        page.goto(f"{app_server}/excel-query")

        has_toast = page.evaluate("typeof Toast !== 'undefined'")
        assert has_toast, "Toast should be defined on Excel Query page"

    def test_excel_query_has_mesapi(self, page: Page, app_server: str):
        """Excel Query page should have MesApi loaded."""
        page.goto(f"{app_server}/excel-query")

        has_mesapi = page.evaluate("typeof MesApi !== 'undefined'")
        assert has_mesapi, "MesApi should be defined on Excel Query page"


@pytest.mark.e2e
class TestConsoleLogVerification:
    """E2E tests for console log verification (Phase 4.2 tasks)."""

    def test_request_has_request_id(self, page: Page, app_server: str):
        """API requests should log with req_xxx ID format."""
        page.goto(f"{app_server}/wip-overview")

        console_messages = []
        page.on("console", lambda msg: console_messages.append(msg.text))

        # Trigger an API request
        page.evaluate("""
            (async () => {
                try {
                    await MesApi.get('/api/wip/overview/summary');
                } catch (e) {}
            })()
        """)

        page.wait_for_timeout(2000)

        # Check for request ID pattern
        req_id_pattern = re.compile(r'req_\d{4}')
        has_req_id = any(req_id_pattern.search(m) for m in console_messages)
        assert has_req_id, "Console should show request ID like req_0001"

    def test_successful_request_shows_checkmark(self, page: Page, app_server: str):
        """Successful requests should show checkmark in console."""
        page.goto(f"{app_server}/wip-overview")

        console_messages = []
        page.on("console", lambda msg: console_messages.append(msg.text))

        # Make request to a working endpoint
        page.evaluate("""
            (async () => {
                try {
                    await MesApi.get('/api/wip/overview/summary');
                } catch (e) {}
            })()
        """)

        page.wait_for_timeout(3000)

        # Filter for MesApi logs
        mesapi_logs = [m for m in console_messages if '[MesApi]' in m]
        # The exact checkmark depends on implementation (✓ or similar)
        assert len(mesapi_logs) > 0, "Should have MesApi console logs"
