Response:
Here is a production-grade implementation for the Widget Analytics Tracking system. This solution uses **FastAPI**, **SQLAlchemy 2.0**, **Pydantic v2**, and **asyncio** for high-performance real-time analytics.

## Project Structure

```
widget/
├── api/
│   ├── __init__.py
│   ├── analytics.py          # Main API routes
│   ├── dependencies.py       # Auth & DB dependencies
│   └── schemas.py            # Pydantic models
├── services/
│   ├── __init__.py
│   ├── tracker.py            # Event tracking service
│   ├── aggregation.py          # Daily rollup service
│   └── sse_manager.py          # Real-time streaming manager
├── models/
│   ├── __init__.py
│   └── database.py           # SQLAlchemy models
└── tests/
    ├── test_black_box.py
    └── test_white_box.py
```

## 1. Database Models (`models/database.py`)

```python
"""
Database models for widget analytics.
Uses SQLAlchemy 2.0 type-mapped columns with proper indexing.
"""
from datetime import datetime, date
from typing import Optional
from uuid import uuid4

from sqlalchemy import (
    String, DateTime, Date, Integer, Float,
    Index, ForeignKey, UniqueConstraint, JSON
)
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy.sql import func

class Base(DeclarativeBase):
    """Base class for all models."""
    pass

class WidgetEvent(Base):
    """
    Raw event log for widget interactions.
    High-volume table; consider partitioning by date in production.
    """
    __tablename__ = "widget_events"

    id: Mapped[str] = mapped_column(
        String(36), primary_key=True, default=lambda: str(uuid4())
    )
    widget_id: Mapped[str] = mapped_column(
        String(64), index=True, nullable=False
    )
    session_id: Mapped[Optional[str]] = mapped_column(
        String(64), index=True, nullable=True
    )
    event_type: Mapped[str] = mapped_column(
        String(32), index=True, nullable=False,
        comment="load, voice_start, voice_end, lead_captured, etc."
    )
    metadata: Mapped[Optional[dict]] = mapped_column(
        JSON, nullable=True, default=dict
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        server_default=func.now(),
        index=True
    )

    __table_args__ = (
        Index('ix_widget_events_widget_date', 'widget_id', 'created_at'),
    )

class WidgetAnalyticsDaily(Base):
    """
    Daily aggregated metrics per widget.
    Pre-computed for fast dashboard queries.
    """
    __tablename__ = "widget_analytics_daily"

    id: Mapped[str] = mapped_column(
        String(36), primary_key=True, default=lambda: str(uuid4())
    )
    widget_id: Mapped[str] = mapped_column(
        String(64), index=True, nullable=False
    )
    date: Mapped[date] = mapped_column(
        Date, index=True, nullable=False
    )

    # Metrics
    loads: Mapped[int] = mapped_column(
        Integer, default=0, nullable=False
    )
    voice_sessions_started: Mapped[int] = mapped_column(
        Integer, default=0, nullable=False
    )
    voice_sessions_completed: Mapped[int] = mapped_column(
        Integer, default=0, nullable=False
    )
    total_duration_seconds: Mapped[int] = mapped_column(
        Integer, default=0, nullable=False,
        comment="Sum of all session durations for avg calculation"
    )
    avg_duration_seconds: Mapped[float] = mapped_column(
        Float, default=0.0, nullable=False
    )
    leads_captured: Mapped[int] = mapped_column(
        Integer, default=0, nullable=False
    )
    conversion_rate: Mapped[float] = mapped_column(
        Float, default=0.0, nullable=False,
        comment="leads_captured / loads * 100"
    )

    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now()
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        server_default=func.now(),
        onupdate=func.now()
    )

    __table_args__ = (
        UniqueConstraint('widget_id', 'date', name='uix_widget_date'),
        Index('ix_widget_analytics_daily_date_widget', 'date', 'widget_id'),
    )
```

## 2. Pydantic Schemas (`api/schemas.py`)

```python
"""
Pydantic v2 schemas for request/response validation.
"""
from datetime import datetime, date
from typing import Optional, Dict, Any, List
from pydantic import BaseModel, Field, ConfigDict

class EventCreate(BaseModel):
    """Schema for creating a new analytics event."""
    widget_id: str = Field(..., min_length=1, max_length=64)
    session_id: Optional[str] = Field(None, max_length=64)
    event_type: str = Field(..., pattern="^(load|voice_start|voice_end|lead_captured)$")
    metadata: Optional[Dict[str, Any]] = Field(default_factory=dict)
    client_timestamp: Optional[datetime] = Field(
        None, description="Client-side timestamp for latency calculation"
    )

class EventResponse(BaseModel):
    """Schema for event response."""
    model_config = ConfigDict(from_attributes=True)

    id: str
    widget_id: str
    event_type: str
    created_at: datetime

class DailyMetrics(BaseModel):
    """Schema for daily aggregated metrics."""
    model_config = ConfigDict(from_attributes=True)

    date: date
    widget_id: str
    loads: int
    voice_sessions_started: int
    voice_sessions_completed: int
    avg_duration_seconds: float
    leads_captured: int
    conversion_rate: float

class AnalyticsSummary(BaseModel):
    """Schema for analytics summary response."""
    widget_id: str
    start_date: date
    end_date: date
    daily_metrics: List[DailyMetrics]
    totals: Dict[str, Any]

class SSEEvent(BaseModel):
    """Schema for Server-Sent Events."""
    event_type: str = Field(default="update")
    data: Dict[str, Any]
    id: Optional[str] = None
```

## 3. Services

### Event Tracker (`services/tracker.py`)

```python
"""
High-performance event tracking service with batching support.
"""
import logging
from datetime import datetime
from typing import Optional, Dict, Any
from uuid import uuid4

from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import insert

from models.database import WidgetEvent

logger = logging.getLogger(__name__)

class AnalyticsTracker:
    """
    Tracks widget analytics events.
    Supports both immediate persistence and batching for high throughput.
    """

    def __init__(self, db_session: AsyncSession):
        self.db = db_session
        self._batch_buffer: list = []
        self._batch_size = 100

    async def track_event(
        self,
        widget_id: str,
        event_type: str,
        session_id: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None,
        client_timestamp: Optional[datetime] = None
    ) -> str:
        """
        Track a single analytics event.

        Args:
            widget_id: Unique widget identifier
            event_type: Type of event (load, voice_start, voice_end, lead_captured)
            session_id: Optional session identifier for grouping
            metadata: Additional JSON data
            client_timestamp: Client-side timestamp for latency analysis

        Returns:
            Event UUID
        """
        try:
            event_id = str(uuid4())
            event = WidgetEvent(
                id=event_id,
                widget_id=widget_id,
                session_id=session_id,
                event_type=event_type,
                metadata=metadata or {},
                created_at=datetime.utcnow()
            )

            self.db.add(event)
            await self.db.commit()

            logger.debug(f"Tracked event {event_type} for widget {widget_id}")
            return event_id

        except Exception as e:
            await self.db.rollback()
            logger.error(f"Failed to track event: {e}", exc_info=True)
            raise

    async def track_widget_load(self, widget_id: str, session_id: Optional[str] = None) -> str:
        """Convenience method for widget load events."""
        return await self.track_event(
            widget_id=widget_id,
            event_type="load",
            session_id=session_id
        )

    async def track_voice_session_start(
        self,
        widget_id: str,
        session_id: str
    ) -> str:
        """Track start of voice session."""
        return await self.track_event(
            widget_id=widget_id,
            event_type="voice_start",
            session_id=session_id,
            metadata={"start_time": datetime.utcnow().isoformat()}
        )

    async def track_voice_session_end(
        self,
        widget_id: str,
        session_id: str,
        duration_seconds: int,
        completed: bool = True
    ) -> str:
        """Track end of voice session with duration."""
        return await self.track_event(
            widget_id=widget_id,
            event_type="voice_end",
            session_id=session_id,
            metadata={
                "duration_seconds": duration_seconds,
                "completed": completed,
                "end_time": datetime.utcnow().isoformat()
            }
        )

    async def track_lead_captured(
        self,
        widget_id: str,
        session_id: Optional[str] = None,
        lead_data: Optional[dict] = None
    ) -> str:
        """Track lead capture conversion."""
        return await self.track_event(
            widget_id=widget_id,
            event_type="lead_captured",
            session_id=session_id,
            metadata={"lead_data": lead_data} if lead_data else {}
        )
```

### Aggregation Service (`services/aggregation.py`)

```python
"""
Daily aggregation service with timezone-aware rollups.
Runs as a background job, not per-request.
"""
import logging
from datetime import date, datetime, timedelta
from typing import Optional, List
from zoneinfo import ZoneInfo

from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, and_, insert, update
from sqlalchemy.dialects.postgresql import insert as pg_insert

from models.database import WidgetEvent, WidgetAnalyticsDaily

logger = logging.getLogger(__name__)

class AggregationService:
    """
    Handles daily aggregation of widget events.
    Designed to run on a schedule (e.g., every hour) via APScheduler or Celery.
    """

    def __init__(self, db_session: AsyncSession, timezone: str = "UTC"):
        self.db = db_session
        self.timezone = ZoneInfo(timezone)

    async def aggregate_daily(
        self,
        target_date: Optional[date] = None,
        widget_id: Optional[str] = None
    ) -> None:
        """
        Aggregate events into daily metrics.

        Args:
            target_date: Date to aggregate (defaults to yesterday to ensure completeness)
            widget_id: Optional specific widget to aggregate (None = all widgets)
        """
        if target_date is None:
            # Default to yesterday to ensure we have complete data
            target_date = datetime.now(self.timezone).date() - timedelta(days=1)

        logger.info(f"Starting daily aggregation for {target_date}" +
                   (f" widget={widget_id}" if widget_id else " (all widgets)"))

        try:
            # Calculate time boundaries in UTC (storage timezone)
            start_dt = datetime.combine(target_date, datetime.min.time())
            end_dt = datetime.combine(target_date, datetime.max.time())

            # Build base query
            base_query = select(WidgetEvent).where(
                and_(
                    WidgetEvent.created_at >= start_dt,
                    WidgetEvent.created_at <= end_dt
                )
            )

            if widget_id:
                base_query = base_query.where(WidgetEvent.widget_id == widget_id)

            # Aggregate metrics per widget
            metrics_query = select(
                WidgetEvent.widget_id,
                func.count(func.distinct(WidgetEvent.session_id)).filter(
                    WidgetEvent.event_type == "load"
                ).label("loads"),
                func.count(func.distinct(WidgetEvent.session_id)).filter(
                    WidgetEvent.event_type == "voice_start"
                ).label("voice_started"),
                func.count(func.distinct(WidgetEvent.session_id)).filter(
                    WidgetEvent.event_type == "voice_end"
                ).label("voice_completed"),
                func.sum(
                    func.coalesce(
                        func.cast(
                            func.json_extract_path_text(WidgetEvent.metadata, "duration_seconds"),
                            Integer
                        ), 0
                    )
                ).label("total_duration"),
                func.count(func.distinct(WidgetEvent.session_id)).filter(
                    WidgetEvent.event_type == "lead_captured"
                ).label("leads")
            ).where(
                and_(
                    WidgetEvent.created_at >= start_dt,
                    WidgetEvent.created_at <= end_dt
                )
            ).group_by(WidgetEvent.widget_id)

            if widget_id:
                metrics_query = metrics_query.where(WidgetEvent.widget_id == widget_id)

            result = await self.db.execute(metrics_query)
            rows = result.all()

            # Upsert daily records
            for row in rows:
                widget_id_val = row.widget_id
                loads = row.loads or 0
                voice_started = row.voice_started or 0
                voice_completed = row.voice_completed or 0
                total_duration = row.total_duration or 0
                leads = row.leads or 0

                # Calculate derived metrics
                avg_duration = (
                    total_duration / voice_completed if voice_completed > 0 else 0.0
                )
                conversion_rate = (leads / loads * 100) if loads > 0 else 0.0

                # Upsert statement (PostgreSQL syntax)
                stmt = pg_insert(WidgetAnalyticsDaily).values(
                    id=str(uuid4()),
                    widget_id=widget_id_val,
                    date=target_date,
                    loads=loads,
                    voice_sessions_started=voice_started,
                    voice_sessions_completed=voice_completed,
                    total_duration_seconds=total_duration,
                    avg_duration_seconds=avg_duration,
                    leads_captured=leads,
                    conversion_rate=conversion_rate
                ).on_conflict_do_update(
                    index_elements=['widget_id', 'date'],
                    set_=dict(
                        loads=loads,
                        voice_sessions_started=voice_started,
                        voice_sessions_completed=voice_completed,
                        total_duration_seconds=total_duration,
                        avg_duration_seconds=avg_duration,
                        leads_captured=leads,
                        conversion_rate=conversion_rate,
                        updated_at=func.now()
                    )
                )

                await self.db.execute(stmt)

            await self.db.commit()
            logger.info(f"Completed aggregation for {target_date}: {len(rows)} widgets processed")

        except Exception as e:
            await self.db.rollback()
            logger.error(f"Aggregation failed for {target_date}: {e}", exc_info=True)
            raise

    async def get_metrics(
        self,
        widget_id: str,
        start_date: date,
        end_date: date
    ) -> List[WidgetAnalyticsDaily]:
        """
        Retrieve aggregated metrics for a date range.
        """
        from sqlalchemy import select

        stmt = select(WidgetAnalyticsDaily).where(
            and_(
                WidgetAnalyticsDaily.widget_id == widget_id,
                WidgetAnalyticsDaily.date >= start_date,
                WidgetAnalyticsDaily.date <= end_date
            )
        ).order_by(WidgetAnalyticsDaily.date)

        result = await self.db.execute(stmt)
        return result.scalars().all()
```

### SSE Manager (`services/sse_manager.py`)

```python
"""
Server-Sent Events manager for real-time analytics streaming.
Handles connection lifecycle and cleanup.
"""
import asyncio
import logging
from typing import Dict, Set, Optional
from asyncio import Queue, Task
from datetime import datetime

from pydantic import BaseModel

logger = logging.getLogger(__name__)

class SSEEvent(BaseModel):
    """Standardized SSE event format."""
    event: str = "message"
    data: dict
    id: Optional[str] = None

class SSEManager:
    """
    Manages SSE connections per widget.
    Handles connection cleanup on disconnect to prevent memory leaks.
    """

    def __init__(self):
        # widget_id -> Set of client queues
        self._connections: Dict[str, Set[Queue]] = {}
        self._cleanup_tasks: Dict[Queue, Task] = {}
        self._lock = asyncio.Lock()

    async def connect(self, widget_id: str) -> Queue:
        """
        Register a new SSE connection for a widget.
        Returns a Queue that will receive events.
        """
        queue: Queue = asyncio.Queue(maxsize=100)  # Backpressure protection

        async with self._lock:
            if widget_id not in self._connections:
                self._connections[widget_id] = set()
            self._connections[widget_id].add(queue)

            # Start cleanup watcher
            self._cleanup_tasks[queue] = asyncio.create_task(
                self._watch_connection(widget_id, queue)
            )

        logger.info(f"SSE connection established for widget {widget_id}. "
                   f"Active connections: {len(self._connections.get(widget_id, set()))}")
        return queue

    async def disconnect(self, widget_id: str, queue: Queue) -> None:
        """
        Clean up disconnected client.
        Called automatically when client disconnects or queue is full.
        """
        async with self._lock:
            await self._cleanup_connection(widget_id, queue)

    async def _cleanup_connection(self, widget_id: str, queue: Queue) -> None:
        """Internal cleanup logic."""
        if widget_id in self._connections and queue in self._connections[widget_id]:
            self._connections[widget_id].discard(queue)

            # Cancel cleanup task
            if queue in self._cleanup_tasks:
                self._cleanup_tasks[queue].cancel()
                del self._cleanup_tasks[queue]

            # Drain queue to prevent memory leak
            while not queue.empty():
                try:
                    queue.get_nowait()
                except asyncio.QueueEmpty:
                    break

            logger.info(f"SSE connection cleaned up for widget {widget_id}")

    async def _watch_connection(self, widget_id: str, queue: Queue) -> None:
        """
        Watch for connection health.
        If queue is full (client not consuming), disconnect to prevent memory issues.
        """
        try:
            while True:
                await asyncio.sleep(30)  # Check every 30 seconds

                # If queue is nearly full, client is likely disconnected
                if queue.qsize() > 90:
                    logger.warning(f"Queue full for widget {widget_id}, forcing disconnect")
                    await self.disconnect(widget_id, queue)
                    break

        except asyncio.CancelledError:
            pass  # Normal cleanup
        except Exception as e:
            logger.error(f"Error watching connection: {e}")
            await self.disconnect(widget_id, queue)

    async def broadcast(self, widget_id: str, event: SSEEvent) -> None:
        """
        Broadcast event to all connected clients for a widget.
        Non-blocking; drops events for slow clients.
        """
        if widget_id not in self._connections:
            return

        dead_queues = []

        for queue in self._connections[widget_id]:
            try:
                # Non-blocking put with timeout
                queue.put_nowait(event)
            except asyncio.QueueFull:
                # Client is slow, mark for cleanup
                dead_queues.append(queue)
            except Exception as e:
                logger.error(f"Error broadcasting to queue: {e}")
                dead_queues.append(queue)

        # Cleanup dead connections
        for queue in dead_queues:
            await self.disconnect(widget_id, queue)
```

## 4. API Routes (`api/analytics.py`)

```python
"""
Analytics API endpoints with authentication and SSE streaming.
"""
import asyncio
from datetime import date, timedelta
from typing import AsyncGenerator, Optional

from fastapi import APIRouter, Depends, HTTPException, Request, status
from fastapi.responses import StreamingResponse
from sqlalchemy.ext.asyncio import AsyncSession

from api.dependencies import get_db, get_current_user, require_permissions
from api.schemas import (
    EventCreate, EventResponse, AnalyticsSummary,
    DailyMetrics, SSEEvent
)
from services.tracker import AnalyticsTracker
from services.aggregation import AggregationService
from services.sse_manager import SSEManager

router = APIRouter(prefix="/api/analytics", tags=["analytics"])

# Global SSE manager instance (in production, use Redis for multi-instance)
sse_manager = SSEManager()

@router.post("/events", response_model=EventResponse, status_code=status.HTTP_201_CREATED)
async def create_event(
    event: EventCreate,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(require_permissions("widget:write"))
):
    """
    Record a new analytics event.
    Requires widget:write permission.
    """
    try:
        tracker = AnalyticsTracker(db)

        # Route to specific tracking method based on event type
        if event.event_type == "load":
            event_id = await tracker.track_widget_load(
                event.widget_id, event.session_id
            )
        elif event.event_type == "voice_start":
            event_id = await tracker.track_voice_session_start(
                event.widget_id, event.session_id
            )
        elif event.event_type == "voice_end":
            duration = event.metadata.get("duration_seconds", 0) if event.metadata else 0
            completed = event.metadata.get("completed", True) if event.metadata else True
            event_id = await tracker.track_voice_session_end(
                event.widget_id, event.session_id, duration, completed
            )
        elif event.event_type == "lead_captured":
            event_id = await tracker.track_lead_captured(
                event.widget_id, event.session_id, event.metadata
            )
        else:
            # Generic event tracking
            event_id = await tracker.track_event(
                event.widget_id,
                event.event_type,
                event.session_id,
                event.metadata
            )

        # Broadcast to real-time listeners
        await sse_manager.broadcast(
            event.widget_id,
            SSEEvent(
                event_type="new_event",
                data={
                    "event_type": event.event_type,
                    "widget_id": event.widget_id,
                    "timestamp": datetime.utcnow().isoformat()
                }
            )
        )

        return EventResponse(
            id=event_id,
            widget_id=event.widget_id,
            event_type=event.event_type,
            created_at=datetime.utcnow()
        )

    except Exception as e:
        logger.error(f"Error creating event: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to record analytics event"
        )

@router.get("/{widget_id}", response_model=AnalyticsSummary)
async def get_analytics(
    widget_id: str,
    start_date: Optional[date] = None,
    end_date: Optional[date] = None,
    db: AsyncSession = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Retrieve aggregated analytics for a widget.
    Returns daily rollups for the specified date range.
    Defaults to last 30 days.
    """
    try:
        # Default to last 30 days if not specified
        if end_date is None:


Response:
Here's a production-grade implementation using **FastAPI**, **SQLAlchemy 2.0 (async)**, and **PostgreSQL**. This implementation follows clean architecture principles with repository pattern, cursor-based pagination, full-text search, and streaming exports.

## Project Structure

```text
widget_admin/
├── app/
│   ├── __init__.py
│   ├── main.py              # FastAPI application factory
│   ├── config.py            # Pydantic settings
│   ├── dependencies.py      # Auth & tenant injection
│   ├── exceptions.py        # Custom exceptions & handlers
│   ├── models.py            # SQLAlchemy ORM models
│   ├── schemas.py           # Pydantic request/response models
│   ├── repositories/        # Data access layer
│   │   ├── __init__.py
│   │   ├── base.py          # Generic repository
│   │   └── admin.py         # Admin-specific queries
│   ├── services/            # Business logic layer
│   │   ├── __init__.py
│   │   └── admin.py
│   └── api/
│       └── v1/
│           ├── __init__.py
│           └── admin.py     # Route handlers
└── requirements.txt
```

## Implementation

### 1. Configuration & Dependencies

```python
# app/config.py
from functools import lru_cache
from typing import List

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    """Application configuration loaded from environment variables."""

    # Database
    database_url: str = "postgresql+asyncpg://user:pass@localhost/widget_db"
    database_pool_size: int = 10

    # Security
    secret_key: str = "your-secret-key-change-in-production"
    algorithm: str = "HS256"
    access_token_expire_minutes: int = 30

    # Pagination
    default_page_size: int = 20
    max_page_size: int = 100

    class Config:
        env_file = ".env"

@lru_cache()
def get_settings() -> Settings:
    return Settings()
```

```python
# app/exceptions.py
from fastapi import HTTPException, Request
from fastapi.responses import JSONResponse

class TenantNotFoundException(HTTPException):
    def __init__(self):
        super().__init__(status_code=404, detail="Tenant not found")

class UnauthorizedException(HTTPException):
    def __init__(self):
        super().__init__(status_code=401, detail="Invalid authentication credentials")

async def http_exception_handler(request: Request, exc: HTTPException):
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.detail, "path": request.url.path}
    )
```

### 2. Database Models with Full-Text Search

```python
# app/models.py
import uuid
from datetime import datetime
from enum import Enum
from typing import List, Optional

from sqlalchemy import (
    Column, String, DateTime, ForeignKey, Text,
    Index, func, Numeric, Boolean, Integer, Enum as SQLEnum
)
from sqlalchemy.dialects.postgresql import UUID, TSVECTOR
from sqlalchemy.orm import DeclarativeBase, relationship, Mapped, mapped_column
from sqlalchemy.sql import expression

class Base(DeclarativeBase):
    pass

class LeadStatus(str, Enum):
    NEW = "new"
    CONTACTED = "contacted"
    QUALIFIED = "qualified"
    CONVERTED = "converted"
    LOST = "lost"

class Tenant(Base):
    __tablename__ = "tenants"

    id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    slug: Mapped[str] = mapped_column(String(100), unique=True, index=True)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)

    # Relationships
    widgets: Mapped[List["Widget"]] = relationship(back_populates="tenant")
    conversations: Mapped[List["Conversation"]] = relationship(back_populates="tenant")
    leads: Mapped[List["Lead"]] = relationship(back_populates="tenant")

class Widget(Base):
    __tablename__ = "widgets"

    id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("tenants.id"), index=True)
    name: Mapped[str] = mapped_column(String(255))
    configuration: Mapped[Optional[dict]] = mapped_column(Text)  # JSON stored as text or use JSONB
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        server_default=func.now(),
        onupdate=func.now()
    )

    tenant: Mapped[Tenant] = relationship(back_populates="widgets")

class Conversation(Base):
    __tablename__ = "conversations"

    id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("tenants.id"), index=True)
    widget_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("widgets.id"))

    # Content for search
    title: Mapped[Optional[str]] = mapped_column(String(500))
    content: Mapped[Optional[str]] = mapped_column(Text)
    customer_email: Mapped[Optional[str]] = mapped_column(String(255), index=True)
    customer_phone: Mapped[Optional[str]] = mapped_column(String(50))

    # Full-text search vector
    search_vector: Mapped[Optional[str]] = mapped_column(TSVECTOR)

    status: Mapped[str] = mapped_column(String(50), default="active")  # active, closed, archived
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), onupdate=func.now())

    tenant: Mapped[Tenant] = relationship(back_populates="conversations")

    __table_args__ = (
        # Composite index for cursor-based pagination (created_at DESC, id DESC)
        Index('idx_conversations_tenant_created', 'tenant_id', 'created_at', 'id'),
        # GIN index for full-text search
        Index('idx_conversations_search', 'search_vector', postgresql_using='gin'),
    )

class Lead(Base):
    __tablename__ = "leads"

    id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("tenants.id"), index=True)

    email: Mapped[str] = mapped_column(String(255), index=True)
    name: Mapped[Optional[str]] = mapped_column(String(255))
    phone: Mapped[Optional[str]] = mapped_column(String(50))
    status: Mapped[LeadStatus] = mapped_column(SQLEnum(LeadStatus), default=LeadStatus.NEW)
    source: Mapped[Optional[str]] = mapped_column(String(100))  # widget, import, etc.
    notes: Mapped[Optional[str]] = mapped_column(Text)

    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), onupdate=func.now())

    tenant: Mapped[Tenant] = relationship(back_populates="leads")

    __table_args__ = (
        Index('idx_leads_tenant_status', 'tenant_id', 'status'),
        Index('idx_leads_tenant_created', 'tenant_id', 'created_at', 'id'),
    )

class BillingSubscription(Base):
    __tablename__ = "billing_subscriptions"

    id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("tenants.id"), unique=True)

    plan_name: Mapped[str] = mapped_column(String(100))
    status: Mapped[str] = mapped_column(String(50))  # active, past_due, cancelled
    current_period_start: Mapped[datetime] = mapped_column(DateTime(timezone=True))
    current_period_end: Mapped[datetime] = mapped_column(DateTime(timezone=True))
    usage_calls_count: Mapped[int] = mapped_column(Integer, default=0)
    usage_calls_limit: Mapped[int] = mapped_column(Integer, default=1000)

    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
```

### 3. Schemas (Pydantic Models)

```python
# app/schemas.py
from datetime import datetime
from decimal import Decimal
from enum import Enum
from typing import Optional, List, Any, Dict
from uuid import UUID

from pydantic import BaseModel, Field, ConfigDict

# Base configuration for ORM models
class ORMBase(BaseModel):
    model_config = ConfigDict(from_attributes=True)

# Pagination Schemas
class CursorParams(BaseModel):
    cursor: Optional[str] = None
    limit: int = Field(default=20, ge=1, le=100)
    search: Optional[str] = None

class PaginatedResponse(BaseModel):
    items: List[Any]
    next_cursor: Optional[str] = None
    has_more: bool = False
    total_count: Optional[int] = None  # Optional: expensive to calculate

# Admin Overview
class OverviewMetrics(ORMBase):
    total_conversations: int
    total_leads: int
    active_leads: int
    converted_leads: int
    calls_this_month: int
    calls_limit: int
    usage_percentage: float

# Conversations
class ConversationOut(ORMBase):
    id: UUID
    title: Optional[str]
    customer_email: Optional[str]
    status: str
    created_at: datetime
    updated_at: Optional[datetime]

class ConversationListResponse(PaginatedResponse):
    items: List[ConversationOut]

# Leads
class LeadUpdate(BaseModel):
    status: Optional[str] = None
    notes: Optional[str] = None

class LeadOut(ORMBase):
    id: UUID
    email: str
    name: Optional[str]
    phone: Optional[str]
    status: str
    source: Optional[str]
    created_at: datetime

class LeadListResponse(PaginatedResponse):
    items: List[LeadOut]

# Settings
class WidgetSettings(BaseModel):
    widget_id: UUID
    name: str
    configuration: Dict[str, Any]
    is_active: bool
    updated_at: datetime

class WidgetSettingsUpdate(BaseModel):
    name: Optional[str] = None
    configuration: Optional[Dict[str, Any]] = None
    is_active: Optional[bool] = None

# Analytics
class AnalyticsRequest(BaseModel):
    start_date: datetime
    end_date: datetime
    granularity: str = "day"  # hour, day, week, month

class AnalyticsDataPoint(BaseModel):
    timestamp: datetime
    conversations_count: int
    leads_count: int
    conversion_rate: float

class AnalyticsResponse(BaseModel):
    date_range: Dict[str, datetime]
    summary: Dict[str, int]
    chart_data: List[AnalyticsDataPoint]

# Billing
class BillingInfo(ORMBase):
    plan_name: str
    status: str
    current_period_start: datetime
    current_period_end: datetime
    usage: Dict[str, Any]
    features: List[str]
```

### 4. Repository Layer with Cursor Pagination & Full-Text Search

```python
# app/repositories/base.py
import base64
import json
from typing import TypeVar, Generic, Type, Optional, List, Any
from datetime import datetime

from sqlalchemy import select, func, desc, text
from sqlalchemy.ext.asyncio import AsyncSession

from app.models import Base

ModelType = TypeVar("ModelType", bound=Base)

class BaseRepository(Generic[ModelType]):
    def __init__(self, model: Type[ModelType]):
        self.model = model

    def _encode_cursor(self, data: dict) -> str:
        """Encode cursor data to base64 string."""
        json_bytes = json.dumps(data, default=str).encode('utf-8')
        return base64.b64encode(json_bytes).decode('utf-8')

    def _decode_cursor(self, cursor: str) -> dict:
        """Decode base64 cursor string to dict."""
        try:
            json_bytes = base64.b64decode(cursor.encode('utf-8'))
            return json.loads(json_bytes)
        except Exception:
            raise ValueError("Invalid cursor format")

    async def get_by_cursor(
        self,
        db: AsyncSession,
        tenant_id: UUID,
        cursor: Optional[str] = None,
        limit: int = 20,
        search: Optional[str] = None,
        order_by: str = "created_at"
    ) -> tuple[List[ModelType], Optional[str]]:
        """
        Cursor-based pagination using (created_at, id) composite key.
        Prevents offset-based performance degradation at scale.
        """
        query = select(self.model).where(self.model.tenant_id == tenant_id)

        # Apply search filter using PostgreSQL full-text search
        if search:
            # Convert search query to tsquery and match against search_vector
            search_filter = text(
                "search_vector @@ plainto_tsquery('english', :search)"
            )
            query = query.where(search_filter).params(search=search)

        # Apply cursor filter
        if cursor:
            cursor_data = self._decode_cursor(cursor)
            cursor_date = datetime.fromisoformat(cursor_data['created_at'])
            cursor_id = cursor_data['id']

            # WHERE (created_at, id) < (cursor_date, cursor_id)
            # This ensures stable pagination even with duplicate timestamps
            query = query.where(
                (self.model.created_at < cursor_date) |
                (
                    (self.model.created_at == cursor_date) &
                    (self.model.id < cursor_id)
                )
            )

        # Order by created_at DESC, id DESC (newest first)
        query = query.order_by(desc(getattr(self.model, order_by)), desc(self.model.id))

        # Fetch limit + 1 to determine if there's a next page
        result = await db.execute(query.limit(limit + 1))
        items = result.scalars().all()

        has_more = len(items) > limit
        items = list(items[:limit])

        next_cursor = None
        if has_more and items:
            last_item = items[-1]
            next_cursor = self._encode_cursor({
                'created_at': last_item.created_at.isoformat(),
                'id': str(last_item.id)
            })

        return items, next_cursor
```

```python
# app/repositories/admin.py
from typing import Optional, List, Tuple
from datetime import datetime
from uuid import UUID

from sqlalchemy import select, func, and_, text
from sqlalchemy.ext.asyncio import AsyncSession

from app.models import Conversation, Lead, Widget, BillingSubscription, Tenant
from app.repositories.base import BaseRepository
from app.schemas import LeadStatus

class AdminRepository:
    def __init__(self, db: AsyncSession):
        self.db = db
        self.conversation_repo = BaseRepository(Conversation)
        self.lead_repo = BaseRepository(Lead)

    async def get_overview_metrics(self, tenant_id: UUID) -> dict:
        """Aggregate metrics for dashboard overview."""
        # Conversations count
        conv_query = select(func.count(Conversation.id)).where(
            Conversation.tenant_id == tenant_id
        )
        conv_result = await self.db.execute(conv_query)
        total_conversations = conv_result.scalar()

        # Leads aggregation
        leads_query = select(
            func.count(Lead.id).label('total'),
            func.sum(func.case((Lead.status == LeadStatus.NEW, 1), else_=0)).label('active'),
            func.sum(func.case((Lead.status == LeadStatus.CONVERTED, 1), else_=0)).label('converted')
        ).where(Lead.tenant_id == tenant_id)

        leads_result = await self.db.execute(leads_query)
        leads_data = leads_result.one()

        # Billing info
        billing_query = select(BillingSubscription).where(
            BillingSubscription.tenant_id == tenant_id
        )
        billing_result = await self.db.execute(billing_query)
        billing = billing_result.scalar_one_or_none()

        usage_count = billing.usage_calls_count if billing else 0
        usage_limit = billing.usage_calls_limit if billing else 1000

        return {
            "total_conversations": total_conversations or 0,
            "total_leads": leads_data.total or 0,
            "active_leads": leads_data.active or 0,
            "converted_leads": leads_data.converted or 0,
            "calls_this_month": usage_count,
            "calls_limit": usage_limit,
            "usage_percentage": (usage_count / usage_limit * 100) if usage_limit > 0 else 0
        }

    async def get_conversations(
        self,
        tenant_id: UUID,
        cursor: Optional[str] = None,
        limit: int = 20,
        search: Optional[str] = None
    ) -> Tuple[List[Conversation], Optional[str]]:
        """Get paginated conversations with full-text search."""
        return await self.conversation_repo.get_by_cursor(
            self.db, tenant_id, cursor, limit, search
        )

    async def get_leads(
        self,
        tenant_id: UUID,
        cursor: Optional[str] = None,
        limit: int = 20,
        status: Optional[str] = None
    ) -> Tuple[List[Lead], Optional[str]]:
        """Get paginated leads with optional status filter."""
        # Override base query to add status filter if needed
        query = select(Lead).where(Lead.tenant_id == tenant_id)

        if status:
            query = query.where(Lead.status == status)

        # Apply cursor logic manually since we have extra filters
        if cursor:
            from app.repositories.base import BaseRepository
            repo = BaseRepository(Lead)
            cursor_data = repo._decode_cursor(cursor)
            cursor_date = datetime.fromisoformat(cursor_data['created_at'])
            cursor_id = cursor_data['id']

            query = query.where(
                (Lead.created_at < cursor_date) |
                ((Lead.created_at == cursor_date) & (Lead.id < cursor_id))
            )

        query = query.order_by(Lead.created_at.desc(), Lead.id.desc())
        result = await self.db.execute(query.limit(limit + 1))
        items = list(result.scalars().all())

        has_more = len(items) > limit
        items = items[:limit]

        next_cursor = None
        if has_more and items:
            repo = BaseRepository(Lead)
            next_cursor = repo._encode_cursor({
                'created_at': items[-1].created_at.isoformat(),
                'id': str(items[-1].id)
            })

        return items, next_cursor

    async def update_lead_status(
        self,
        tenant_id: UUID,
        lead_id: UUID,
        status: str,
        notes: Optional[str] = None
    ) -> Optional[Lead]:
        """Update lead status and notes."""
        query = select(Lead).where(
            and_(Lead.id == lead_id, Lead.tenant_id == tenant_id)
        )
        result = await self.db.execute(query)
        lead = result.scalar_one_or_none()

        if not lead:
            return None

        lead.status = status
        if notes is not None:
            lead.notes = notes

        await self.db.commit()
        await self.db.refresh(lead)
        return lead

    async def get_widget_settings(self, tenant_id: UUID) -> Optional[Widget]:
        """Get widget configuration for tenant."""
        query = select(Widget).where(
            and_(Widget.tenant_id == tenant_id, Widget.is_active == True)
        )
        result = await self.db.execute(query)
        return result.scalar_one_or_none()

    async def update_widget_settings(
        self,
        tenant_id: UUID,
        widget_id: UUID,
        **updates
    ) -> Optional[Widget]:
        """Update widget configuration."""
        query = select(Widget).where(
            and_(
                Widget.id == widget_id,
                Widget.tenant_id == tenant_id
            )
        )
        result = await self.db.execute(query)
        widget = result.scalar_one_or_none()

        if not widget:
            return None

        for key, value in updates.items():
            if value is not None and hasattr(widget, key):
                setattr(widget, key, value)

        await self.db.commit()
        await self.db.refresh(widget)
        return widget

    async def get_analytics(
        self,
        tenant_id: UUID,
        start_date: datetime,
        end_date: datetime,
        granularity: str = "day"
    ) -> List[dict]:
        """
        Generate time-series analytics data.
        Uses date_trunc for PostgreSQL time bucketing.
        """
        # Map granularity to PostgreSQL date_trunc format
        trunc_map = {
            "hour": "hour",
            "day": "day",
            "week": "week",
            "month": "month"
        }
        trunc_format = trunc_map.get(granularity, "day")

        # Conversations per time bucket
        conv_query = text(f"""
            SELECT
                date_trunc('{trunc_format}', created_at) as period,
                count(*) as count
            FROM conversations
            WHERE tenant_id = :tenant_id
              AND created_at BETWEEN :start_date AND :end_date
            GROUP BY period
            ORDER BY period
        """)

        # Leads per time bucket
        leads_query = text(f"""
            SELECT
                date_trunc('{trunc_format}', created_at) as period,
                count(*) as count,
                sum(case when status = 'converted' then 1 else 0 end) as converted
            FROM leads
            WHERE tenant_id = :tenant_id
              AND created_at BETWEEN :start_date AND :end_date
            GROUP BY period
            ORDER BY period
        """)

        conv_result = await self.db.execute(
            conv_query,
            {
                "tenant_id": tenant_id,
                "start_date": start_date,
                "end_date": end_date
            }
        )

        leads_result = await self.db.execute(
            leads_query,
            {
                "tenant_id": tenant_id,
                "start_date": start_date,
                "end_date": end_date
            }
        )

        conv_data = {row.period: row.count for row in conv_result}
        leads_data = {
            row.period: {"total": row.count, "converted": row.converted or 0}
            for row in leads_result
        }

        # Merge data
        all_periods = set(conv_data.keys()) | set(leads_data.keys())
        analytics = []

        for period in sorted(all_periods):
            conv_count = conv_data.get(period, 0)
            leads_info = leads_data.get(period, {"total": 0, "converted": 0})
            leads_count = leads_info["total"]
            converted = leads_info["converted"]

            conversion_rate = (converted / leads_count * 100) if leads_count > 0 else 0

            analytics.append({
                "timestamp": period,
                "conversations_count": conv_count,
                "leads_count": leads_count,
                "conversion_rate": round(conversion_rate, 2)
            })

        return analytics

    async def get_billing_info(self, tenant_id: UUID) -> Optional[BillingSubscription]:
        """Get billing and subscription details."""
        query = select(BillingSubscription).where(
            BillingSubscription.tenant_id == tenant_id
        )
        result = await self.db.execute(query)
        return result.scalar_one_or_none()

    async def stream_leads_csv(self, tenant_id: UUID, batch_size: int = 1000):
        """
        Generator for streaming CSV export.
        Yields rows in chunks to prevent memory exhaustion on large datasets.
        """
        import csv
        import io

        output = io.StringIO()
        writer = csv.writer(output)

        # Write headers
        writer.writerow(['id', 'email', 'name', 'phone', 'status', 'source', 'created_at'])
        yield output.getvalue()
        output.seek(0)
        output.truncate(0)

        # Stream in batches using keyset pagination (last_id)
        last_id = None

        while True:
            query = select(Lead).where(
                Lead.tenant_id == tenant_id
            ).order_by(Lead.id).limit(batch_size)

            if last_id:
                query = query.where(Lead.id > last_id)

            result = await self.db.execute(query)
            batch = result.scalars().all()

            if not batch:
                break

            for lead in batch:
                writer.writerow([
                    str(lead.id),
                    lead.email,
                    lead.name or '',
                    lead.phone or '',
                    lead.status,
                    lead.source or '',
                    lead.created_at.isoformat()
                ])
                last_id = lead.id

            yield output.getvalue()
            output.seek(0)
            output.truncate(0)
```

### 5. API Routes

```python
# app/api/v1/admin.py
from typing import Optional
from datetime import datetime
from uuid import UUID

from fastapi import APIRouter, Depends, Query, HTTPException, BackgroundTasks
from fastapi.responses import StreamingResponse
from sqlalchemy.ext.asyncio import AsyncSession

from app.dependencies import get_current_tenant, get_db, get_settings
from app.repositories.admin import AdminRepository
from app.schemas import (
    OverviewMetrics, ConversationListResponse, LeadListResponse,
    LeadOut, LeadUpdate, WidgetSettings, WidgetSettingsUpdate,
    AnalyticsRequest, AnalyticsResponse, BillingInfo, CursorParams
)

router = APIRouter(prefix="/admin", tags=["admin"])

@router.get("/overview", response_model=OverviewMetrics)
async def get_overview(
    tenant_id: UUID = Depends(get_current_tenant),
    db: AsyncSession = Depends(get_db)
):
    """
    Get dashboard overview metrics scoped to authenticated tenant.

    Returns aggregated counts for conversations, leads, and billing usage.
    """
    repo = AdminRepository(db)
    metrics = await repo.get_overview_metrics(tenant_id)
    return OverviewMetrics(**metrics)

@router.get("/conversations", response_model=ConversationListResponse)
async def list_conversations(
    params: CursorParams = Depends(),
    tenant_id: UUID = Depends(get_current_tenant),
    db: AsyncSession = Depends(get_db)
):
    """
    List conversations with cursor-based pagination and full-text search.

    - **cursor**: Base64 encoded pagination cursor
    - **limit**: Items per page (max 100)
    - **search**: Full-text search query (uses PostgreSQL tsvector)

    White-box: Uses composite index (tenant_id, created_at, id) for efficient
    keyset pagination. Avoids OFFSET for O(1) performance at any scale.
    """
    repo = AdminRepository(db)
    items, next_cursor = await repo.get_conversations(
        tenant_id=tenant_id,
        cursor=params.cursor,
        limit=params.limit,
        search=params.search
    )

    return ConversationListResponse(
        items=items,
        next_cursor=next_cursor,
        has_more=next_cursor is not None
    )

@router.get("/leads", response_model=LeadListResponse)
async def list_leads(
    cursor: Optional[str] = None,
    limit: int = Query(default=20, ge=1, le=100),
    status: Optional[str] = None,
    tenant_id: UUID = Depends(get_current_tenant),
    db: AsyncSession = Depends(get_db)
):
    """
    List leads with cursor pagination and optional status filtering.
    """
    repo = AdminRepository(db)
    items, next_cursor = await repo.get_leads(
        tenant_id=tenant_id,
        cursor=cursor,
        limit=limit,
        status=status
    )

    return LeadListResponse(
        items=items,
        next_cursor=next_cursor,
        has_more=next_cursor is not None
    )

@router.patch("/leads/{lead_id}", response_model=LeadOut)
async def update_lead(
    lead_id: UUID,
    update: LeadUpdate,
    tenant_id: UUID = Depends(get_current_tenant),
    db: AsyncSession = Depends(get_db)
):
    """
    Update lead status and/or notes.
    """
    repo = AdminRepository(db)
    lead = await repo.update_lead_status(
        tenant_id=tenant_id,
        lead_id=lead_id,
        status=update.status,
        notes=update.notes
    )

    if not lead:
        raise HTTPException(status_code=404, detail="Lead not found")

    return lead

@router.get("/leads/export")
async def export_leads(
    tenant_id: UUID = Depends(get_current_tenant),
    db: AsyncSession = Depends(get_db)
):
    """
    Stream leads as CSV export.

    White-box: Uses server-side cursor (keyset pagination) and generators
    to stream response. Memory usage remains constant regardless of dataset size.
    """
    repo = AdminRepository(db)

    return StreamingResponse(
        repo.stream_leads_csv(tenant_id),
        media_type="text/csv",
        headers={
            "Content-Disposition": f"attachment; filename=leads_{tenant_id}.csv",
            "Cache-Control": "no-cache",
        }
    )

@router.get("/settings", response_model=WidgetSettings)
async def get_settings(
    tenant_id: UUID = Depends(get_current_tenant),
    db: AsyncSession = Depends(get_db)
):
    """
    Get widget configuration settings for the tenant.
    """
    repo = AdminRepository(db)
    widget = await repo.get_widget_settings(tenant_id)

    if not widget:
        raise HTTPException(status_code=404, detail="Widget not found")

    # Parse configuration JSON if stored as string
    config = widget.configuration
    if isinstance(config, str):
        import json
        config = json.loads(config)

    return WidgetSettings(
        widget_id=widget.id,
        name=widget.name,
        configuration=config or {},
        is_active=widget.is_active,
        updated_at=widget.updated_at
    )

@router.patch("/settings/{widget_id}", response_model=WidgetSettings)
async def update_settings(
    widget_id: UUID,
    update: WidgetSettingsUpdate,
    tenant_id: UUID = Depends(get_current_tenant),
    db: AsyncSession = Depends(get_db)
):
    """
    Update widget configuration.
    """
    repo = AdminRepository(db)

    # Convert dict to JSON string if needed by your model
    config = update.configuration
    if config is not None:
        import json
        config = json.dumps(config)

    widget = await repo.update_widget_settings(
        tenant_id=tenant_id,
        widget_id=widget_id,
        name=update.name,
        configuration=config,
        is_active=update.is_active
    )

    if not widget:
        raise HTTPException(status_code=404, detail="Widget not found")

    return await get_settings(tenant_id, db)

@router.get("/analytics", response_model=AnalyticsResponse)
async def get_analytics(
    start_date: datetime,
    end_date: datetime,
    granularity: str = Query(default="day", regex="^(hour|day|week|month)$"),
    tenant_id: UUID = Depends(get_current_tenant),
    db: AsyncSession = Depends(get_db)
):
    """
    Get date-range analytics with chart data.

    - **start_date**: ISO format datetime
    - **end_date**: ISO format datetime
    - **granularity**: Time bucketing (hour/day/week/month)
    """
    if start_date >= end_date:
        raise HTTPException(
            status_code=400,
            detail="start_date must be before end_date"
        )

    repo = AdminRepository(db)
    chart_data = await repo.get_analytics(
        tenant_id=tenant_id,
        start_date=start_date,
        end_date=end_date,
        granularity=granularity
    )

    # Calculate summary totals
    total_conversations = sum(d["conversations_count"] for d in chart_data)
    total_leads = sum(d["leads_count"] for d in chart_data)
    avg_conversion = (
        sum(d["conversion_rate"] for d in chart_data) / len(chart_data)
        if chart_data else 0
    )

    return AnalyticsResponse(
        date_range={"start": start_date, "end": end_date},
        summary={
            "total_conversations": total_conversations,
            "total_leads": total_leads,
            "avg_conversion_rate": round(avg_conversion, 2)
        },
        chart_data=chart_data
    )

@router.get("/billing", response_model=BillingInfo)
async def get_billing(
    tenant_id: UUID = Depends(get_current_t


Response:
Here's a production-grade implementation of the Widget Embed Code Generator using FastAPI, with comprehensive security, error handling, and type safety.

## Project Structure

```
widget_embed_api/
├── app/
│   ├── __init__.py
│   ├── main.py                 # FastAPI application entry point
│   ├── config.py               # Pydantic settings
│   ├── models.py               # Request/response schemas
│   ├── dependencies.py         # Dependency injection
│   └── services/
│       ├── __init__.py
│       ├── embed_generator.py  # HTML/JS generation logic
│       ├── domain_verifier.py  # Live widget detection
│       └── wordpress.py        # WordPress plugin generator
├── templates/
│   └── embed_script.html       # Jinja2 template for embed code
└── tests/
    └── test_embed.py
```

## 1. Configuration (`app/config.py`)

```python
"""Application configuration with environment variable support."""

from pydantic import Field, HttpUrl, validator
from pydantic_settings import BaseSettings
from functools import lru_cache
from typing import Optional

class Settings(BaseSettings):
    """Production-grade configuration management."""

    # API Settings
    API_VERSION: str = "v1"
    DEBUG: bool = False

    # CDN Configuration
    CDN_BASE_URL: HttpUrl = Field(default="https://cdn.widget-service.com")
    WIDGET_JS_PATH: str = "/widget.js"
    DEFAULT_VERSION: str = "stable"

    # Security
    ALLOWED_DOMAINS: list[str] = Field(default=[])
    MAX_STYLE_OVERRIDE_LENGTH: int = 1000
    EMBED_TOKEN_SECRET: str = Field(..., env="EMBED_TOKEN_SECRET")

    # Verification Settings
    VERIFY_TIMEOUT: int = 10  # seconds
    VERIFY_MAX_REDIRECTS: int = 3
    VERIFY_CACHE_TTL: int = 300  # 5 minutes

    # Rate Limiting
    RATE_LIMIT_REQUESTS: int = 100
    RATE_LIMIT_PERIOD: int = 60  # seconds

    class Config:
        env_file = ".env"
        case_sensitive = True

@lru_cache()
def get_settings() -> Settings:
    """Cached settings instance for performance."""
    return Settings()
```

## 2. Data Models (`app/models.py`)

```python
"""Pydantic models with strict validation and sanitization."""

from pydantic import BaseModel, Field, HttpUrl, validator, root_validator
from typing import Optional, Dict, Any, Literal
from html import escape
import re

class StyleOverrides(BaseModel):
    """CSS style overrides with injection prevention."""

    primary_color: Optional[str] = Field(None, max_length=7, regex=r'^#[0-9a-fA-F]{6}$')
    font_family: Optional[str] = Field(None, max_length=50)
    border_radius: Optional[str] = Field(None, max_length=10, regex=r'^\d+(px|rem|%)$')
    z_index: Optional[int] = Field(None, ge=0, le=999999)

    @validator('*', pre=True)
    def sanitize_css_values(cls, v):
        """Prevent CSS injection attacks."""
        if v is None:
            return v
        if isinstance(v, str):
            # Remove potentially dangerous CSS characters
            if any(c in v for c in [';', '{', '}', '/*', '*/', '@import', 'expression']):
                raise ValueError("Invalid CSS characters detected")
            return escape(v.strip())
        return v

class GenerateEmbedRequest(BaseModel):
    """Request model for embed code generation."""

    widget_id: str = Field(
        ...,
        min_length=8,
        max_length=64,
        regex=r'^[a-zA-Z0-9_-]+$',
        description="Unique widget identifier"
    )
    target_domain: Optional[HttpUrl] = Field(
        None,
        description="Domain where widget will be embedded (for verification)"
    )
    style_overrides: Optional[StyleOverrides] = None
    format_type: Literal['standard', 'async', 'defer', 'wordpress', 'iframe'] = 'standard'
    cdn_version: str = Field(default="latest", regex=r'^[a-zA-Z0-9._-]+$')
    custom_attributes: Optional[Dict[str, str]] = Field(
        default_factory=dict,
        max_length=10,
        description="Additional data attributes for the script tag"
    )

    @validator('widget_id')
    def validate_widget_id(cls, v: str) -> str:
        """Ensure widget_id is safe for HTML insertion."""
        if not re.match(r'^[a-zA-Z0-9_-]+$', v):
            raise ValueError("widget_id must be alphanumeric with hyphens/underscores only")
        return v

    @validator('custom_attributes')
    def validate_attributes(cls, v: Optional[Dict[str, str]]) -> Dict[str, str]:
        """Sanitize HTML attributes to prevent XSS."""
        if not v:
            return {}
        safe_attrs = {}
        for key, val in v.items():
            # Only allow data-* attributes or specific safe attributes
            if not key.startswith('data-') and key not in ['id', 'class']:
                continue
            safe_key = escape(key.strip())
            safe_val = escape(str(val).strip())
            safe_attrs[safe_key] = safe_val
        return safe_attrs

class EmbedResponse(BaseModel):
    """Response containing generated embed code."""

    html_code: str = Field(..., description="Escaped HTML snippet ready for insertion")
    script_url: HttpUrl
    widget_id: str
    verification_token: Optional[str] = None
    format_type: str
    security_hash: str = Field(..., description="HMAC hash for integrity verification")

    class Config:
        schema_extra = {
            "example": {
                "html_code": "<script src='...' data-widget-id='abc123'></script>",
                "script_url": "https://cdn.widget-service.com/widget.js",
                "widget_id": "abc123",
                "format_type": "standard"
            }
        }

class VerificationRequest(BaseModel):
    """Request to verify widget installation."""

    domain: HttpUrl
    widget_id: str
    verification_token: Optional[str] = None

class VerificationResponse(BaseModel):
    """Result of domain verification."""

    is_live: bool
    domain: str
    widget_id: str
    checked_at: str
    details: Dict[str, Any]
    confidence_score: float = Field(..., ge=0.0, le=1.0)

class WordPressPluginResponse(BaseModel):
    """WordPress plugin package metadata."""

    plugin_name: str
    download_url: str
    installation_code: str
    shortcode: str
    readme_content: str
```

## 3. Embed Generator Service (`app/services/embed_generator.py`)

```python
"""Core service for generating secure embed codes."""

import hmac
import hashlib
import json
from datetime import datetime
from typing import Dict, Any, Optional
from html import escape
from jinja2 import Template, Environment, PackageLoader
from markupsafe import Markup

from app.config import Settings, get_settings
from app.models import GenerateEmbedRequest, EmbedResponse, StyleOverrides

class EmbedGenerationError(Exception):
    """Custom exception for embed generation failures."""
    pass

class EmbedGenerator:
    """Generates secure, escaped HTML embed codes."""

    def __init__(self, settings: Optional[Settings] = None):
        self.settings = settings or get_settings()
        self.env = Environment(loader=PackageLoader('app', 'templates'))
        self.template = self.env.get_template('embed_script.html')

    def _generate_security_hash(self, widget_id: str, domain: Optional[str]) -> str:
        """Generate HMAC hash for integrity verification."""
        secret = self.settings.EMBED_TOKEN_SECRET.encode('utf-8')
        message = f"{widget_id}:{domain or 'none'}:{datetime.utcnow().timestamp()}"
        return hmac.new(secret, message.encode('utf-8'), hashlib.sha256).hexdigest()[:16]

    def _build_script_url(self, version: str, widget_id: str) -> str:
        """Construct CDN URL with cache-busting parameters."""
        base = str(self.settings.CDN_BASE_URL).rstrip('/')
        path = self.settings.WIDGET_JS_PATH.lstrip('/')
        # Add integrity param for cache busting
        return f"{base}/{path}?v={escape(version)}&wid={escape(widget_id)}"

    def _serialize_styles(self, styles: Optional[StyleOverrides]) -> str:
        """Convert style overrides to JSON string with escaping."""
        if not styles:
            return ""
        # Convert to dict, excluding None values
        style_dict = styles.dict(exclude_none=True)
        # JSON encode ensures proper escaping of quotes and special chars
        return json.dumps(style_dict, separators=(',', ':'))

    def generate_standard_embed(self, request: GenerateEmbedRequest) -> str:
        """Generate standard script tag embed code."""
        script_url = self._build_script_url(request.cdn_version, request.widget_id)
        style_json = self._serialize_styles(request.style_overrides)

        # Build data attributes dict
        data_attrs = {
            'data-widget-id': request.widget_id,
        }

        if style_json:
            data_attrs['data-style-overrides'] = style_json

        if request.target_domain:
            data_attrs['data-domain'] = str(request.target_domain)

        # Add custom attributes
        data_attrs.update(request.custom_attributes or {})

        # Render template with escaped values
        html_output = self.template.render(
            script_url=script_url,
            async_loading=False,
            defer_loading=False,
            data_attributes=data_attrs,
            style_config=style_json
        )

        return html_output

    def generate_async_embed(self, request: GenerateEmbedRequest) -> str:
        """Generate non-blocking async embed code."""
        base_html = self.generate_standard_embed(request)
        # Replace <script with <script async
        return base_html.replace('<script ', '<script async ')

    def generate_wordpress_shortcode(self, request: GenerateEmbedRequest) -> str:
        """Generate WordPress shortcode format."""
        # WordPress shortcode attributes need different escaping
        attrs = [f'id="{escape(request.widget_id)}"']

        if request.style_overrides:
            styles = request.style_overrides.json(exclude_none=True)
            # Base64 encode to avoid quote conflicts in shortcode
            import base64
            encoded = base64.b64encode(styles.encode()).decode()
            attrs.append(f'styles="{encoded}"')

        if request.target_domain:
            attrs.append(f'domain="{escape(str(request.target_domain))}"')

        return f"[widget_embed {' '.join(attrs)}]"

    def generate_iframe_preview(self, request: GenerateEmbedRequest) -> str:
        """Generate isolated iframe preview HTML."""
        script_url = self._build_script_url(request.cdn_version, request.widget_id)

        # Full HTML document for iframe
        html_content = f"""<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Widget Preview - {escape(request.widget_id)}</title>
    <style>
        body {{ margin: 0; padding: 20px; font-family: system-ui, sans-serif; }}
        #widget-container {{ border: 1px dashed #ccc; min-height: 200px; }}
    </style>
</head>
<body>
    <div id="widget-container"></div>
    <script src="{escape(script_url)}"
            data-widget-id="{escape(request.widget_id)}"
            data-preview-mode="true"
            data-style-overrides='{self._serialize_styles(request.style_overrides)}'>
    </script>
</body>
</html>"""
        return html_content

    def create_embed(self, request: GenerateEmbedRequest) -> EmbedResponse:
        """Main entry point for embed generation."""
        try:
            # Dispatch to appropriate generator
            generators = {
                'standard': self.generate_standard_embed,
                'async': self.generate_async_embed,
                'defer': lambda r: self.generate_standard_embed(r).replace('<script ', '<script defer '),
                'wordpress': self.generate_wordpress_shortcode,
                'iframe': self.generate_iframe_preview
            }

            generator = generators.get(request.format_type)
            if not generator:
                raise EmbedGenerationError(f"Unknown format type: {request.format_type}")

            html_code = generator(request)
            script_url = self._build_script_url(request.cdn_version, request.widget_id)
            security_hash = self._generate_security_hash(
                request.widget_id,
                str(request.target_domain) if request.target_domain else None
            )

            return EmbedResponse(
                html_code=html_code,
                script_url=script_url,
                widget_id=request.widget_id,
                format_type=request.format_type,
                security_hash=security_hash,
                verification_token=security_hash if request.target_domain else None
            )

        except Exception as e:
            raise EmbedGenerationError(f"Failed to generate embed: {str(e)}") from e
```

## 4. Domain Verification Service (`app/services/domain_verifier.py`)

```python
"""Service for verifying widget installation on remote domains."""

import asyncio
import re
from typing import Optional, Dict, Any
from datetime import datetime
from urllib.parse import urlparse
import httpx
from cachetools import TTLCache

from app.config import Settings, get_settings
from app.models import VerificationRequest, VerificationResponse

class DomainVerificationError(Exception):
    """Custom exception for verification failures."""
    pass

class DomainVerifier:
    """Verifies widget presence on target domains using HEAD/GET requests."""

    def __init__(self, settings: Optional[Settings] = None):
        self.settings = settings or get_settings()
        self.cache: TTLCache = TTLCache(maxsize=1000, ttl=self.settings.VERIFY_CACHE_TTL)

    def _normalize_domain(self, url: str) -> str:
        """Extract clean domain from URL."""
        parsed = urlparse(url if url.startswith('http') else f"https://{url}")
        return parsed.netloc.lower()

    def _build_search_pattern(self, widget_id: str) -> re.Pattern:
        """Build regex pattern to find widget script in HTML."""
        # Look for data-widget-id attribute or script src containing widget ID
        escaped_id = re.escape(widget_id)
        pattern = rf'data-widget-id=["\']{escaped_id}["\']|src=["\'][^"\']*{escaped_id}[^"\']*["\']'
        return re.compile(pattern, re.IGNORECASE)

    async def verify_domain(self, request: VerificationRequest) -> VerificationResponse:
        """
        Verify if widget is live on target domain.
        Uses HEAD first, falls back to GET if needed.
        """
        domain = self._normalize_domain(str(request.domain))
        cache_key = f"{domain}:{request.widget_id}"

        # Check cache
        if cache_key in self.cache:
            return self.cache[cache_key]

        details: Dict[str, Any] = {
            "method_used": None,
            "response_time_ms": None,
            "content_length": None,
            "ssl_valid": True
        }

        is_live = False
        confidence = 0.0

        try:
            async with httpx.AsyncClient(
                timeout=self.settings.VERIFY_TIMEOUT,
                follow_redirects=True,
                limits=httpx.Limits(max_redirects=self.settings.VERIFY_MAX_REDIRECTS)
            ) as client:

                start_time = datetime.utcnow()

                # Try HEAD request first (lighter)
                try:
                    response = await client.head(f"https://{domain}", headers={
                        'User-Agent': 'WidgetBot/1.0 (Verification Bot)'
                    })
                    details["method_used"] = "HEAD"
                except (httpx.MethodNotAllowedError, httpx.HTTPStatusError):
                    # Fallback to GET if HEAD not allowed
                    response = await client.get(f"https://{domain}", headers={
                        'User-Agent': 'WidgetBot/1.0 (Verification Bot)'
                    })
                    details["method_used"] = "GET"

                elapsed = (datetime.utcnow() - start_time).total_seconds() * 1000
                details["response_time_ms"] = round(elapsed, 2)
                details["status_code"] = response.status_code

                if response.status_code == 200:
                    # Check headers for widget indicators
                    body_content = ""

                    if details["method_used"] == "GET":
                        body_content = response.text
                    else:
                        # For HEAD requests, we can't see body, so confidence is lower
                        confidence = 0.3

                    if body_content:
                        pattern = self._build_search_pattern(request.widget_id)
                        matches = pattern.findall(body_content)

                        if matches:
                            is_live = True
                            confidence = min(0.95, 0.5 + (0.1 * len(matches)))
                            details["matches_found"] = len(matches)

                            # Check for specific script src
                            cdn_domain = str(self.settings.CDN_BASE_URL).replace('https://', '')
                            if cdn_domain in body_content:
                                confidence = 0.99
                                details["cdn_verified"] = True

                else:
                    details["error"] = f"HTTP {response.status_code}"

        except httpx.TimeoutException:
            details["error"] = "Connection timeout"
            confidence = 0.0
        except httpx.SSLError:
            details["ssl_valid"] = False
            details["error"] = "SSL Certificate error"
            confidence = 0.0
        except Exception as e:
            details["error"] = str(e)
            confidence = 0.0

        result = VerificationResponse(
            is_live=is_live,
            domain=domain,
            widget_id=request.widget_id,
            checked_at=datetime.utcnow().isoformat(),
            details=details,
            confidence_score=confidence
        )

        # Cache result
        self.cache[cache_key] = result
        return result

    async def batch_verify(self, requests: list[VerificationRequest]) -> list[VerificationResponse]:
        """Verify multiple domains concurrently."""
        tasks = [self.verify_domain(req) for req in requests]
        return await asyncio.gather(*tasks, return_exceptions=True)
```

## 5. WordPress Plugin Generator (`app/services/wordpress.py`)

```python
"""Generator for WordPress plugin packages."""

import io
import zipfile
from typing import Dict, Any
from app.models import GenerateEmbedRequest

class WordPressGenerator:
    """Generates WordPress plugin files."""

    @staticmethod
    def generate_plugin_php(widget_id: str, config: Dict[str, Any]) -> str:
        """Generate main plugin PHP file."""
        return f"""<?php
/**
 * Plugin Name: Business Widget Embed
 * Description: Securely embed your custom widget
 * Version: 1.0.0
 * Author: Widget Service
 * Text Domain: widget-embed
 */

if (!defined('ABSPATH')) {{
    exit; // Exit if accessed directly
}}

class Widget_Embed_Plugin {{
    private static $instance = null;
    private $widget_id = '{widget_id}';

    public static function instance() {{
        if (null === self::$instance) {{
            self::$instance = new self();
        }}
        return self::$instance;
    }}

    public function __construct() {{
        add_shortcode('widget_embed', array($this, 'render_shortcode'));
        add_action('wp_enqueue_scripts', array($this, 'register_scripts'));
    }}

    public function register_scripts() {{
        wp_register_script(
            'widget-cdn',
            'https://cdn.widget-service.com/widget.js',
            array(),
            '1.0.0',
            true
        );
    }}

    public function render_shortcode($atts) {{
        $atts = shortcode_atts(array(
            'id' => $this->widget_id,
            'styles' => '',
            'class' => ''
        ), $atts, 'widget_embed');

        // Sanitize attributes
        $id = sanitize_text_field($atts['id']);
        $class = sanitize_html_class($atts['class']);

        // Decode base64 styles if present
        $styles = '';
        if (!empty($atts['styles'])) {{
            $decoded = base64_decode($atts['styles'], true);
            if ($decoded !== false) {{
                $styles = esc_attr($decoded);
            }}
        }}

        wp_enqueue_script('widget-cdn');

        ob_start();
        ?>
        <div class="widget-container <?php echo esc_attr($class); ?>">
            <script
                data-widget-id="<?php echo esc_attr($id); ?>"
                <?php if ($styles): ?>
                data-style-overrides="<?php echo $styles; ?>"
                <?php endif; ?>
            ></script>
        </div>
        <?php
        return ob_get_clean();
    }}
}}

Widget_Embed_Plugin::instance();
"""

    @staticmethod
    def generate_readme() -> str:
        """Generate WordPress readme.txt."""
        return """=== Business Widget Embed ===
Contributors: widgetservice
Tags: widget, embed, business
Requires at least: 5.0
Tested up to: 6.4
Stable tag: 1.0.0
License: GPLv2 or later

Automatically embed your business widget with a simple shortcode.

== Description ==
This plugin provides a secure way to embed your custom widget.

Usage:
[widget_embed]

With custom styles:
[widget_embed styles="eyJjb2xvciI6IiMwMDAwMDAifQ=="]

== Installation ==
1. Upload plugin files to /wp-content/plugins/widget-embed/
2. Activate through the 'Plugins' menu
3. Use shortcode [widget_embed] in posts or pages
"""

    def create_plugin_zip(self, request: GenerateEmbedRequest) -> io.BytesIO:
        """Create WordPress plugin zip package."""
        zip_buffer = io.BytesIO()

        with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
            # Main plugin file
            php_content = self.generate_plugin_php(
                request.widget_id,
                request.dict()
            )
            zip_file.writestr('widget-embed/widget-embed.php', php_content)

            # Readme
            zip_file.writestr('widget-embed/readme.txt', self.generate_readme())

            # Security file
            zip_file.writestr('widget-embed/index.php', '<?php // Silence is golden')

        zip_buffer.seek(0)
        return zip_buffer
```

## 6. API Routes (`app/api/routes.py`)

```python
"""FastAPI route handlers with comprehensive error handling."""

from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks, Query
from fastapi.responses import HTMLResponse, StreamingResponse
from typing import Optional
import logging

from app.models import (
    GenerateEmbedRequest,
    EmbedResponse,
    VerificationRequest,
    VerificationResponse,
    WordPressPluginResponse
)
from app.services.embed_generator import EmbedGenerator, EmbedGenerationError
from app.services.domain_verifier import DomainVerifier, DomainVerificationError
from app.services.wordpress import WordPressGenerator

router = APIRouter(prefix="/api/admin/widget", tags=["Widget Admin"])
logger = logging.getLogger(__name__)

@router.post(
    "/generate-embed",
    response_model=EmbedResponse,
    summary="Generate embed code for widget",
    response_description="HTML snippet and metadata"
)
async def generate_embed(
    request: GenerateEmbedRequest,
    generator: EmbedGenerator = Depends()
) -> EmbedResponse:
    """
    Generate secure HTML embed code for widget installation.

    - **widget_id**: Unique identifier for the widget
    - **target_domain**: Optional domain for verification purposes
    - **style_overrides**: CSS customization options
    - **format_type**: Output format (standard, async, wordpress, iframe)
    """
    try:
        result = generator.create_embed(request)
        logger.info(f"Generated embed for widget {request.widget_id}, format {request.format_type}")
        return result

    except EmbedGenerationError as e:
        logger.error(f"Embed generation failed: {e}")
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(f"Unexpected error in embed generation: {e}")
        raise HTTPException(status_code=500, detail="Internal server error")

@router.get(
    "/preview",
    response_class=HTMLResponse,
    summary="Preview widget in isolated iframe"
)
async def preview_widget(
    widget_id: str = Query(..., min_length=8),
    cdn_version: str = "latest",
    generator: EmbedGenerator = Depends()
):
    """
    Generate isolated HTML page for widget preview.
    Safe to embed in iframes on admin dashboards.
    """
    try:
        request = GenerateEmbedRequest(
            widget_id=widget_id,
            cdn_version=cdn_version,
            format_type="iframe"
        )
        html_content = generator.generate_iframe_preview(request)

        return HTMLResponse(
            content=html_content,
            headers={
                "X-Frame-Options": "SAMEORIGIN",  # Prevent clickjacking
                "Content-Security-Policy": "default-src 'self' https://cdn.widget-service.com; script-src 'self' 'unsafe-inline' https://cdn.widget-service.com;"
            }
        )

    except Exception as e:
        logger.error(f"Preview generation failed: {e}")
        return HTMLResponse(
            content=f"<html><body><h1>Preview Error</h1><p>{str(e)}</p></body></html>",
            status_code=500
        )

@router.post(
    "/verify",
    response_model=VerificationResponse,
    summary="Verify widget is live on domain"
)
async def verify_installation(
    request: VerificationRequest,
    background_tasks: BackgroundTasks,
    verifier: DomainVerifier = Depends()
):
    """
    Verify that the widget script is present on the target domain.
    Uses HEAD request with fallback to GET for detection.
    """
    try:
        result = await verifier.verify_domain(request)

        # Log verification attempt
        logger.info(
            f"Verification check: {request.domain} - Live: {result.is_live} "
            f"(Confidence: {result.confidence_score})"
        )

        return result

    except DomainVerificationError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(f"Verification error: {e}")
        raise HTTPException(status_code=500, detail="Verification service unavailable")

@router.get(
    "/wordpress-plugin",
    response_class=StreamingResponse,
    summary="Download WordPress plugin package"
)
async def download_wordpress_plugin(
    widget_id: str = Query(...),
    cdn_version: str = "latest"
):
    """
    Generate and download WordPress plugin as ZIP file.
    Includes secure shortcode handling and attribute sanitization.
    """
    try:
        request = GenerateEmbedRequest(
            widget_id=widget_id,
            cdn_version=cdn_version,
            format_type="wordpress"
        )

        generator = WordPressGenerator()
        zip_buffer = generator.create_plugin_zip(request)

        return StreamingResponse(
            zip_buffer,
            media_type="application/zip",
            headers={
                "Content-Disposition": f"attachment; filename=widget-embed-{widget_id}.zip"
            }
        )

    except Exception as e:
        logger.error(f"WordPress plugin generation failed: {e}")
        raise HTTPException(status_code=500, detail="Plugin generation failed")
```

## 7. Main Application (`app/main.py`)

```python
"""FastAPI application factory with security middleware."""

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded

from app.api.routes import router
from app.config import get_settings

settings = get_settings()

# Rate limiter
limiter = Limiter(key_func=get_remote_address)

def create_application() -> FastAPI:
    """Application factory pattern."""
    app = FastAPI(
        title="Widget Embed API",
        description="Production-grade widget embed code generation service",
        version=settings.API_VERSION,
        docs_url="/api/docs" if settings.DEBUG else None,
        redoc_url="/api/redoc" if settings.DEBUG else None,
    )

    # Security middleware
    app.state.limiter = limiter
    app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

    app.add_middleware(
        TrustedHostMiddleware,
        allowed_hosts=settings.ALLOWED_DOMAINS or ["*"]
    )

    app.add_middleware(
        CORSMiddleware,
        allow_origins=["https://admin.widget-service.com"] if not settings.DEBUG else ["*"],
        allow_credentials=True,
        allow_methods=["POST", "GET"],
        allow_headers=["*"],
    )

    # Include routes
    app.include_router(router)

    @app.get("/health")
    async def health_check():
        return {"status": "healthy", "version": settings.API_VERSION}

    return app

app = create_application()
```

## 8. Template (`templates/embed_script.html`)

```html
<!-- Secure Jinja2 template for embed code generation -->
<script
    src="{{ script_url | e }}"
    {% if async_loading %}async{% endif %}
    {% if defer_loading %}defer{% endif %}
    {% for key, value in data_attributes.items() %}
    {{ key | e }}="{{ value | e }}"
    {% endfor %}
    crossorigin="anonymous"
    integrity="{{ config_hash | default('') }}"
></script>
{% if style_config %}
<style>
    /* Widget container base styles */
    #widget-{{ data_attributes['data-widget-id'] | e }} {
        all: initial;
    }
</style>
{% endif %}
```

## 9. Test Suite (`tests/test_embed.py`)

```python
"""Comprehensive test suite for embed generator."""

import pytest
from fastapi.testclient import TestClient
from app.main import create_application
from app.services.embed_generator import EmbedGenerator
from app.models import GenerateEmbedRequest, StyleOverrides

@pytest.fixture
def client():
    app = create_application()
    return TestClient(app)

class TestEmbedGeneration:
    """Black box tests for embed generation."""

    def test_generate_standard_embed(self, client):
        """Test basic embed generation."""
        response = client.post("/api/admin/widget/generate-embed", json={
            "widget_id": "test12345",
            "format_type": "standard"
        })

        assert response.status_code == 200
        data = response.json()
        assert "script" in data["html_code"].lower()
        assert 'data-widget-id="test12345"' in data["html_code"]
        assert "cdn.widget-service.com" in data["script_url"]

    def test_xss_prevention_in_widget_id(self, client):
        """Verify special characters are escaped."""
        malicious_id = "test\"><script>alert('xss')</script>"

        response = client.post("/api/admin/widget/generate-embed", json={
            "widget_id": malicious_id,
            "format_type": "standard"
        })

        # Should either reject or escape
        assert response.status_code in [200, 422]
        if response.status_code == 200:
            html = response.json()["html_code"]
            assert "<script>alert" not in html
            assert "<script>" in html or "alert" not in html

    def test_style_injection_prevention(self, client):
        """Test CSS injection attempts are blocked."""
        response = client.post("/api/admin/widget/generate-embed", json={
            "widget_id": "valid123",
            "style_overrides": {
                "primary_color": "#ff0000; background: url('evil')"
            }
        })

        # Should reject malicious CSS
        assert response.status_code == 422

class TestDomainVerification:
    """White box tests for verification logic."""

    @pytest.mark.asyncio
    async def test_verification_uses_head_request(self, mocker):
        """Verify HEAD request is used for efficiency."""
        import httpx
        mock_head = mocker.patch('httpx.AsyncClient.head')
        mock_head.return_value = mocker.Mock(status_code=200)

        from app.services.domain_verifier import DomainVerifier
        verifier = DomainVerifier()

        # Mock settings
        verifier.settings.VERIFY_TIMEOUT = 5

        request = VerificationRequest(
            domain="https://example.com",
            widget_id="test123"
        )

        await verifier.verify_domain(request)
        mock_head.assert_called_once()

    def test_cdn_url_validation(self):
        """Ensure script URL uses HTTPS CDN."""
        generator = EmbedGenerator()
        request = GenerateEmbedRequest(widget_id="test123")

        url = generator._build_script_url("latest", "test123")
        assert url.startswith("https://")
        assert "cdn.widget-service.com" in url

class TestWordPressGeneration:
    """Tests for WordPress plugin format."""

    def test_wordpress_shortcode_format(self, client):
        """Test WordPress shortcode generation."""
        response = client.post("/api/admin/widget/generate-embed", json={
            "widget_id": "biz_widget_1",
            "format_type": "wordpress"
        })

        assert response.status_code == 200
        html = response.json()["html_code"]
        assert "[widget_embed" in html
        assert 'id="biz_widget_1"' in html

    def test_wordpress_plugin_download(self, client):
        """Test ZIP file generation."""
        response = client.get(
            "/api/admin/widget/wordpress-plugin?widget_id=test123"
        )

        assert response.status_code == 200
        assert response.headers["content-type"] == "application/zip"
        assert "widget-embed-test123.zip" in response.headers["content-disposition"]
```

## Key Security Features

1. **HTML Escaping**: All user inputs are escaped using Jinja2's `| e` filter and Python's `html.escape()`
2. **CSS Injection Prevention**: Style overrides validate against regex patterns and block dangerous characters (`;`, `{`, `}`)
3. **XSS Protection**: Widget IDs restricted to alphanumeric + hyphen/underscore only
4. **CSP Headers**: Preview endpoints use strict Content Security Policies
5. **HMAC Verification**: Security hashes prevent tampering with embed codes
6. **Rate Limiting**: Slowapi integration prevents abuse of generation endpoints
7. **SSRF Protection**: Domain verification uses strict timeout and redirect limits

## Usage Examples

```bash
# Generate standard embed
curl -X POST "http://localhost:8000/api/admin/widget/generate-embed" \
  -H "Content-Type: application/json" \
  -d '{
    "widget_id": "biz_12345",
    "target_domain": "https://example.com",
    "style_overrides": {"primary_color": "#ff0000"},
    "format_type": "async"
  }'

# Verify installation
curl -X POST "http://localhost:8000/api/admin/widget/verify" \
  -d '{
    "domain": "https://example.com",
    "widget_id": "biz_12345"
  }'

# Download WordPress plugin
curl -OJ "http://localhost:8000/api/admin/widget/wordpress-plugin?widget_id=biz_12345"
```

This implementation provides a robust, secure, and scalable solution for widget embed code generation with comprehensive error handling, input validation, and production-ready security measures.