# -*- coding: utf-8 -*-
"""End-to-end tests for Redis cache functionality.

These tests require a running server with Redis enabled.
Run with: pytest tests/e2e/test_cache_e2e.py -v
"""

import pytest
import requests
import time


@pytest.mark.e2e
class TestHealthEndpointE2E:
    """E2E tests for /health endpoint."""

    def test_health_endpoint_accessible(self, health_url):
        """Test health endpoint is accessible."""
        response = requests.get(health_url, timeout=10)

        assert response.status_code in [200, 503]
        data = response.json()
        assert 'status' in data
        assert 'services' in data
        assert 'cache' in data

    def test_health_shows_database_status(self, health_url):
        """Test health endpoint shows database status."""
        response = requests.get(health_url, timeout=10)
        data = response.json()

        assert 'database' in data['services']
        assert data['services']['database'] in ['ok', 'error']

    def test_health_shows_redis_status(self, health_url):
        """Test health endpoint shows Redis status."""
        response = requests.get(health_url, timeout=10)
        data = response.json()

        assert 'redis' in data['services']
        assert data['services']['redis'] in ['ok', 'error', 'disabled']

    def test_health_shows_cache_info(self, health_url):
        """Test health endpoint shows cache information."""
        response = requests.get(health_url, timeout=10)
        data = response.json()

        assert 'cache' in data
        assert 'enabled' in data['cache']
        assert 'sys_date' in data['cache']
        assert 'updated_at' in data['cache']


@pytest.mark.e2e
@pytest.mark.redis
class TestCachedWipApiE2E:
    """E2E tests for cached WIP API endpoints."""

    def _unwrap(self, resp_json):
        """Unwrap API response to get data."""
        if isinstance(resp_json, dict) and 'data' in resp_json:
            return resp_json['data']
        return resp_json

    def test_wip_summary_returns_data(self, api_base_url):
        """Test WIP summary endpoint returns valid data."""
        response = requests.get(f"{api_base_url}/wip/overview/summary", timeout=30)

        assert response.status_code == 200
        data = self._unwrap(response.json())
        assert 'totalLots' in data
        assert 'totalQtyPcs' in data
        assert 'byWipStatus' in data
        assert 'dataUpdateDate' in data

    def test_wip_summary_status_breakdown(self, api_base_url):
        """Test WIP summary contains correct status breakdown."""
        response = requests.get(f"{api_base_url}/wip/overview/summary", timeout=30)
        data = self._unwrap(response.json())

        by_status = data['byWipStatus']
        assert 'run' in by_status
        assert 'queue' in by_status
        assert 'hold' in by_status
        assert 'qualityHold' in by_status
        assert 'nonQualityHold' in by_status

        # Each status should have lots and qtyPcs
        for status in ['run', 'queue', 'hold']:
            assert 'lots' in by_status[status]
            assert 'qtyPcs' in by_status[status]

    def test_wip_matrix_returns_data(self, api_base_url):
        """Test WIP matrix endpoint returns valid data."""
        response = requests.get(f"{api_base_url}/wip/overview/matrix", timeout=30)

        assert response.status_code == 200
        data = self._unwrap(response.json())
        assert 'workcenters' in data
        assert 'packages' in data
        assert 'matrix' in data
        assert 'workcenter_totals' in data
        assert 'package_totals' in data
        assert 'grand_total' in data

    def test_wip_workcenters_returns_list(self, api_base_url):
        """Test workcenters endpoint returns list."""
        response = requests.get(f"{api_base_url}/wip/meta/workcenters", timeout=30)

        assert response.status_code == 200
        data = self._unwrap(response.json())
        assert isinstance(data, list)

        if len(data) > 0:
            assert 'name' in data[0]
            assert 'lot_count' in data[0]

    def test_wip_packages_returns_list(self, api_base_url):
        """Test packages endpoint returns list."""
        response = requests.get(f"{api_base_url}/wip/meta/packages", timeout=30)

        assert response.status_code == 200
        data = self._unwrap(response.json())
        assert isinstance(data, list)

        if len(data) > 0:
            assert 'name' in data[0]
            assert 'lot_count' in data[0]

    def test_wip_hold_summary_returns_data(self, api_base_url):
        """Test hold summary endpoint returns valid data."""
        response = requests.get(f"{api_base_url}/wip/overview/hold", timeout=30)

        assert response.status_code == 200
        data = self._unwrap(response.json())
        assert 'items' in data
        assert isinstance(data['items'], list)


@pytest.mark.e2e
@pytest.mark.redis
class TestCachePerformanceE2E:
    """E2E tests for cache performance."""

    def _unwrap(self, resp_json):
        """Unwrap API response to get data."""
        if isinstance(resp_json, dict) and 'data' in resp_json:
            return resp_json['data']
        return resp_json

    def test_cached_response_is_fast(self, api_base_url):
        """Test cached responses are faster than 2 seconds."""
        # First request may load cache
        requests.get(f"{api_base_url}/wip/overview/summary", timeout=30)

        # Second request should be from cache
        start = time.time()
        response = requests.get(f"{api_base_url}/wip/overview/summary", timeout=30)
        elapsed = time.time() - start

        assert response.status_code == 200
        # Cached response should be fast (< 2 seconds)
        assert elapsed < 2.0, f"Response took {elapsed:.2f}s, expected < 2s"

    def test_multiple_endpoints_consistent(self, api_base_url):
        """Test multiple endpoints return consistent data."""
        # Get summary
        summary_resp = requests.get(f"{api_base_url}/wip/overview/summary", timeout=30)
        summary = self._unwrap(summary_resp.json())

        # Get matrix
        matrix_resp = requests.get(f"{api_base_url}/wip/overview/matrix", timeout=30)
        matrix = self._unwrap(matrix_resp.json())

        # Grand total from matrix should match total from summary (approximately)
        # There may be slight differences due to filtering
        if summary['totalLots'] > 0 and matrix['grand_total'] > 0:
            assert summary['totalQtyPcs'] > 0 or matrix['grand_total'] > 0


@pytest.mark.e2e
@pytest.mark.redis
class TestSearchEndpointsE2E:
    """E2E tests for search endpoints with cache."""

    def _unwrap(self, resp_json):
        """Unwrap API response to get data."""
        if isinstance(resp_json, dict) and 'data' in resp_json:
            data = resp_json['data']
            # Search returns {'items': [...]}
            if isinstance(data, dict) and 'items' in data:
                return data['items']
            return data
        return resp_json

    def test_search_workorders(self, api_base_url):
        """Test workorder search returns results."""
        # Use a common pattern that should exist
        response = requests.get(
            f"{api_base_url}/wip/meta/search",
            params={'field': 'workorder', 'q': 'WO', 'limit': 10},
            timeout=30
        )

        assert response.status_code == 200
        data = self._unwrap(response.json())
        assert isinstance(data, list)

    def test_search_lotids(self, api_base_url):
        """Test lot ID search returns results."""
        response = requests.get(
            f"{api_base_url}/wip/meta/search",
            params={'field': 'lotid', 'q': 'LOT', 'limit': 10},
            timeout=30
        )

        assert response.status_code == 200
        data = self._unwrap(response.json())
        assert isinstance(data, list)

    def test_search_with_short_query_returns_empty(self, api_base_url):
        """Test search with short query returns empty list."""
        response = requests.get(
            f"{api_base_url}/wip/meta/search",
            params={'field': 'workorder', 'q': 'W'},  # Too short
            timeout=30
        )

        assert response.status_code == 200
        data = self._unwrap(response.json())
        assert data == []


@pytest.mark.e2e
@pytest.mark.redis
class TestWipDetailE2E:
    """E2E tests for WIP detail endpoint with cache."""

    def _unwrap(self, resp_json):
        """Unwrap API response to get data."""
        if isinstance(resp_json, dict) and 'data' in resp_json:
            return resp_json['data']
        return resp_json

    def test_wip_detail_with_workcenter(self, api_base_url):
        """Test WIP detail endpoint for a workcenter."""
        # First get list of workcenters
        wc_resp = requests.get(f"{api_base_url}/wip/meta/workcenters", timeout=30)
        workcenters = self._unwrap(wc_resp.json())

        if len(workcenters) > 0:
            wc_name = workcenters[0]['name']
            response = requests.get(
                f"{api_base_url}/wip/detail/{wc_name}",
                timeout=30
            )

            assert response.status_code == 200
            data = self._unwrap(response.json())
            assert 'workcenter' in data
            assert 'summary' in data
            assert 'lots' in data
            assert 'pagination' in data

    def test_wip_detail_pagination(self, api_base_url):
        """Test WIP detail pagination."""
        wc_resp = requests.get(f"{api_base_url}/wip/meta/workcenters", timeout=30)
        workcenters = self._unwrap(wc_resp.json())

        if len(workcenters) > 0:
            wc_name = workcenters[0]['name']
            response = requests.get(
                f"{api_base_url}/wip/detail/{wc_name}",
                params={'page': 1, 'page_size': 10},
                timeout=30
            )

            assert response.status_code == 200
            data = self._unwrap(response.json())
            assert data['pagination']['page'] == 1
            assert data['pagination']['page_size'] == 10
