#!/usr/bin/env python3
"""
Complete Authentication System Test Script

This script tests all three authentication contexts:
1. Admin authentication and cookie isolation
2. Store authentication and cookie isolation
3. Customer authentication and cookie isolation
4. Cross-context access prevention
5. Logging middleware

Usage:
    python test_auth_complete.py

Requirements:
    - Server running on http://localhost:8000
    - Test users configured:
      * Admin: username=admin, password=admin123
      * Store: username=store, password=store123
      * Customer: username=customer, password=customer123, store_id=1
"""

import requests

BASE_URL = "http://localhost:8000"


class Color:
    """Terminal colors for pretty output"""

    GREEN = "\033[92m"
    RED = "\033[91m"
    YELLOW = "\033[93m"
    BLUE = "\033[94m"
    MAGENTA = "\033[95m"
    CYAN = "\033[96m"
    BOLD = "\033[1m"
    END = "\033[0m"


def print_section(name: str):
    """Print section header"""
    print(f"\n{Color.BOLD}{Color.CYAN}{'═' * 60}")
    print(f"  {name}")
    print(f"{'═' * 60}{Color.END}")


def print_test(name: str):
    """Print test name"""
    print(f"\n{Color.BOLD}{Color.BLUE}🧪 Test: {name}{Color.END}")


def print_success(message: str):
    """Print success message"""
    print(f"{Color.GREEN}✅ {message}{Color.END}")


def print_error(message: str):
    """Print error message"""
    print(f"{Color.RED}❌ {message}{Color.END}")


def print_info(message: str):
    """Print info message"""
    print(f"{Color.YELLOW}ℹ️  {message}{Color.END}")


def print_warning(message: str):
    """Print warning message"""
    print(f"{Color.MAGENTA}⚠️  {message}{Color.END}")


# ============================================================================
# ADMIN AUTHENTICATION TESTS
# ============================================================================


def test_admin_login() -> dict | None:
    """Test admin login and cookie configuration"""
    print_test("Admin Login")

    try:
        response = requests.post(
            f"{BASE_URL}/api/v1/admin/auth/login",
            json={"username": "admin", "password": "admin123"},
        )

        if response.status_code == 200:
            data = response.json()
            cookies = response.cookies

            if "access_token" in data:
                print_success("Admin login successful")
                print_success(f"Received access token: {data['access_token'][:20]}...")
            else:
                print_error("No access token in response")
                return None

            if "admin_token" in cookies:
                print_success("admin_token cookie set")
                print_info("Cookie path should be /admin (verify in browser)")
            else:
                print_error("admin_token cookie NOT set")

            return {"token": data["access_token"], "user": data.get("user", {})}
        print_error(f"Login failed: {response.status_code}")
        print_error(f"Response: {response.text}")
        return None

    except Exception as e:
        print_error(f"Exception during admin login: {str(e)}")
        return None


def test_admin_cannot_access_store_api(admin_token: str):
    """Test that admin token cannot access store API"""
    print_test("Admin Token on Store API (Should Block)")

    try:
        response = requests.get(
            f"{BASE_URL}/api/v1/store/TESTSTORE/products",
            headers={"Authorization": f"Bearer {admin_token}"},
        )

        if response.status_code in [401, 403]:
            data = response.json()
            print_success("Admin correctly blocked from store API")
            print_success(f"Error code: {data.get('error_code', 'N/A')}")
            return True
        if response.status_code == 200:
            print_error("SECURITY ISSUE: Admin can access store API!")
            return False
        print_warning(f"Unexpected status code: {response.status_code}")
        return False

    except Exception as e:
        print_error(f"Exception: {str(e)}")
        return False


def test_admin_cannot_access_customer_api(admin_token: str):
    """Test that admin token cannot access customer account pages"""
    print_test("Admin Token on Customer API (Should Block)")

    try:
        response = requests.get(
            f"{BASE_URL}/shop/account/dashboard",
            headers={"Authorization": f"Bearer {admin_token}"},
        )

        # Customer pages may return HTML or JSON error
        if response.status_code in [401, 403]:
            print_success("Admin correctly blocked from customer pages")
            return True
        if response.status_code == 200:
            print_error("SECURITY ISSUE: Admin can access customer pages!")
            return False
        print_warning(f"Unexpected status code: {response.status_code}")
        return False

    except Exception as e:
        print_error(f"Exception: {str(e)}")
        return False


# ============================================================================
# STORE AUTHENTICATION TESTS
# ============================================================================


def test_store_login() -> dict | None:
    """Test store login and cookie configuration"""
    print_test("Store Login")

    try:
        response = requests.post(
            f"{BASE_URL}/api/v1/store/auth/login",
            json={"username": "store", "password": "store123"},
        )

        if response.status_code == 200:
            data = response.json()
            cookies = response.cookies

            if "access_token" in data:
                print_success("Store login successful")
                print_success(f"Received access token: {data['access_token'][:20]}...")
            else:
                print_error("No access token in response")
                return None

            if "store_token" in cookies:
                print_success("store_token cookie set")
                print_info("Cookie path should be /store (verify in browser)")
            else:
                print_error("store_token cookie NOT set")

            if "store" in data:
                print_success(f"Store: {data['store'].get('store_code', 'N/A')}")

            return {
                "token": data["access_token"],
                "user": data.get("user", {}),
                "store": data.get("store", {}),
            }
        print_error(f"Login failed: {response.status_code}")
        print_error(f"Response: {response.text}")
        return None

    except Exception as e:
        print_error(f"Exception during store login: {str(e)}")
        return None


def test_store_cannot_access_admin_api(store_token: str):
    """Test that store token cannot access admin API"""
    print_test("Store Token on Admin API (Should Block)")

    try:
        response = requests.get(
            f"{BASE_URL}/api/v1/admin/stores",
            headers={"Authorization": f"Bearer {store_token}"},
        )

        if response.status_code in [401, 403]:
            data = response.json()
            print_success("Store correctly blocked from admin API")
            print_success(f"Error code: {data.get('error_code', 'N/A')}")
            return True
        if response.status_code == 200:
            print_error("SECURITY ISSUE: Store can access admin API!")
            return False
        print_warning(f"Unexpected status code: {response.status_code}")
        return False

    except Exception as e:
        print_error(f"Exception: {str(e)}")
        return False


def test_store_cannot_access_customer_api(store_token: str):
    """Test that store token cannot access customer account pages"""
    print_test("Store Token on Customer API (Should Block)")

    try:
        response = requests.get(
            f"{BASE_URL}/shop/account/dashboard",
            headers={"Authorization": f"Bearer {store_token}"},
        )

        if response.status_code in [401, 403]:
            print_success("Store correctly blocked from customer pages")
            return True
        if response.status_code == 200:
            print_error("SECURITY ISSUE: Store can access customer pages!")
            return False
        print_warning(f"Unexpected status code: {response.status_code}")
        return False

    except Exception as e:
        print_error(f"Exception: {str(e)}")
        return False


# ============================================================================
# CUSTOMER AUTHENTICATION TESTS
# ============================================================================


def test_customer_login() -> dict | None:
    """Test customer login and cookie configuration"""
    print_test("Customer Login")

    try:
        response = requests.post(
            f"{BASE_URL}/api/v1/platform/stores/1/customers/login",
            json={"username": "customer", "password": "customer123"},
        )

        if response.status_code == 200:
            data = response.json()
            cookies = response.cookies

            if "access_token" in data:
                print_success("Customer login successful")
                print_success(f"Received access token: {data['access_token'][:20]}...")
            else:
                print_error("No access token in response")
                return None

            if "customer_token" in cookies:
                print_success("customer_token cookie set")
                print_info("Cookie path should be /shop (verify in browser)")
            else:
                print_error("customer_token cookie NOT set")

            return {"token": data["access_token"], "user": data.get("user", {})}
        print_error(f"Login failed: {response.status_code}")
        print_error(f"Response: {response.text}")
        return None

    except Exception as e:
        print_error(f"Exception during customer login: {str(e)}")
        return None


def test_customer_cannot_access_admin_api(customer_token: str):
    """Test that customer token cannot access admin API"""
    print_test("Customer Token on Admin API (Should Block)")

    try:
        response = requests.get(
            f"{BASE_URL}/api/v1/admin/stores",
            headers={"Authorization": f"Bearer {customer_token}"},
        )

        if response.status_code in [401, 403]:
            data = response.json()
            print_success("Customer correctly blocked from admin API")
            print_success(f"Error code: {data.get('error_code', 'N/A')}")
            return True
        if response.status_code == 200:
            print_error("SECURITY ISSUE: Customer can access admin API!")
            return False
        print_warning(f"Unexpected status code: {response.status_code}")
        return False

    except Exception as e:
        print_error(f"Exception: {str(e)}")
        return False


def test_customer_cannot_access_store_api(customer_token: str):
    """Test that customer token cannot access store API"""
    print_test("Customer Token on Store API (Should Block)")

    try:
        response = requests.get(
            f"{BASE_URL}/api/v1/store/TESTSTORE/products",
            headers={"Authorization": f"Bearer {customer_token}"},
        )

        if response.status_code in [401, 403]:
            data = response.json()
            print_success("Customer correctly blocked from store API")
            print_success(f"Error code: {data.get('error_code', 'N/A')}")
            return True
        if response.status_code == 200:
            print_error("SECURITY ISSUE: Customer can access store API!")
            return False
        print_warning(f"Unexpected status code: {response.status_code}")
        return False

    except Exception as e:
        print_error(f"Exception: {str(e)}")
        return False


def test_public_shop_access():
    """Test that public shop pages are accessible without authentication"""
    print_test("Public Shop Access (No Auth Required)")

    try:
        response = requests.get(f"{BASE_URL}/shop/products")  # noqa: SEC040, PERF040

        if response.status_code == 200:
            print_success("Public shop pages accessible without auth")
            return True
        print_error(f"Failed to access public shop: {response.status_code}")
        return False

    except Exception as e:
        print_error(f"Exception: {str(e)}")
        return False


def test_health_check():
    """Test health check endpoint"""
    print_test("Health Check")

    try:
        response = requests.get(f"{BASE_URL}/health")  # noqa: SEC040, PERF040

        if response.status_code == 200:
            data = response.json()
            print_success("Health check passed")
            print_info(f"Status: {data.get('status', 'N/A')}")
            return True
        print_error(f"Health check failed: {response.status_code}")
        return False

    except Exception as e:
        print_error(f"Exception: {str(e)}")
        return False


# ============================================================================
# MAIN TEST RUNNER
# ============================================================================


def main():
    """Run all tests"""
    print(f"\n{Color.BOLD}{Color.CYAN}{'═' * 60}")
    print("  🔒 COMPLETE AUTHENTICATION SYSTEM TEST SUITE")
    print(f"{'═' * 60}{Color.END}")
    print(f"Testing server at: {BASE_URL}")

    results = {"passed": 0, "failed": 0, "total": 0}

    # Health check first
    print_section("🏥 System Health")
    results["total"] += 1
    if test_health_check():
        results["passed"] += 1
    else:
        results["failed"] += 1
        print_error("Server not responding. Is it running?")
        return

    # ========================================================================
    # ADMIN TESTS
    # ========================================================================
    print_section("👤 Admin Authentication Tests")

    # Admin login
    results["total"] += 1
    admin_auth = test_admin_login()
    if admin_auth:
        results["passed"] += 1
    else:
        results["failed"] += 1
        admin_auth = None

    # Admin cross-context tests
    if admin_auth:
        results["total"] += 1
        if test_admin_cannot_access_store_api(admin_auth["token"]):
            results["passed"] += 1
        else:
            results["failed"] += 1

        results["total"] += 1
        if test_admin_cannot_access_customer_api(admin_auth["token"]):
            results["passed"] += 1
        else:
            results["failed"] += 1

    # ========================================================================
    # STORE TESTS
    # ========================================================================
    print_section("🏪 Store Authentication Tests")

    # Store login
    results["total"] += 1
    store_auth = test_store_login()
    if store_auth:
        results["passed"] += 1
    else:
        results["failed"] += 1
        store_auth = None

    # Store cross-context tests
    if store_auth:
        results["total"] += 1
        if test_store_cannot_access_admin_api(store_auth["token"]):
            results["passed"] += 1
        else:
            results["failed"] += 1

        results["total"] += 1
        if test_store_cannot_access_customer_api(store_auth["token"]):
            results["passed"] += 1
        else:
            results["failed"] += 1

    # ========================================================================
    # CUSTOMER TESTS
    # ========================================================================
    print_section("🛒 Customer Authentication Tests")

    # Public shop access
    results["total"] += 1
    if test_public_shop_access():
        results["passed"] += 1
    else:
        results["failed"] += 1

    # Customer login
    results["total"] += 1
    customer_auth = test_customer_login()
    if customer_auth:
        results["passed"] += 1
    else:
        results["failed"] += 1
        customer_auth = None

    # Customer cross-context tests
    if customer_auth:
        results["total"] += 1
        if test_customer_cannot_access_admin_api(customer_auth["token"]):
            results["passed"] += 1
        else:
            results["failed"] += 1

        results["total"] += 1
        if test_customer_cannot_access_store_api(customer_auth["token"]):
            results["passed"] += 1
        else:
            results["failed"] += 1

    # ========================================================================
    # RESULTS
    # ========================================================================
    print_section("📊 Test Results")
    print(f"\n{Color.BOLD}Total Tests: {results['total']}{Color.END}")
    print_success(f"Passed: {results['passed']}")
    if results["failed"] > 0:
        print_error(f"Failed: {results['failed']}")

    if results["failed"] == 0:
        print(f"\n{Color.GREEN}{Color.BOLD}🎉 ALL TESTS PASSED!{Color.END}")
        print(
            f"{Color.GREEN}Your authentication system is properly isolated!{Color.END}"
        )
    else:
        print(f"\n{Color.RED}{Color.BOLD}⚠️  SOME TESTS FAILED{Color.END}")
        print(f"{Color.RED}Please review the output above.{Color.END}")

    # Browser tests reminder
    print_section("🌐 Manual Browser Tests")
    print("Please also verify in browser:")
    print("\n1. Open DevTools → Application → Cookies")
    print("\n2. Log in as admin:")
    print("   - Cookie name: admin_token")
    print("   - Path: /admin")
    print("   - HttpOnly: ✓")
    print("\n3. Log in as store:")
    print("   - Cookie name: store_token")
    print("   - Path: /store")
    print("   - HttpOnly: ✓")
    print("\n4. Log in as customer:")
    print("   - Cookie name: customer_token")
    print("   - Path: /shop")
    print("   - HttpOnly: ✓")
    print("\n5. Verify cross-context isolation:")
    print("   - Admin cookie NOT sent to /store/* or /shop/*")
    print("   - Store cookie NOT sent to /admin/* or /shop/*")
    print("   - Customer cookie NOT sent to /admin/* or /store/*")
    print(f"\n{Color.CYAN}{'═' * 60}{Color.END}\n")


if __name__ == "__main__":
    main()
