# tests/integration/api/v1/vendor/test_orders.py
"""Integration tests for vendor orders API endpoints."""

from datetime import UTC, datetime

import pytest

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


@pytest.fixture
def test_order(db, test_vendor_with_vendor_user, test_customer):
    """Create a test order for the vendor."""
    order = Order(
        vendor_id=test_vendor_with_vendor_user.id,
        customer_id=test_customer.id,
        order_number="ORD-TEST-001",
        status="pending",
        channel="direct",
        order_date=datetime.now(UTC),
        subtotal_cents=10000,
        tax_amount_cents=1700,
        shipping_amount_cents=500,
        total_amount_cents=12200,
        currency="EUR",
        customer_email="customer@test.com",
        customer_first_name="Test",
        customer_last_name="Customer",
        ship_first_name="Test",
        ship_last_name="Customer",
        ship_address_line_1="123 Test St",
        ship_city="Test City",
        ship_postal_code="12345",
        ship_country_iso="LU",
        bill_first_name="Test",
        bill_last_name="Customer",
        bill_address_line_1="123 Test St",
        bill_city="Test City",
        bill_postal_code="12345",
        bill_country_iso="LU",
    )
    db.add(order)
    db.commit()
    db.refresh(order)
    return order


@pytest.fixture
def test_orders(db, test_vendor_with_vendor_user, test_customer):
    """Create multiple test orders."""
    orders = []
    for i, status in enumerate(["pending", "processing", "shipped", "delivered", "cancelled"]):
        order = Order(
            vendor_id=test_vendor_with_vendor_user.id,
            customer_id=test_customer.id,
            order_number=f"ORD-TEST-{i+1:03d}",
            status=status,
            channel="direct" if i % 2 == 0 else "letzshop",
            order_date=datetime.now(UTC),
            subtotal_cents=10000 * (i + 1),
            tax_amount_cents=1700 * (i + 1),
            shipping_amount_cents=500,
            total_amount_cents=12200 * (i + 1),
            currency="EUR",
            customer_email=f"customer{i}@test.com",
            customer_first_name="Test",
            customer_last_name=f"Customer{i}",
            ship_first_name="Test",
            ship_last_name=f"Customer{i}",
            ship_address_line_1="123 Test St",
            ship_city="Test City",
            ship_postal_code="12345",
            ship_country_iso="LU",
            bill_first_name="Test",
            bill_last_name=f"Customer{i}",
            bill_address_line_1="123 Test St",
            bill_city="Test City",
            bill_postal_code="12345",
            bill_country_iso="LU",
        )
        db.add(order)
        orders.append(order)
    db.commit()
    for order in orders:
        db.refresh(order)
    return orders


@pytest.fixture
def test_order_with_items(db, test_vendor_with_vendor_user, test_customer):
    """Create a test order with order items."""
    order = Order(
        vendor_id=test_vendor_with_vendor_user.id,
        customer_id=test_customer.id,
        order_number="ORD-ITEMS-001",
        status="pending",
        channel="direct",
        order_date=datetime.now(UTC),
        subtotal_cents=20000,
        tax_amount_cents=3400,
        shipping_amount_cents=500,
        total_amount_cents=23900,
        currency="EUR",
        customer_email="customer@test.com",
        customer_first_name="Test",
        customer_last_name="Customer",
        ship_first_name="Test",
        ship_last_name="Customer",
        ship_address_line_1="123 Test St",
        ship_city="Test City",
        ship_postal_code="12345",
        ship_country_iso="LU",
        bill_first_name="Test",
        bill_last_name="Customer",
        bill_address_line_1="123 Test St",
        bill_city="Test City",
        bill_postal_code="12345",
        bill_country_iso="LU",
    )
    db.add(order)
    db.flush()

    # Add order items
    item = OrderItem(
        order_id=order.id,
        product_id=1,  # Placeholder, no product FK constraint in test
        product_sku="TEST-SKU-001",
        product_name="Test Product",
        quantity=2,
        unit_price_cents=10000,
        total_price_cents=20000,
    )
    db.add(item)
    db.commit()
    db.refresh(order)
    return order


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorOrdersListAPI:
    """Test vendor orders list endpoint."""

    def test_list_orders_success(self, client, vendor_user_headers, test_orders):
        """Test listing vendor orders."""
        response = client.get("/api/v1/vendor/orders", headers=vendor_user_headers)

        assert response.status_code == 200
        data = response.json()
        assert "orders" in data
        assert "total" in data
        assert data["total"] == 5
        assert len(data["orders"]) == 5

    def test_list_orders_with_pagination(self, client, vendor_user_headers, test_orders):
        """Test orders list with pagination."""
        response = client.get(
            "/api/v1/vendor/orders?skip=2&limit=2", headers=vendor_user_headers
        )

        assert response.status_code == 200
        data = response.json()
        assert len(data["orders"]) == 2
        assert data["skip"] == 2
        assert data["limit"] == 2

    def test_list_orders_filter_by_status(self, client, vendor_user_headers, test_orders):
        """Test filtering orders by status."""
        response = client.get(
            "/api/v1/vendor/orders?status=pending", headers=vendor_user_headers
        )

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

    def test_list_orders_filter_by_customer(
        self, client, vendor_user_headers, test_orders, test_customer
    ):
        """Test filtering orders by customer ID."""
        response = client.get(
            f"/api/v1/vendor/orders?customer_id={test_customer.id}",
            headers=vendor_user_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["total"] == 5  # All orders belong to test_customer

    def test_list_orders_empty(self, client, vendor_user_headers):
        """Test empty orders list."""
        response = client.get("/api/v1/vendor/orders", headers=vendor_user_headers)

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

    def test_list_orders_unauthorized(self, client):
        """Test orders list without authentication."""
        response = client.get("/api/v1/vendor/orders")

        assert response.status_code == 401


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorOrderDetailAPI:
    """Test vendor order detail endpoint."""

    def test_get_order_detail(self, client, vendor_user_headers, test_order_with_items):
        """Test getting order details."""
        response = client.get(
            f"/api/v1/vendor/orders/{test_order_with_items.id}",
            headers=vendor_user_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["order_number"] == "ORD-ITEMS-001"
        assert data["status"] == "pending"
        assert "items" in data
        assert len(data["items"]) == 1
        assert data["items"][0]["quantity"] == 2

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

        assert response.status_code == 404

    def test_get_order_unauthorized(self, client, test_order):
        """Test getting order without authentication."""
        response = client.get(f"/api/v1/vendor/orders/{test_order.id}")

        assert response.status_code == 401


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorOrderStatusUpdateAPI:
    """Test vendor order status update endpoint."""

    def test_update_order_status_to_processing(
        self, client, vendor_user_headers, test_order
    ):
        """Test updating order status to processing."""
        response = client.put(
            f"/api/v1/vendor/orders/{test_order.id}/status",
            json={"status": "processing"},
            headers=vendor_user_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "processing"

    def test_update_order_status_to_shipped(
        self, client, vendor_user_headers, test_order
    ):
        """Test updating order status to shipped with tracking."""
        response = client.put(
            f"/api/v1/vendor/orders/{test_order.id}/status",
            json={
                "status": "shipped",
                "tracking_number": "TRACK123456",
                "tracking_url": "https://tracking.example.com/TRACK123456",
            },
            headers=vendor_user_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "shipped"

    def test_update_order_status_to_cancelled(
        self, client, vendor_user_headers, test_order
    ):
        """Test updating order status to cancelled."""
        response = client.put(
            f"/api/v1/vendor/orders/{test_order.id}/status",
            json={"status": "cancelled"},
            headers=vendor_user_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "cancelled"

    def test_update_order_not_found(self, client, vendor_user_headers):
        """Test updating non-existent order."""
        response = client.put(
            "/api/v1/vendor/orders/99999/status",
            json={"status": "processing"},
            headers=vendor_user_headers,
        )

        assert response.status_code == 404

    def test_update_order_unauthorized(self, client, test_order):
        """Test updating order without authentication."""
        response = client.put(
            f"/api/v1/vendor/orders/{test_order.id}/status",
            json={"status": "processing"},
        )

        assert response.status_code == 401
