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

Tests cover:
1. Credentials management (CRUD)
2. Connection testing
3. Order listing
"""

from unittest.mock import MagicMock, patch

import pytest


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
@pytest.mark.letzshop
class TestVendorLetzshopCredentialsAPI:
    """Test vendor Letzshop credentials endpoints."""

    def test_get_status_not_configured(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test getting status when not configured."""
        response = client.get(
            "/api/v1/vendor/letzshop/status", headers=vendor_user_headers
        )

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

    def test_save_credentials(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test saving Letzshop credentials."""
        response = client.post(
            "/api/v1/vendor/letzshop/credentials",
            headers=vendor_user_headers,
            json={
                "api_key": "test-letzshop-api-key-12345",
                "auto_sync_enabled": False,
                "sync_interval_minutes": 30,
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["vendor_id"] == test_vendor_with_vendor_user.id
        assert "****" in data["api_key_masked"]
        assert data["auto_sync_enabled"] is False
        assert data["sync_interval_minutes"] == 30

    def test_get_credentials_after_save(
        self, client, db, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test getting credentials after saving."""
        # Save first
        client.post(
            "/api/v1/vendor/letzshop/credentials",
            headers=vendor_user_headers,
            json={"api_key": "my-test-key"},
        )

        # Get
        response = client.get(
            "/api/v1/vendor/letzshop/credentials", headers=vendor_user_headers
        )

        assert response.status_code == 200
        data = response.json()
        assert data["vendor_id"] == test_vendor_with_vendor_user.id
        assert "api_key_masked" in data

    def test_get_credentials_not_configured(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test getting credentials when not configured returns 404."""
        response = client.get(
            "/api/v1/vendor/letzshop/credentials", headers=vendor_user_headers
        )

        assert response.status_code == 404

    def test_update_credentials(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test partial update of credentials."""
        # Save first
        client.post(
            "/api/v1/vendor/letzshop/credentials",
            headers=vendor_user_headers,
            json={"api_key": "original-key", "auto_sync_enabled": False},
        )

        # Update
        response = client.patch(
            "/api/v1/vendor/letzshop/credentials",
            headers=vendor_user_headers,
            json={"auto_sync_enabled": True, "sync_interval_minutes": 60},
        )

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

    def test_delete_credentials(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test deleting credentials."""
        # Save first
        client.post(
            "/api/v1/vendor/letzshop/credentials",
            headers=vendor_user_headers,
            json={"api_key": "test-key"},
        )

        # Delete
        response = client.delete(
            "/api/v1/vendor/letzshop/credentials", headers=vendor_user_headers
        )

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

        # Verify deleted
        response = client.get(
            "/api/v1/vendor/letzshop/credentials", headers=vendor_user_headers
        )
        assert response.status_code == 404

    def test_delete_credentials_not_configured(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test deleting when not configured returns 404."""
        response = client.delete(
            "/api/v1/vendor/letzshop/credentials", headers=vendor_user_headers
        )

        assert response.status_code == 404


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
@pytest.mark.letzshop
class TestVendorLetzshopConnectionAPI:
    """Test vendor Letzshop connection testing endpoints."""

    def test_test_connection_not_configured(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test connection when not configured."""
        response = client.post(
            "/api/v1/vendor/letzshop/test", headers=vendor_user_headers
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is False
        assert "not configured" in data["error_details"]

    @patch("app.modules.marketplace.services.letzshop.client_service.requests.Session.post")
    def test_test_connection_success(
        self, mock_post, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test successful connection test."""
        # Mock successful response
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {"data": {"__typename": "Query"}}
        mock_post.return_value = mock_response

        # Save credentials first
        client.post(
            "/api/v1/vendor/letzshop/credentials",
            headers=vendor_user_headers,
            json={"api_key": "valid-test-key"},
        )

        # Test connection
        response = client.post(
            "/api/v1/vendor/letzshop/test", headers=vendor_user_headers
        )

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

    @patch("app.modules.marketplace.services.letzshop.client_service.requests.Session.post")
    def test_test_api_key_without_saving(
        self, mock_post, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test API key without saving it."""
        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/vendor/letzshop/test-key",
            headers=vendor_user_headers,
            json={"api_key": "test-key-to-validate"},
        )

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


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
@pytest.mark.letzshop
class TestVendorLetzshopOrdersAPI:
    """Test vendor Letzshop order endpoints."""

    def test_list_orders_empty(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test listing orders when none exist."""
        response = client.get(
            "/api/v1/vendor/letzshop/orders", headers=vendor_user_headers
        )

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

    def test_list_orders_with_filters(
        self, client, db, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test listing orders with status filter."""
        from datetime import datetime, timezone

        from app.modules.orders.models import Order

        # Create test orders using unified Order model with all required fields
        order1 = Order(
            vendor_id=test_vendor_with_vendor_user.id,
            customer_id=1,
            order_number=f"LS-{test_vendor_with_vendor_user.id}-order_1",
            channel="letzshop",
            external_order_id="order_1",
            status="pending",
            order_date=datetime.now(timezone.utc),
            customer_first_name="Test",
            customer_last_name="User",
            customer_email="test1@example.com",
            ship_first_name="Test",
            ship_last_name="User",
            ship_address_line_1="123 Test Street",
            ship_city="Luxembourg",
            ship_postal_code="1234",
            ship_country_iso="LU",
            bill_first_name="Test",
            bill_last_name="User",
            bill_address_line_1="123 Test Street",
            bill_city="Luxembourg",
            bill_postal_code="1234",
            bill_country_iso="LU",
            total_amount_cents=10000,
            currency="EUR",
        )
        order2 = Order(
            vendor_id=test_vendor_with_vendor_user.id,
            customer_id=1,
            order_number=f"LS-{test_vendor_with_vendor_user.id}-order_2",
            channel="letzshop",
            external_order_id="order_2",
            status="processing",
            order_date=datetime.now(timezone.utc),
            customer_first_name="Test",
            customer_last_name="User",
            customer_email="test2@example.com",
            ship_first_name="Test",
            ship_last_name="User",
            ship_address_line_1="456 Test Avenue",
            ship_city="Luxembourg",
            ship_postal_code="5678",
            ship_country_iso="LU",
            bill_first_name="Test",
            bill_last_name="User",
            bill_address_line_1="456 Test Avenue",
            bill_city="Luxembourg",
            bill_postal_code="5678",
            bill_country_iso="LU",
            total_amount_cents=20000,
            currency="EUR",
        )
        db.add_all([order1, order2])
        db.commit()

        # List pending only
        response = client.get(
            "/api/v1/vendor/letzshop/orders?status=pending",
            headers=vendor_user_headers,
        )

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

    def test_get_order_detail(
        self, client, db, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test getting order detail."""
        from datetime import datetime, timezone

        from app.modules.orders.models import Order

        order = Order(
            vendor_id=test_vendor_with_vendor_user.id,
            customer_id=1,
            order_number=f"LS-{test_vendor_with_vendor_user.id}-order_detail_test",
            channel="letzshop",
            external_order_id="order_detail_test",
            external_shipment_id="shipment_1",
            status="pending",
            order_date=datetime.now(timezone.utc),
            customer_first_name="Test",
            customer_last_name="User",
            customer_email="test@example.com",
            ship_first_name="Test",
            ship_last_name="User",
            ship_address_line_1="123 Test Street",
            ship_city="Luxembourg",
            ship_postal_code="1234",
            ship_country_iso="LU",
            bill_first_name="Test",
            bill_last_name="User",
            bill_address_line_1="123 Test Street",
            bill_city="Luxembourg",
            bill_postal_code="1234",
            bill_country_iso="LU",
            total_amount_cents=9999,  # €99.99
            currency="EUR",
            external_data={"test": "data"},
        )
        db.add(order)
        db.commit()

        response = client.get(
            f"/api/v1/vendor/letzshop/orders/{order.id}",
            headers=vendor_user_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["external_order_id"] == "order_detail_test"
        assert data["customer_email"] == "test@example.com"
        assert data["external_data"] == {"test": "data"}

    def test_get_order_not_found(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test getting non-existent order returns 404."""
        response = client.get(
            "/api/v1/vendor/letzshop/orders/99999",
            headers=vendor_user_headers,
        )

        assert response.status_code == 404

    def test_import_orders_not_configured(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test importing orders when not configured."""
        response = client.post(
            "/api/v1/vendor/letzshop/orders/import",
            headers=vendor_user_headers,
            json={},
        )

        assert response.status_code == 422  # Validation error

    @patch("app.modules.marketplace.services.letzshop.client_service.requests.Session.post")
    def test_import_orders_success(
        self,
        mock_post,
        client,
        db,
        vendor_user_headers,
        test_vendor_with_vendor_user,
    ):
        """Test successful order import."""
        # Mock Letzshop API response
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "data": {
                "shipments": {
                    "nodes": [
                        {
                            "id": "gid://letzshop/Shipment/123",
                            "state": "unconfirmed",
                            "order": {
                                "id": "gid://letzshop/Order/456",
                                "number": "LS-2025-001",
                                "email": "customer@example.com",
                                "total": "99.99",
                            },
                            "inventoryUnits": [
                                {"id": "unit_1", "state": "unconfirmed"},
                            ],
                        }
                    ]
                }
            }
        }
        mock_post.return_value = mock_response

        # Save credentials first
        client.post(
            "/api/v1/vendor/letzshop/credentials",
            headers=vendor_user_headers,
            json={"api_key": "test-key"},
        )

        # Import orders
        response = client.post(
            "/api/v1/vendor/letzshop/orders/import",
            headers=vendor_user_headers,
            json={"operation": "order_import"},
        )

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


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
@pytest.mark.letzshop
class TestVendorLetzshopFulfillmentAPI:
    """Test vendor Letzshop fulfillment endpoints."""

    @patch("app.modules.marketplace.services.letzshop.client_service.requests.Session.post")
    def test_confirm_order(
        self,
        mock_post,
        client,
        db,
        vendor_user_headers,
        test_vendor_with_vendor_user,
    ):
        """Test confirming an order."""
        from datetime import datetime, timezone

        from app.modules.orders.models import Order, OrderItem

        # Create test order using unified Order model with all required fields
        order = Order(
            vendor_id=test_vendor_with_vendor_user.id,
            customer_id=1,
            order_number=f"LS-{test_vendor_with_vendor_user.id}-order_confirm",
            channel="letzshop",
            external_order_id="order_confirm",
            external_shipment_id="shipment_1",
            status="pending",
            order_date=datetime.now(timezone.utc),
            customer_first_name="Test",
            customer_last_name="User",
            customer_email="test@example.com",
            ship_first_name="Test",
            ship_last_name="User",
            ship_address_line_1="123 Test Street",
            ship_city="Luxembourg",
            ship_postal_code="1234",
            ship_country_iso="LU",
            bill_first_name="Test",
            bill_last_name="User",
            bill_address_line_1="123 Test Street",
            bill_city="Luxembourg",
            bill_postal_code="1234",
            bill_country_iso="LU",
            total_amount_cents=10000,
            currency="EUR",
        )
        db.add(order)
        db.flush()

        # Add order item
        item = OrderItem(
            order_id=order.id,
            product_id=1,
            product_name="Test Product",
            quantity=1,
            unit_price_cents=10000,
            total_price_cents=10000,
            external_item_id="unit_1",
            item_state="unconfirmed",
        )
        db.add(item)
        db.commit()

        # Save credentials
        client.post(
            "/api/v1/vendor/letzshop/credentials",
            headers=vendor_user_headers,
            json={"api_key": "test-key"},
        )

        # Mock confirm response
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "data": {
                "confirmInventoryUnits": {
                    "inventoryUnits": [{"id": "unit_1", "state": "confirmed"}],
                    "errors": [],
                }
            }
        }
        mock_post.return_value = mock_response

        # Confirm order
        response = client.post(
            f"/api/v1/vendor/letzshop/orders/{order.id}/confirm",
            headers=vendor_user_headers,
        )

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

    @patch("app.modules.marketplace.services.letzshop.client_service.requests.Session.post")
    def test_set_tracking(
        self,
        mock_post,
        client,
        db,
        vendor_user_headers,
        test_vendor_with_vendor_user,
    ):
        """Test setting tracking information."""
        from datetime import datetime, timezone

        from app.modules.orders.models import Order

        order = Order(
            vendor_id=test_vendor_with_vendor_user.id,
            customer_id=1,
            order_number=f"LS-{test_vendor_with_vendor_user.id}-order_tracking",
            channel="letzshop",
            external_order_id="order_tracking",
            external_shipment_id="shipment_track",
            status="processing",  # confirmed state
            order_date=datetime.now(timezone.utc),
            customer_first_name="Test",
            customer_last_name="User",
            customer_email="test@example.com",
            ship_first_name="Test",
            ship_last_name="User",
            ship_address_line_1="123 Test Street",
            ship_city="Luxembourg",
            ship_postal_code="1234",
            ship_country_iso="LU",
            bill_first_name="Test",
            bill_last_name="User",
            bill_address_line_1="123 Test Street",
            bill_city="Luxembourg",
            bill_postal_code="1234",
            bill_country_iso="LU",
            total_amount_cents=10000,
            currency="EUR",
        )
        db.add(order)
        db.commit()

        # Save credentials
        client.post(
            "/api/v1/vendor/letzshop/credentials",
            headers=vendor_user_headers,
            json={"api_key": "test-key"},
        )

        # Mock tracking response
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "data": {
                "setShipmentTracking": {
                    "shipment": {
                        "id": "shipment_track",
                        "tracking": {"code": "1Z999AA1", "provider": "ups"},
                    },
                    "errors": [],
                }
            }
        }
        mock_post.return_value = mock_response

        # Set tracking
        response = client.post(
            f"/api/v1/vendor/letzshop/orders/{order.id}/tracking",
            headers=vendor_user_headers,
            json={
                "tracking_number": "1Z999AA1",
                "tracking_carrier": "ups",
            },
        )

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


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
@pytest.mark.letzshop
class TestVendorLetzshopExportAPI:
    """Test vendor Letzshop product export endpoints."""

    def test_export_products_empty(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test exporting products when vendor has no products."""
        response = client.get(
            "/api/v1/vendor/letzshop/export", headers=vendor_user_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_products_with_data(
        self, client, db, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test exporting products with actual data."""
        from app.modules.marketplace.models import MarketplaceProduct
        from app.modules.marketplace.models import MarketplaceProductTranslation
        from app.modules.catalog.models import Product

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

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

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

        response = client.get(
            "/api/v1/vendor/letzshop/export", headers=vendor_user_headers
        )

        assert response.status_code == 200
        content = response.text
        assert "VEXP-001" in content
        assert "Vendor Export Product" in content
        assert "49.99 EUR" in content

    def test_export_products_french_language(
        self, client, db, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test exporting products in French."""
        from app.modules.marketplace.models import MarketplaceProduct
        from app.modules.marketplace.models import MarketplaceProductTranslation
        from app.modules.catalog.models import Product

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

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

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

        response = client.get(
            "/api/v1/vendor/letzshop/export?language=fr",
            headers=vendor_user_headers,
        )

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

    def test_export_products_german_language(
        self, client, db, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test exporting products in German."""
        from app.modules.marketplace.models import MarketplaceProduct
        from app.modules.marketplace.models import MarketplaceProductTranslation
        from app.modules.catalog.models import Product

        mp = MarketplaceProduct(
            marketplace_product_id="VENDOR-DE-001",
            price="59.99",
            is_active=True,
        )
        db.add(mp)
        db.flush()

        translation_de = MarketplaceProductTranslation(
            marketplace_product_id=mp.id,
            language="de",
            title="Deutsches Exportprodukt",
        )
        db.add(translation_de)
        db.flush()

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

        response = client.get(
            "/api/v1/vendor/letzshop/export?language=de",
            headers=vendor_user_headers,
        )

        assert response.status_code == 200
        content = response.text
        assert "Deutsches Exportprodukt" in content

    def test_export_products_include_inactive(
        self, client, db, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test exporting including inactive products."""
        from app.modules.marketplace.models import MarketplaceProduct
        from app.modules.marketplace.models import MarketplaceProductTranslation
        from app.modules.catalog.models import Product

        mp = MarketplaceProduct(
            marketplace_product_id="VENDOR-INACTIVE-001",
            price="9.99",
            is_active=True,
        )
        db.add(mp)
        db.flush()

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

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

        # Without include_inactive
        response = client.get(
            "/api/v1/vendor/letzshop/export",
            headers=vendor_user_headers,
        )
        assert "VINACTIVE-001" not in response.text

        # With include_inactive
        response = client.get(
            "/api/v1/vendor/letzshop/export?include_inactive=true",
            headers=vendor_user_headers,
        )
        assert "VINACTIVE-001" in response.text

    def test_export_unauthenticated(self, client):
        """Test that unauthenticated requests are rejected."""
        response = client.get("/api/v1/vendor/letzshop/export")
        assert response.status_code == 401

    def test_export_filename_uses_vendor_code(
        self, client, vendor_user_headers, test_vendor_with_vendor_user
    ):
        """Test that export filename uses vendor code."""
        response = client.get(
            "/api/v1/vendor/letzshop/export", headers=vendor_user_headers
        )

        assert response.status_code == 200
        content_disposition = response.headers.get("content-disposition", "")
        assert "letzshop_export.csv" in content_disposition
