# 01 - Visitor Identity, IP Capture & Geolocation Resolution

Welcome to **Milestone 2, Step 2.3**: Visitor Identity, IP Capture & Geolocation Resolution.

---

## 1. Logged-in vs. Anonymous Visitors

The widget automatically handles both authenticated and anonymous visitors:

| Visitor Type | Detection | Stored Fields |
|---|---|---|
| **Logged-In** | `window.CHATBOT_USER` defined on host page | `isLoggedIn: true`, `userId`, `userName`, `userEmail` |
| **Anonymous** | `window.CHATBOT_USER` undefined | `isLoggedIn: false`, `userId: null`, `userName: null`, `userEmail: null` |

---

## 2. Client IP Capture (`X-Forwarded-For` Fallback)

To display visitor locations on the Agent Dashboard, the backend captures the client IP address:

```python
def extract_client_ip(request: Request) -> str:
    # 1. Check X-Forwarded-For header (reverse proxies / load balancers)
    forwarded_for = request.headers.get("x-forwarded-for")
    if forwarded_for:
        return forwarded_for.split(",")[0].strip()
    
    # 2. Fall back to direct client host
    if request.client and request.client.host:
        return request.client.host
        
    return "Unknown"
```

---

## 3. Geolocation & Country Resolution Service

`app/utils/country_resolver.py` provides location classification via `resolve_country(ip_address)`:

- **Local / Loopback IPs (`127.0.0.1`, `::1`):** Resolves to `"Local / Demo"`.
- **Private Subnets (`10.x.x.x`, `192.168.x.x`, `172.16.x.x`):** Resolves to `"Local / Demo"`.
- **Missing / Invalid IPs:** Resolves to `"Unknown"`.
- **Public IPs:** Map to ISO country names.

---

## 4. Agent Dashboard UI Integration

The visitor card and live chat header display the visitor identity and metadata:
- **Logged-in:** `"Alice Visitor (alice@example.com)"`
- **Anonymous:** `"Anonymous Visitor"`
- **Sub-header:** `IP: 127.0.0.1 | Country: Local / Demo | Session: sess_12345`
