"""
Phase 2 Admin CRM Dashboard Testing
Tests for:
- Admin login and authentication
- Dashboard stats with new fields (total_customers, unpaid_invoices, paid_invoices, total_collected)
- Admin customers list endpoint
- Admin customer profile endpoint
- Admin pipeline endpoint
- Admin pipeline stage move endpoint
"""

import pytest
import requests
import os

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

class TestAdminAuth:
    """Admin authentication tests"""
    
    def test_admin_login_success(self):
        """POST /api/auth/login with valid credentials returns token"""
        response = requests.post(f"{BASE_URL}/api/auth/login", json={
            "username": "admin",
            "password": "queencity2024"
        })
        assert response.status_code == 200
        data = response.json()
        assert "token" in data
        assert data["username"] == "admin"
        assert data["role"] == "admin"
        print(f"PASS: Admin login returns token, username={data['username']}, role={data['role']}")
    
    def test_admin_login_invalid_credentials(self):
        """POST /api/auth/login with invalid credentials returns 401"""
        response = requests.post(f"{BASE_URL}/api/auth/login", json={
            "username": "admin",
            "password": "wrongpassword"
        })
        assert response.status_code == 401
        print("PASS: Invalid credentials return 401")


class TestDashboardStats:
    """Dashboard stats endpoint tests"""
    
    @pytest.fixture(autouse=True)
    def setup(self):
        """Get admin token before each test"""
        response = requests.post(f"{BASE_URL}/api/auth/login", json={
            "username": "admin",
            "password": "queencity2024"
        })
        assert response.status_code == 200
        self.token = response.json()["token"]
        self.headers = {"Authorization": f"Bearer {self.token}"}
    
    def test_dashboard_stats_returns_all_fields(self):
        """GET /api/dashboard/stats returns all required fields including new Phase 2 fields"""
        response = requests.get(f"{BASE_URL}/api/dashboard/stats", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        
        # Check original fields
        assert "total_requests" in data
        assert "new_requests" in data
        assert "in_progress" in data
        assert "completed" in data
        assert "total_revenue" in data
        assert "total_profit" in data
        assert "total_contacts" in data
        assert "total_orders" in data
        assert "total_quotes" in data
        
        # Check new Phase 2 fields
        assert "total_customers" in data
        assert "unpaid_invoices" in data
        assert "paid_invoices" in data
        assert "total_collected" in data
        
        print(f"PASS: Dashboard stats returned all fields")
        print(f"  - total_requests: {data['total_requests']}")
        print(f"  - total_customers: {data['total_customers']}")
        print(f"  - total_orders: {data['total_orders']}")
        print(f"  - total_collected: ${data['total_collected']}")
        print(f"  - unpaid_invoices: {data['unpaid_invoices']}")
        print(f"  - paid_invoices: {data['paid_invoices']}")
        print(f"  - total_quotes: {data['total_quotes']}")
        print(f"  - total_profit: ${data['total_profit']}")
    
    def test_dashboard_stats_requires_auth(self):
        """GET /api/dashboard/stats without token returns 401/403"""
        response = requests.get(f"{BASE_URL}/api/dashboard/stats")
        assert response.status_code in [401, 403]
        print("PASS: Dashboard stats requires auth")


class TestAdminCustomers:
    """Admin customers management tests"""
    
    @pytest.fixture(autouse=True)
    def setup(self):
        """Get admin token before each test"""
        response = requests.post(f"{BASE_URL}/api/auth/login", json={
            "username": "admin",
            "password": "queencity2024"
        })
        assert response.status_code == 200
        self.token = response.json()["token"]
        self.headers = {"Authorization": f"Bearer {self.token}"}
    
    def test_list_customers_returns_enriched_data(self):
        """GET /api/admin/customers returns list with enriched fields"""
        response = requests.get(f"{BASE_URL}/api/admin/customers", headers=self.headers)
        assert response.status_code == 200
        customers = response.json()
        
        assert isinstance(customers, list)
        print(f"PASS: Found {len(customers)} customers")
        
        if len(customers) > 0:
            c = customers[0]
            # Check enriched fields
            assert "name" in c
            assert "email" in c
            assert "requests_count" in c
            assert "orders_count" in c
            assert "invoices_total" in c
            assert "unpaid_amount" in c
            
            print(f"  - First customer: {c['name']}, email={c['email']}")
            print(f"    requests: {c['requests_count']}, orders: {c['orders_count']}")
            print(f"    invoices_total: ${c['invoices_total']}, unpaid: ${c['unpaid_amount']}")
    
    def test_list_customers_requires_auth(self):
        """GET /api/admin/customers without token returns 401/403"""
        response = requests.get(f"{BASE_URL}/api/admin/customers")
        assert response.status_code in [401, 403]
        print("PASS: Customers list requires auth")
    
    def test_get_customer_profile(self):
        """GET /api/admin/customers/{id} returns full profile with related data"""
        # First get list to find a customer id
        response = requests.get(f"{BASE_URL}/api/admin/customers", headers=self.headers)
        assert response.status_code == 200
        customers = response.json()
        
        if len(customers) == 0:
            pytest.skip("No customers to test profile endpoint")
        
        customer_id = customers[0]["id"]
        response = requests.get(f"{BASE_URL}/api/admin/customers/{customer_id}", headers=self.headers)
        assert response.status_code == 200
        profile = response.json()
        
        # Check profile has all required fields
        assert "id" in profile
        assert "name" in profile
        assert "email" in profile
        assert "vehicles" in profile
        assert "requests" in profile
        assert "quotes" in profile
        assert "orders" in profile
        assert "invoices" in profile
        assert "payments" in profile
        
        assert isinstance(profile["vehicles"], list)
        assert isinstance(profile["requests"], list)
        assert isinstance(profile["orders"], list)
        assert isinstance(profile["invoices"], list)
        assert isinstance(profile["payments"], list)
        
        print(f"PASS: Customer profile returned for {profile['name']}")
        print(f"  - vehicles: {len(profile['vehicles'])}")
        print(f"  - requests: {len(profile['requests'])}")
        print(f"  - orders: {len(profile['orders'])}")
        print(f"  - invoices: {len(profile['invoices'])}")
        print(f"  - payments: {len(profile['payments'])}")
    
    def test_get_customer_profile_not_found(self):
        """GET /api/admin/customers/{invalid_id} returns 404"""
        response = requests.get(f"{BASE_URL}/api/admin/customers/invalid-customer-id", headers=self.headers)
        assert response.status_code == 404
        print("PASS: Invalid customer id returns 404")


class TestAdminPipeline:
    """Admin pipeline management tests"""
    
    @pytest.fixture(autouse=True)
    def setup(self):
        """Get admin token before each test"""
        response = requests.post(f"{BASE_URL}/api/auth/login", json={
            "username": "admin",
            "password": "queencity2024"
        })
        assert response.status_code == 200
        self.token = response.json()["token"]
        self.headers = {"Authorization": f"Bearer {self.token}"}
    
    def test_get_pipeline_returns_all_stages(self):
        """GET /api/admin/pipeline returns all 9 pipeline stages"""
        response = requests.get(f"{BASE_URL}/api/admin/pipeline", headers=self.headers)
        assert response.status_code == 200
        pipeline = response.json()
        
        expected_stages = ["new_lead", "vin_review", "sourcing", "quote_sent", 
                          "invoice_sent", "paid", "ordered", "shipped", "delivered"]
        
        for stage in expected_stages:
            assert stage in pipeline, f"Missing stage: {stage}"
            assert isinstance(pipeline[stage], list)
        
        print("PASS: Pipeline returned all 9 stages:")
        for stage in expected_stages:
            count = len(pipeline[stage])
            print(f"  - {stage}: {count} items")
    
    def test_get_pipeline_requires_auth(self):
        """GET /api/admin/pipeline without token returns 401/403"""
        response = requests.get(f"{BASE_URL}/api/admin/pipeline")
        assert response.status_code in [401, 403]
        print("PASS: Pipeline requires auth")
    
    def test_move_pipeline_stage(self):
        """PATCH /api/admin/pipeline/{request_id} moves request to new stage"""
        # First get pipeline to find a request to move
        response = requests.get(f"{BASE_URL}/api/admin/pipeline", headers=self.headers)
        assert response.status_code == 200
        pipeline = response.json()
        
        # Find a request in any stage
        request_id = None
        original_stage = None
        for stage, items in pipeline.items():
            if len(items) > 0:
                request_id = items[0]["id"]
                original_stage = stage
                break
        
        if not request_id:
            pytest.skip("No requests in pipeline to test move")
        
        # Move to a different stage (vin_review if not already there, else sourcing)
        new_stage = "vin_review" if original_stage != "vin_review" else "sourcing"
        
        response = requests.patch(
            f"{BASE_URL}/api/admin/pipeline/{request_id}",
            json={"pipeline_stage": new_stage},
            headers=self.headers
        )
        assert response.status_code == 200
        data = response.json()
        assert data.get("pipeline_stage") == new_stage
        
        print(f"PASS: Moved request {request_id} from {original_stage} to {new_stage}")
        
        # Move back to original stage
        requests.patch(
            f"{BASE_URL}/api/admin/pipeline/{request_id}",
            json={"pipeline_stage": original_stage},
            headers=self.headers
        )
    
    def test_move_pipeline_requires_stage(self):
        """PATCH /api/admin/pipeline/{id} without pipeline_stage returns 400"""
        # Get any request id
        response = requests.get(f"{BASE_URL}/api/admin/pipeline", headers=self.headers)
        pipeline = response.json()
        
        request_id = None
        for stage, items in pipeline.items():
            if len(items) > 0:
                request_id = items[0]["id"]
                break
        
        if not request_id:
            pytest.skip("No requests to test")
        
        response = requests.patch(
            f"{BASE_URL}/api/admin/pipeline/{request_id}",
            json={},
            headers=self.headers
        )
        assert response.status_code == 400
        print("PASS: Pipeline move without stage returns 400")
    
    def test_move_pipeline_not_found(self):
        """PATCH /api/admin/pipeline/{invalid_id} returns 404"""
        response = requests.patch(
            f"{BASE_URL}/api/admin/pipeline/invalid-request-id",
            json={"pipeline_stage": "sourcing"},
            headers=self.headers
        )
        assert response.status_code == 404
        print("PASS: Invalid request id returns 404")


class TestExistingAdminEndpoints:
    """Verify existing admin endpoints still work"""
    
    @pytest.fixture(autouse=True)
    def setup(self):
        """Get admin token before each test"""
        response = requests.post(f"{BASE_URL}/api/auth/login", json={
            "username": "admin",
            "password": "queencity2024"
        })
        assert response.status_code == 200
        self.token = response.json()["token"]
        self.headers = {"Authorization": f"Bearer {self.token}"}
    
    def test_part_requests_list(self):
        """GET /api/part-requests returns requests list"""
        response = requests.get(f"{BASE_URL}/api/part-requests", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        print(f"PASS: Part requests returned {len(data)} items")
    
    def test_orders_list(self):
        """GET /api/orders returns orders list"""
        response = requests.get(f"{BASE_URL}/api/orders", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        print(f"PASS: Orders returned {len(data)} items")
    
    def test_invoices_list(self):
        """GET /api/invoices returns invoices list"""
        response = requests.get(f"{BASE_URL}/api/invoices", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        print(f"PASS: Invoices returned {len(data)} items")
    
    def test_shipments_list(self):
        """GET /api/shipments returns shipments list"""
        response = requests.get(f"{BASE_URL}/api/shipments", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        print(f"PASS: Shipments returned {len(data)} items")
    
    def test_contacts_list(self):
        """GET /api/contacts returns contacts list"""
        response = requests.get(f"{BASE_URL}/api/contacts", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        print(f"PASS: Contacts returned {len(data)} items")
    
    def test_quotes_list(self):
        """GET /api/quotes returns quotes list"""
        response = requests.get(f"{BASE_URL}/api/quotes", headers=self.headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)
        print(f"PASS: Quotes returned {len(data)} items")


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