# tests/integration/api/v1/admin/test_letzshop.py
"""
Integration tests for admin Letzshop API endpoints.

Tests cover:
1. Vendor Letzshop status overview
2. Credentials management for vendors
3. Connection testing
4. Order management for vendors
"""

from unittest.mock import MagicMock, patch

import pytest


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
@pytest.mark.letzshop
class TestAdminLetzshopVendorsAPI:
    """Test admin Letzshop vendor overview endpoints."""

    def test_list_vendors_letzshop_status(self, client, admin_headers, test_vendor):
        """Test listing vendors with Letzshop status."""
        response = client.get("/api/v1/admin/letzshop/vendors", headers=admin_headers)

        assert response.status_code == 200
        data = response.json()
        assert "vendors" in data
        assert "total" in data
        # Find our test vendor
        vendor_found = False
        for v in data["vendors"]:
            if v["vendor_id"] == test_vendor.id:
                vendor_found = True
                assert v["is_configured"] is False  # Not configured yet
                break
        # Vendor may not be found if inactive, that's ok

    def test_list_vendors_configured_only(self, client, db, admin_headers, test_vendor):
        """Test listing only configured vendors."""
        from app.utils.encryption import encrypt_value
        from models.database.letzshop import VendorLetzshopCredentials

        # Configure credentials for test vendor
        credentials = VendorLetzshopCredentials(
            vendor_id=test_vendor.id,
            api_key_encrypted=encrypt_value("test-key"),
            api_endpoint="https://letzshop.lu/graphql",
        )
        db.add(credentials)
        db.commit()

        response = client.get(
            "/api/v1/admin/letzshop/vendors?configured_only=true",
            headers=admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        # All returned vendors should be configured
        for v in data["vendors"]:
            assert v["is_configured"] is True


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
@pytest.mark.letzshop
class TestAdminLetzshopCredentialsAPI:
    """Test admin Letzshop credentials management endpoints."""

    def test_get_vendor_credentials_not_configured(
        self, client, admin_headers, test_vendor
    ):
        """Test getting credentials when not configured returns 404."""
        response = client.get(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/credentials",
            headers=admin_headers,
        )

        assert response.status_code == 404

    def test_create_vendor_credentials(self, client, admin_headers, test_vendor):
        """Test creating credentials for a vendor."""
        response = client.post(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/credentials",
            headers=admin_headers,
            json={
                "api_key": "admin-set-api-key-12345",
                "auto_sync_enabled": True,
                "sync_interval_minutes": 60,
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["vendor_id"] == test_vendor.id
        assert "****" in data["api_key_masked"]
        assert data["auto_sync_enabled"] is True
        assert data["sync_interval_minutes"] == 60

    def test_get_vendor_credentials_after_create(
        self, client, db, admin_headers, test_vendor
    ):
        """Test getting credentials after creation."""
        # Create first
        client.post(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/credentials",
            headers=admin_headers,
            json={"api_key": "test-key"},
        )

        # Get
        response = client.get(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/credentials",
            headers=admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["vendor_id"] == test_vendor.id

    def test_update_vendor_credentials(self, client, admin_headers, test_vendor):
        """Test partial update of vendor credentials."""
        # Create first
        client.post(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/credentials",
            headers=admin_headers,
            json={"api_key": "original-key", "auto_sync_enabled": False},
        )

        # Update
        response = client.patch(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/credentials",
            headers=admin_headers,
            json={"auto_sync_enabled": True},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["auto_sync_enabled"] is True

    def test_delete_vendor_credentials(self, client, admin_headers, test_vendor):
        """Test deleting vendor credentials."""
        # Create first
        client.post(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/credentials",
            headers=admin_headers,
            json={"api_key": "test-key"},
        )

        # Delete
        response = client.delete(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/credentials",
            headers=admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True

    def test_vendor_not_found(self, client, admin_headers):
        """Test operations on non-existent vendor return 404."""
        response = client.get(
            "/api/v1/admin/letzshop/vendors/99999/credentials",
            headers=admin_headers,
        )

        assert response.status_code == 404


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
@pytest.mark.letzshop
class TestAdminLetzshopConnectionAPI:
    """Test admin Letzshop connection testing endpoints."""

    @patch("app.services.letzshop.client_service.requests.Session.post")
    def test_test_vendor_connection(
        self, mock_post, client, admin_headers, test_vendor
    ):
        """Test connection for a specific vendor."""
        # Mock response
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {"data": {"__typename": "Query"}}
        mock_post.return_value = mock_response

        # Create credentials
        client.post(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/credentials",
            headers=admin_headers,
            json={"api_key": "test-key"},
        )

        # Test connection
        response = client.post(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/test",
            headers=admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True

    @patch("app.services.letzshop.client_service.requests.Session.post")
    def test_test_api_key_directly(self, mock_post, client, admin_headers):
        """Test any API key without associating with vendor."""
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {"data": {"__typename": "Query"}}
        mock_post.return_value = mock_response

        response = client.post(
            "/api/v1/admin/letzshop/test",
            headers=admin_headers,
            json={"api_key": "test-api-key-to-validate"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
@pytest.mark.letzshop
class TestAdminLetzshopOrdersAPI:
    """Test admin Letzshop order management endpoints."""

    def test_list_vendor_orders_empty(self, client, admin_headers, test_vendor):
        """Test listing vendor orders when none exist."""
        response = client.get(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/orders",
            headers=admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["orders"] == []
        assert data["total"] == 0

    def test_list_vendor_orders_with_data(self, client, db, admin_headers, test_vendor):
        """Test listing vendor orders with data."""
        from models.database.order import Order

        # Create test order using unified Order model with all required fields
        order = Order(
            vendor_id=test_vendor.id,
            customer_id=1,
            order_number=f"LS-{test_vendor.id}-admin_order_1",
            channel="letzshop",
            external_order_id="admin_order_1",
            status="pending",
            customer_first_name="Admin",
            customer_last_name="Test",
            customer_email="admin-test@example.com",
            ship_first_name="Admin",
            ship_last_name="Test",
            ship_address_line_1="123 Test Street",
            ship_city="Luxembourg",
            ship_postal_code="1234",
            ship_country_iso="LU",
            bill_first_name="Admin",
            bill_last_name="Test",
            bill_address_line_1="123 Test Street",
            bill_city="Luxembourg",
            bill_postal_code="1234",
            bill_country_iso="LU",
            total_amount_cents=15000,  # €150.00
            currency="EUR",
        )
        db.add(order)
        db.commit()

        response = client.get(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/orders",
            headers=admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["total"] == 1
        assert data["orders"][0]["customer_email"] == "admin-test@example.com"

    @patch("app.services.letzshop.client_service.requests.Session.post")
    def test_trigger_vendor_sync(self, mock_post, client, admin_headers, test_vendor):
        """Test triggering sync for a vendor."""
        # Mock response
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "data": {
                "shipments": {
                    "nodes": [
                        {
                            "id": "gid://letzshop/Shipment/789",
                            "state": "unconfirmed",
                            "order": {
                                "id": "gid://letzshop/Order/111",
                                "number": "LS-ADMIN-001",
                                "email": "sync@example.com",
                                "total": "200.00",
                            },
                            "inventoryUnits": [],
                        }
                    ]
                }
            }
        }
        mock_post.return_value = mock_response

        # Create credentials
        client.post(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/credentials",
            headers=admin_headers,
            json={"api_key": "admin-sync-key"},
        )

        # Trigger sync
        response = client.post(
            f"/api/v1/admin/letzshop/vendors/{test_vendor.id}/sync",
            headers=admin_headers,
            json={"operation": "order_import"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True
        assert data["orders_imported"] >= 0


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
@pytest.mark.letzshop
class TestAdminLetzshopAccessControl:
    """Test admin access control for Letzshop endpoints."""

    def test_non_admin_cannot_access(self, client, auth_headers, test_vendor):
        """Test that non-admin users cannot access admin endpoints."""
        response = client.get(
            "/api/v1/admin/letzshop/vendors",
            headers=auth_headers,
        )

        assert response.status_code == 403

    def test_unauthenticated_cannot_access(self, client):
        """Test that unauthenticated requests are rejected."""
        response = client.get("/api/v1/admin/letzshop/vendors")

        assert response.status_code == 401


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
@pytest.mark.letzshop
class TestAdminLetzshopExportAPI:
    """Test admin Letzshop product export endpoints."""

    def test_export_vendor_products_empty(self, client, admin_headers, test_vendor):
        """Test exporting products when vendor has no products."""
        response = client.get(
            f"/api/v1/admin/vendors/{test_vendor.id}/export/letzshop",
            headers=admin_headers,
        )

        assert response.status_code == 200
        assert response.headers["content-type"] == "text/csv; charset=utf-8"
        # Should have header row at minimum
        content = response.text
        assert "id\ttitle\tdescription" in content

    def test_export_vendor_products_with_data(
        self, client, db, admin_headers, test_vendor
    ):
        """Test exporting products with actual data."""
        from models.database.marketplace_product import MarketplaceProduct
        from models.database.marketplace_product_translation import (
            MarketplaceProductTranslation,
        )
        from models.database.product import Product

        # Create marketplace product
        mp = MarketplaceProduct(
            marketplace_product_id="EXPORT-TEST-001",
            price="29.99",
            price_numeric=29.99,
            currency="EUR",
            brand="TestBrand",
            availability="in stock",
            is_active=True,
        )
        db.add(mp)
        db.flush()

        # Add translation
        translation = MarketplaceProductTranslation(
            marketplace_product_id=mp.id,
            language="en",
            title="Export Test Product",
            description="A product for testing exports",
        )
        db.add(translation)
        db.flush()

        # Create product linked to vendor
        product = Product(
            vendor_id=test_vendor.id,
            vendor_sku="EXP-001",
            marketplace_product_id=mp.id,
            is_active=True,
        )
        db.add(product)
        db.commit()

        response = client.get(
            f"/api/v1/admin/vendors/{test_vendor.id}/export/letzshop",
            headers=admin_headers,
        )

        assert response.status_code == 200
        content = response.text
        assert "EXP-001" in content
        assert "Export Test Product" in content
        assert "29.99 EUR" in content

    def test_export_vendor_products_french(
        self, client, db, admin_headers, test_vendor
    ):
        """Test exporting products in French."""
        from models.database.marketplace_product import MarketplaceProduct
        from models.database.marketplace_product_translation import (
            MarketplaceProductTranslation,
        )
        from models.database.product import Product

        mp = MarketplaceProduct(
            marketplace_product_id="EXPORT-FR-001",
            price="19.99",
            is_active=True,
        )
        db.add(mp)
        db.flush()

        # Add French translation
        translation_fr = MarketplaceProductTranslation(
            marketplace_product_id=mp.id,
            language="fr",
            title="Produit Test Export",
            description="Un produit pour tester les exportations",
        )
        db.add(translation_fr)
        db.flush()

        product = Product(
            vendor_id=test_vendor.id,
            vendor_sku="EXP-FR-001",
            marketplace_product_id=mp.id,
            is_active=True,
        )
        db.add(product)
        db.commit()

        response = client.get(
            f"/api/v1/admin/vendors/{test_vendor.id}/export/letzshop?language=fr",
            headers=admin_headers,
        )

        assert response.status_code == 200
        content = response.text
        assert "Produit Test Export" in content

    def test_export_vendor_products_include_inactive(
        self, client, db, admin_headers, test_vendor
    ):
        """Test exporting including inactive products."""
        from models.database.marketplace_product import MarketplaceProduct
        from models.database.marketplace_product_translation import (
            MarketplaceProductTranslation,
        )
        from models.database.product import Product

        # Create inactive product
        mp = MarketplaceProduct(
            marketplace_product_id="EXPORT-INACTIVE-001",
            price="5.99",
            is_active=True,
        )
        db.add(mp)
        db.flush()

        translation = MarketplaceProductTranslation(
            marketplace_product_id=mp.id,
            language="en",
            title="Inactive Product",
        )
        db.add(translation)
        db.flush()

        product = Product(
            vendor_id=test_vendor.id,
            vendor_sku="INACTIVE-001",
            marketplace_product_id=mp.id,
            is_active=False,  # Inactive
        )
        db.add(product)
        db.commit()

        # Without include_inactive
        response = client.get(
            f"/api/v1/admin/vendors/{test_vendor.id}/export/letzshop",
            headers=admin_headers,
        )
        assert "INACTIVE-001" not in response.text

        # With include_inactive
        response = client.get(
            f"/api/v1/admin/vendors/{test_vendor.id}/export/letzshop?include_inactive=true",
            headers=admin_headers,
        )
        assert "INACTIVE-001" in response.text

    def test_export_vendor_products_by_vendor_code(
        self, client, admin_headers, test_vendor
    ):
        """Test exporting products using vendor_code identifier."""
        response = client.get(
            f"/api/v1/admin/vendors/{test_vendor.vendor_code}/export/letzshop",
            headers=admin_headers,
        )

        assert response.status_code == 200
        assert response.headers["content-type"] == "text/csv; charset=utf-8"

    def test_export_vendor_not_found(self, client, admin_headers):
        """Test exporting for non-existent vendor."""
        response = client.get(
            "/api/v1/admin/vendors/999999/export/letzshop",
            headers=admin_headers,
        )

        assert response.status_code == 404
