"""
Phase 1 Customer Portal Backend Tests
Tests for: User Auth, User Overview, Vehicles CRUD, VIN Decode, 
Invoices, Quotes, Orders, Shipments, Stripe Checkout
"""
import pytest
import requests
import os
import uuid

BASE_URL = os.environ.get('REACT_APP_BACKEND_URL', '').rstrip('/')

# Test credentials
TEST_USER_EMAIL = "test@test.com"
TEST_USER_PASSWORD = "test123"

class TestUserAuth:
    """User authentication tests"""
    
    def test_user_login_success(self):
        """Test user login with valid credentials"""
        response = requests.post(f"{BASE_URL}/api/user/login", json={
            "email": TEST_USER_EMAIL,
            "password": TEST_USER_PASSWORD
        })
        assert response.status_code == 200, f"Expected 200, got {response.status_code}: {response.text}"
        data = response.json()
        assert "token" in data, "Response should contain token"
        assert "user" in data, "Response should contain user object"
        assert data["user"]["email"] == TEST_USER_EMAIL
        
    def test_user_login_invalid_credentials(self):
        """Test user login with invalid credentials"""
        response = requests.post(f"{BASE_URL}/api/user/login", json={
            "email": "wrong@test.com",
            "password": "wrongpassword"
        })
        assert response.status_code == 401
        

class TestUserOverview:
    """User overview/dashboard stats tests"""
    
    @pytest.fixture(autouse=True)
    def setup_auth(self):
        response = requests.post(f"{BASE_URL}/api/user/login", json={
            "email": TEST_USER_EMAIL,
            "password": TEST_USER_PASSWORD
        })
        if response.status_code == 200:
            self.token = response.json()["token"]
            self.headers = {"Authorization": f"Bearer {self.token}"}
        else:
            pytest.skip("User login failed")
            
    def test_user_overview_returns_stats(self):
        """Test GET /api/user/overview returns all expected stats"""
        response = requests.get(f"{BASE_URL}/api/user/overview", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        
        # Verify all required fields
        assert "active_orders" in data
        assert "pending_quotes" in data
        assert "unpaid_invoices_count" in data
        assert "vehicles_count" in data
        assert "recent_requests" in data
        assert "recent_shipments" in data
        assert "unpaid_total" in data
        
        # Verify data types
        assert isinstance(data["active_orders"], int)
        assert isinstance(data["pending_quotes"], int)
        assert isinstance(data["unpaid_invoices_count"], int)
        assert isinstance(data["vehicles_count"], int)
        assert isinstance(data["recent_requests"], list)
        assert isinstance(data["recent_shipments"], list)


class TestVehiclesCRUD:
    """Vehicle CRUD operations tests"""
    
    @pytest.fixture(autouse=True)
    def setup_auth(self):
        response = requests.post(f"{BASE_URL}/api/user/login", json={
            "email": TEST_USER_EMAIL,
            "password": TEST_USER_PASSWORD
        })
        if response.status_code == 200:
            self.token = response.json()["token"]
            self.headers = {"Authorization": f"Bearer {self.token}"}
        else:
            pytest.skip("User login failed")
    
    def test_create_vehicle(self):
        """Test POST /api/user/vehicles creates a vehicle"""
        vehicle_data = {
            "year": "2022",
            "make": "Ford",
            "model": "Mustang",
            "vin": "",
            "engine": "5.0L V8",
            "trim": "GT",
            "nickname": f"TEST_Mustang_{uuid.uuid4().hex[:6]}"
        }
        response = requests.post(f"{BASE_URL}/api/user/vehicles", 
                                 json=vehicle_data, headers=self.headers)
        assert response.status_code == 200, f"Expected 200, got {response.status_code}: {response.text}"
        data = response.json()
        
        assert data["year"] == vehicle_data["year"]
        assert data["make"] == vehicle_data["make"]
        assert data["model"] == vehicle_data["model"]
        assert "id" in data
        
        # Cleanup - delete the test vehicle
        requests.delete(f"{BASE_URL}/api/user/vehicles/{data['id']}", headers=self.headers)
        
    def test_list_vehicles(self):
        """Test GET /api/user/vehicles lists user's vehicles"""
        response = requests.get(f"{BASE_URL}/api/user/vehicles", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        
    def test_update_vehicle(self):
        """Test PATCH /api/user/vehicles/{id} updates a vehicle"""
        # First create a vehicle
        create_response = requests.post(f"{BASE_URL}/api/user/vehicles", 
                                        json={"year": "2021", "make": "Chevrolet", "model": "Camaro",
                                              "nickname": f"TEST_Camaro_{uuid.uuid4().hex[:6]}"}, 
                                        headers=self.headers)
        assert create_response.status_code == 200
        vehicle_id = create_response.json()["id"]
        
        # Update the vehicle
        update_response = requests.patch(f"{BASE_URL}/api/user/vehicles/{vehicle_id}",
                                         json={"nickname": "TEST_Updated_Nickname"},
                                         headers=self.headers)
        assert update_response.status_code == 200
        assert update_response.json()["nickname"] == "TEST_Updated_Nickname"
        
        # Cleanup
        requests.delete(f"{BASE_URL}/api/user/vehicles/{vehicle_id}", headers=self.headers)
        
    def test_delete_vehicle(self):
        """Test DELETE /api/user/vehicles/{id} removes a vehicle"""
        # Create a vehicle
        create_response = requests.post(f"{BASE_URL}/api/user/vehicles", 
                                        json={"year": "2020", "make": "Dodge", "model": "Challenger",
                                              "nickname": f"TEST_Delete_{uuid.uuid4().hex[:6]}"}, 
                                        headers=self.headers)
        vehicle_id = create_response.json()["id"]
        
        # Delete it
        delete_response = requests.delete(f"{BASE_URL}/api/user/vehicles/{vehicle_id}",
                                          headers=self.headers)
        assert delete_response.status_code == 200
        assert "message" in delete_response.json()
        
        # Verify it's deleted
        list_response = requests.get(f"{BASE_URL}/api/user/vehicles", headers=self.headers)
        vehicle_ids = [v["id"] for v in list_response.json()]
        assert vehicle_id not in vehicle_ids


class TestVINDecode:
    """VIN Decode API tests"""
    
    def test_vin_decode_valid_vin(self):
        """Test GET /api/vin-decode/{vin} decodes a valid VIN"""
        # Using a sample Honda VIN
        response = requests.get(f"{BASE_URL}/api/vin-decode/1HGBH41JXMN109186")
        assert response.status_code == 200
        data = response.json()
        
        assert "year" in data
        assert "make" in data
        assert "model" in data
        assert data["make"].upper() == "HONDA"
        
    def test_vin_decode_invalid_length(self):
        """Test VIN decode fails with invalid VIN length"""
        response = requests.get(f"{BASE_URL}/api/vin-decode/ABC123")
        assert response.status_code == 400


class TestUserInvoices:
    """User invoices tests"""
    
    @pytest.fixture(autouse=True)
    def setup_auth(self):
        response = requests.post(f"{BASE_URL}/api/user/login", json={
            "email": TEST_USER_EMAIL,
            "password": TEST_USER_PASSWORD
        })
        if response.status_code == 200:
            self.token = response.json()["token"]
            self.headers = {"Authorization": f"Bearer {self.token}"}
        else:
            pytest.skip("User login failed")
            
    def test_list_user_invoices(self):
        """Test GET /api/user/invoices returns invoices"""
        response = requests.get(f"{BASE_URL}/api/user/invoices", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        
        # If invoices exist, verify structure
        if len(data) > 0:
            invoice = data[0]
            assert "id" in invoice
            assert "status" in invoice
            assert "amount" in invoice
            assert invoice["status"] in ["paid", "unpaid"]


class TestUserQuotes:
    """User quotes tests"""
    
    @pytest.fixture(autouse=True)
    def setup_auth(self):
        response = requests.post(f"{BASE_URL}/api/user/login", json={
            "email": TEST_USER_EMAIL,
            "password": TEST_USER_PASSWORD
        })
        if response.status_code == 200:
            self.token = response.json()["token"]
            self.headers = {"Authorization": f"Bearer {self.token}"}
        else:
            pytest.skip("User login failed")
            
    def test_list_user_quotes(self):
        """Test GET /api/user/quotes returns quotes"""
        response = requests.get(f"{BASE_URL}/api/user/quotes", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)


class TestUserOrders:
    """User orders tests"""
    
    @pytest.fixture(autouse=True)
    def setup_auth(self):
        response = requests.post(f"{BASE_URL}/api/user/login", json={
            "email": TEST_USER_EMAIL,
            "password": TEST_USER_PASSWORD
        })
        if response.status_code == 200:
            self.token = response.json()["token"]
            self.headers = {"Authorization": f"Bearer {self.token}"}
        else:
            pytest.skip("User login failed")
            
    def test_list_user_orders(self):
        """Test GET /api/user/orders returns orders"""
        response = requests.get(f"{BASE_URL}/api/user/orders", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)


class TestUserShipments:
    """User shipments tests"""
    
    @pytest.fixture(autouse=True)
    def setup_auth(self):
        response = requests.post(f"{BASE_URL}/api/user/login", json={
            "email": TEST_USER_EMAIL,
            "password": TEST_USER_PASSWORD
        })
        if response.status_code == 200:
            self.token = response.json()["token"]
            self.headers = {"Authorization": f"Bearer {self.token}"}
        else:
            pytest.skip("User login failed")
            
    def test_list_user_shipments(self):
        """Test GET /api/user/shipments returns shipments"""
        response = requests.get(f"{BASE_URL}/api/user/shipments", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        
        # If shipments exist, verify structure
        if len(data) > 0:
            shipment = data[0]
            assert "carrier" in shipment
            assert "tracking_number" in shipment
            assert "status" in shipment


class TestStripePayments:
    """Stripe payment integration tests"""
    
    @pytest.fixture(autouse=True)
    def setup_auth(self):
        response = requests.post(f"{BASE_URL}/api/user/login", json={
            "email": TEST_USER_EMAIL,
            "password": TEST_USER_PASSWORD
        })
        if response.status_code == 200:
            self.token = response.json()["token"]
            self.headers = {"Authorization": f"Bearer {self.token}"}
        else:
            pytest.skip("User login failed")
            
    def test_create_checkout_session(self):
        """Test POST /api/payments/checkout creates Stripe session"""
        # First get an unpaid invoice
        invoices_response = requests.get(f"{BASE_URL}/api/user/invoices", headers=self.headers)
        invoices = invoices_response.json()
        unpaid_invoice = next((inv for inv in invoices if inv["status"] == "unpaid"), None)
        
        if not unpaid_invoice:
            pytest.skip("No unpaid invoice available for testing")
            
        response = requests.post(f"{BASE_URL}/api/payments/checkout", 
                                 json={
                                     "invoice_id": unpaid_invoice["id"],
                                     "origin_url": "https://wholesale-auto-parts.preview.emergentagent.com"
                                 },
                                 headers=self.headers)
        assert response.status_code == 200, f"Expected 200, got {response.status_code}: {response.text}"
        data = response.json()
        
        assert "url" in data, "Response should contain checkout URL"
        assert "session_id" in data, "Response should contain session_id"
        assert "checkout.stripe.com" in data["url"]


class TestUserPartRequests:
    """User part requests tests"""
    
    @pytest.fixture(autouse=True)
    def setup_auth(self):
        response = requests.post(f"{BASE_URL}/api/user/login", json={
            "email": TEST_USER_EMAIL,
            "password": TEST_USER_PASSWORD
        })
        if response.status_code == 200:
            self.token = response.json()["token"]
            self.headers = {"Authorization": f"Bearer {self.token}"}
        else:
            pytest.skip("User login failed")
            
    def test_list_user_part_requests(self):
        """Test GET /api/user/part-requests returns user's requests"""
        response = requests.get(f"{BASE_URL}/api/user/part-requests", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
