# services/sales/tests/integration/test_api_endpoints.py
"""
Integration tests for Sales API endpoints
"""

import pytest
import json
from decimal import Decimal
from datetime import datetime, timezone
from uuid import uuid4


@pytest.mark.asyncio
class TestSalesAPIEndpoints:
    """Test Sales API endpoints integration"""

    async def test_create_sales_record_success(self, test_client, override_get_db, sample_tenant_id):
        """Test creating a sales record via API"""
        sales_data = {
            "date": datetime.now(timezone.utc).isoformat(),
            "product_name": "Pan Integral",
            "product_category": "Panadería",
            "quantity_sold": 5,
            "unit_price": 2.50,
            "revenue": 12.50,
            "location_id": "STORE_001",
            "sales_channel": "in_store",
            "source": "manual"
        }
        
        response = test_client.post(
            f"/api/v1/sales?tenant_id={sample_tenant_id}",
            json=sales_data
        )
        
        assert response.status_code == 201
        data = response.json()
        assert data["product_name"] == "Pan Integral"
        assert data["quantity_sold"] == 5
        assert "id" in data

    async def test_create_sales_record_validation_error(self, test_client, override_get_db, sample_tenant_id):
        """Test creating a sales record with validation errors"""
        invalid_data = {
            "date": "invalid-date",
            "product_name": "",  # Empty product name
            "quantity_sold": -1,  # Invalid quantity
            "revenue": -5.00  # Invalid revenue
        }
        
        response = test_client.post(
            f"/api/v1/sales?tenant_id={sample_tenant_id}",
            json=invalid_data
        )
        
        assert response.status_code == 422  # Validation error

    async def test_get_sales_records(self, test_client, override_get_db, sample_tenant_id, populated_db):
        """Test getting sales records for tenant"""
        response = test_client.get(f"/api/v1/sales?tenant_id={sample_tenant_id}")
        
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        assert len(data) >= 0

    async def test_get_sales_records_with_filters(self, test_client, override_get_db, sample_tenant_id):
        """Test getting sales records with filters"""
        # First create a record
        sales_data = {
            "date": datetime.now(timezone.utc).isoformat(),
            "product_name": "Croissant",
            "quantity_sold": 3,
            "revenue": 7.50,
            "source": "manual"
        }
        
        create_response = test_client.post(
            f"/api/v1/sales?tenant_id={sample_tenant_id}",
            json=sales_data
        )
        assert create_response.status_code == 201
        
        # Get with product filter
        response = test_client.get(
            f"/api/v1/sales?tenant_id={sample_tenant_id}&product_name=Croissant"
        )
        
        assert response.status_code == 200
        data = response.json()
        assert len(data) >= 1
        assert all(record["product_name"] == "Croissant" for record in data)

    async def test_get_sales_record_by_id(self, test_client, override_get_db, sample_tenant_id):
        """Test getting a specific sales record"""
        # First create a record
        sales_data = {
            "date": datetime.now(timezone.utc).isoformat(),
            "product_name": "Test Product",
            "quantity_sold": 1,
            "revenue": 5.00,
            "source": "manual"
        }
        
        create_response = test_client.post(
            f"/api/v1/sales?tenant_id={sample_tenant_id}",
            json=sales_data
        )
        assert create_response.status_code == 201
        created_record = create_response.json()
        
        # Get the specific record
        response = test_client.get(
            f"/api/v1/sales/{created_record['id']}?tenant_id={sample_tenant_id}"
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["id"] == created_record["id"]
        assert data["product_name"] == "Test Product"

    async def test_get_sales_record_not_found(self, test_client, override_get_db, sample_tenant_id):
        """Test getting a non-existent sales record"""
        fake_id = str(uuid4())
        
        response = test_client.get(
            f"/api/v1/sales/{fake_id}?tenant_id={sample_tenant_id}"
        )
        
        assert response.status_code == 404

    async def test_update_sales_record(self, test_client, override_get_db, sample_tenant_id):
        """Test updating a sales record"""
        # First create a record
        sales_data = {
            "date": datetime.now(timezone.utc).isoformat(),
            "product_name": "Original Product",
            "quantity_sold": 1,
            "revenue": 5.00,
            "source": "manual"
        }
        
        create_response = test_client.post(
            f"/api/v1/sales?tenant_id={sample_tenant_id}",
            json=sales_data
        )
        assert create_response.status_code == 201
        created_record = create_response.json()
        
        # Update the record
        update_data = {
            "product_name": "Updated Product",
            "quantity_sold": 2,
            "revenue": 10.00
        }
        
        response = test_client.put(
            f"/api/v1/sales/{created_record['id']}?tenant_id={sample_tenant_id}",
            json=update_data
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["product_name"] == "Updated Product"
        assert data["quantity_sold"] == 2

    async def test_delete_sales_record(self, test_client, override_get_db, sample_tenant_id):
        """Test deleting a sales record"""
        # First create a record
        sales_data = {
            "date": datetime.now(timezone.utc).isoformat(),
            "product_name": "To Delete",
            "quantity_sold": 1,
            "revenue": 5.00,
            "source": "manual"
        }
        
        create_response = test_client.post(
            f"/api/v1/sales?tenant_id={sample_tenant_id}",
            json=sales_data
        )
        assert create_response.status_code == 201
        created_record = create_response.json()
        
        # Delete the record
        response = test_client.delete(
            f"/api/v1/sales/{created_record['id']}?tenant_id={sample_tenant_id}"
        )
        
        assert response.status_code == 200
        
        # Verify it's deleted
        get_response = test_client.get(
            f"/api/v1/sales/{created_record['id']}?tenant_id={sample_tenant_id}"
        )
        assert get_response.status_code == 404

    async def test_get_sales_analytics(self, test_client, override_get_db, sample_tenant_id):
        """Test getting sales analytics"""
        # First create some records
        for i in range(3):
            sales_data = {
                "date": datetime.now(timezone.utc).isoformat(),
                "product_name": f"Product {i}",
                "quantity_sold": i + 1,
                "revenue": (i + 1) * 5.0,
                "source": "manual"
            }
            
            response = test_client.post(
                f"/api/v1/sales?tenant_id={sample_tenant_id}",
                json=sales_data
            )
            assert response.status_code == 201
        
        # Get analytics
        response = test_client.get(
            f"/api/v1/sales/analytics?tenant_id={sample_tenant_id}"
        )
        
        assert response.status_code == 200
        data = response.json()
        assert "total_revenue" in data
        assert "total_quantity" in data
        assert "total_transactions" in data

    async def test_validate_sales_record(self, test_client, override_get_db, sample_tenant_id):
        """Test validating a sales record"""
        # First create a record
        sales_data = {
            "date": datetime.now(timezone.utc).isoformat(),
            "product_name": "To Validate",
            "quantity_sold": 1,
            "revenue": 5.00,
            "source": "manual"
        }
        
        create_response = test_client.post(
            f"/api/v1/sales?tenant_id={sample_tenant_id}",
            json=sales_data
        )
        assert create_response.status_code == 201
        created_record = create_response.json()
        
        # Validate the record
        validation_data = {
            "validation_notes": "Validated by manager"
        }
        
        response = test_client.post(
            f"/api/v1/sales/{created_record['id']}/validate?tenant_id={sample_tenant_id}",
            json=validation_data
        )
        
        assert response.status_code == 200
        data = response.json()
        assert data["is_validated"] is True
        assert data["validation_notes"] == "Validated by manager"

    async def test_get_product_sales(self, test_client, override_get_db, sample_tenant_id):
        """Test getting sales for specific product"""
        # First create records for different products
        products = ["Product A", "Product B", "Product A"]
        for product in products:
            sales_data = {
                "date": datetime.now(timezone.utc).isoformat(),
                "product_name": product,
                "quantity_sold": 1,
                "revenue": 5.00,
                "source": "manual"
            }
            
            response = test_client.post(
                f"/api/v1/sales?tenant_id={sample_tenant_id}",
                json=sales_data
            )
            assert response.status_code == 201
        
        # Get sales for Product A
        response = test_client.get(
            f"/api/v1/sales/products/Product A?tenant_id={sample_tenant_id}"
        )
        
        assert response.status_code == 200
        data = response.json()
        assert len(data) == 2  # Two Product A records
        assert all(record["product_name"] == "Product A" for record in data)

    async def test_get_product_categories(self, test_client, override_get_db, sample_tenant_id):
        """Test getting product categories"""
        # First create records with categories
        for category in ["Panadería", "Cafetería", "Panadería"]:
            sales_data = {
                "date": datetime.now(timezone.utc).isoformat(),
                "product_name": "Test Product",
                "product_category": category,
                "quantity_sold": 1,
                "revenue": 5.00,
                "source": "manual"
            }
            
            response = test_client.post(
                f"/api/v1/sales?tenant_id={sample_tenant_id}",
                json=sales_data
            )
            assert response.status_code == 201
        
        # Get categories
        response = test_client.get(
            f"/api/v1/sales/categories?tenant_id={sample_tenant_id}"
        )
        
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)

    async def test_export_sales_data_csv(self, test_client, override_get_db, sample_tenant_id):
        """Test exporting sales data as CSV"""
        # First create some records
        for i in range(3):
            sales_data = {
                "date": datetime.now(timezone.utc).isoformat(),
                "product_name": f"Export Product {i}",
                "quantity_sold": i + 1,
                "revenue": (i + 1) * 5.0,
                "source": "manual"
            }
            
            response = test_client.post(
                f"/api/v1/sales?tenant_id={sample_tenant_id}",
                json=sales_data
            )
            assert response.status_code == 201
        
        # Export as CSV
        response = test_client.get(
            f"/api/v1/sales/export?tenant_id={sample_tenant_id}&format=csv"
        )
        
        assert response.status_code == 200
        assert response.headers["content-type"].startswith("text/csv")
        assert "Export Product" in response.text

    async def test_bulk_create_sales_records(self, test_client, override_get_db, sample_tenant_id):
        """Test bulk creating sales records"""
        bulk_data = [
            {
                "date": datetime.now(timezone.utc).isoformat(),
                "product_name": f"Bulk Product {i}",
                "quantity_sold": i + 1,
                "revenue": (i + 1) * 3.0,
                "source": "bulk"
            }
            for i in range(5)
        ]
        
        response = test_client.post(
            f"/api/v1/sales/bulk?tenant_id={sample_tenant_id}",
            json=bulk_data
        )
        
        assert response.status_code == 201
        data = response.json()
        assert data["created_count"] == 5
        assert data["success"] is True

    async def test_tenant_isolation(self, test_client, override_get_db):
        """Test that tenants can only access their own data"""
        tenant_1 = uuid4()
        tenant_2 = uuid4()
        
        # Create record for tenant 1
        sales_data = {
            "date": datetime.now(timezone.utc).isoformat(),
            "product_name": "Tenant 1 Product",
            "quantity_sold": 1,
            "revenue": 5.00,
            "source": "manual"
        }
        
        create_response = test_client.post(
            f"/api/v1/sales?tenant_id={tenant_1}",
            json=sales_data
        )
        assert create_response.status_code == 201
        created_record = create_response.json()
        
        # Try to access with tenant 2
        response = test_client.get(
            f"/api/v1/sales/{created_record['id']}?tenant_id={tenant_2}"
        )
        
        assert response.status_code == 404  # Should not be found
        
        # Tenant 1 should still be able to access
        response = test_client.get(
            f"/api/v1/sales/{created_record['id']}?tenant_id={tenant_1}"
        )
        
        assert response.status_code == 200

    async def test_api_error_handling(self, test_client, override_get_db, sample_tenant_id):
        """Test API error handling"""
        # Test missing tenant_id
        sales_data = {
            "date": datetime.now(timezone.utc).isoformat(),
            "product_name": "Test Product",
            "quantity_sold": 1,
            "revenue": 5.00
        }
        
        response = test_client.post("/api/v1/sales", json=sales_data)
        assert response.status_code == 422  # Missing required parameter
        
        # Test invalid UUID
        response = test_client.get("/api/v1/sales/invalid-uuid?tenant_id={sample_tenant_id}")
        assert response.status_code == 422  # Invalid UUID format