"""Pydantic schemas for the Visitor Monitor admin + public endpoints."""

from __future__ import annotations

from datetime import datetime
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, Field


# ---------------------------------------------------------------------------
# Public tracking ingest
# ---------------------------------------------------------------------------


class TrackPageviewIn(BaseModel):
    """Payload from the frontend `useVisitorTracking` hook on route change."""

    session_id: str = Field(..., min_length=6, max_length=64)
    page: str = Field(..., max_length=500)
    referrer: Optional[str] = Field(default=None, max_length=1000)
    utm_source: Optional[str] = Field(default=None, max_length=100)
    utm_medium: Optional[str] = Field(default=None, max_length=100)
    utm_campaign: Optional[str] = Field(default=None, max_length=100)
    utm_term: Optional[str] = Field(default=None, max_length=100)
    utm_content: Optional[str] = Field(default=None, max_length=100)
    screen: Optional[str] = Field(default=None, max_length=40)


class TrackEventIn(BaseModel):
    session_id: str = Field(..., min_length=6, max_length=64)
    event_type: str = Field(..., min_length=1, max_length=30)
    label: Optional[str] = Field(default=None, max_length=255)
    page: Optional[str] = Field(default=None, max_length=500)
    metadata: Optional[Dict[str, Any]] = None


class TrackAck(BaseModel):
    ok: bool = True
    excluded: bool = False


# ---------------------------------------------------------------------------
# Admin: sessions / live
# ---------------------------------------------------------------------------


class SessionItem(BaseModel):
    id: int
    session_id: str
    visitor_id: Optional[str] = None
    user_id: Optional[str] = None
    ip_address: Optional[str] = None
    country: Optional[str] = None
    city: Optional[str] = None
    device: Optional[str] = None
    browser: Optional[str] = None
    os: Optional[str] = None
    referrer: Optional[str] = None
    landing_page: Optional[str] = None
    current_page: Optional[str] = None
    utm_source: Optional[str] = None
    utm_medium: Optional[str] = None
    utm_campaign: Optional[str] = None
    pageview_count: int
    conversion_stage: str
    started_at: datetime
    last_activity_at: datetime
    ended_at: Optional[datetime] = None
    is_online: bool = False
    duration_seconds: int = 0

    class Config:
        from_attributes = True


class SessionListResponse(BaseModel):
    items: List[SessionItem]
    total: int
    page: int
    page_size: int


# ---------------------------------------------------------------------------
# Admin: overview / analytics
# ---------------------------------------------------------------------------


class OverviewStats(BaseModel):
    total_visits: int
    unique_visitors: int
    campaign_clicks: int
    referral_clicks: int
    conversion_rate: float
    active_now: int


class BucketStat(BaseModel):
    key: str
    count: int


class DailyStat(BaseModel):
    date: str
    visits: int
    unique_visitors: int


class ReportResponse(BaseModel):
    by_day: List[DailyStat]
    by_source: List[BucketStat]
    by_campaign: List[BucketStat]
    by_device: List[BucketStat]
    by_browser: List[BucketStat]
    by_country: List[BucketStat]


# ---------------------------------------------------------------------------
# Admin: campaigns
# ---------------------------------------------------------------------------


class CampaignItem(BaseModel):
    id: int
    name: str
    utm_source: str
    utm_medium: Optional[str] = None
    utm_campaign: str
    utm_term: Optional[str] = None
    utm_content: Optional[str] = None
    landing_page: str
    target_url: Optional[str] = None
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None
    status: str
    notes: Optional[str] = None
    created_at: datetime
    updated_at: datetime
    # Aggregated stats (computed at read-time)
    total_clicks: int = 0
    unique_visitors: int = 0
    leads: int = 0
    signups: int = 0
    orders: int = 0
    conversions: int = 0
    referral_url: str = ""

    class Config:
        from_attributes = True


class CampaignCreate(BaseModel):
    name: str = Field(..., min_length=1, max_length=255)
    utm_source: str = Field(..., min_length=1, max_length=100)
    utm_medium: Optional[str] = Field(default=None, max_length=100)
    utm_campaign: str = Field(..., min_length=1, max_length=100)
    utm_term: Optional[str] = Field(default=None, max_length=100)
    utm_content: Optional[str] = Field(default=None, max_length=100)
    landing_page: str = Field(default="/", max_length=500)
    target_url: Optional[str] = Field(default=None, max_length=1000)
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None
    status: str = Field(default="active", pattern=r"^(active|paused|archived)$")
    notes: Optional[str] = None


class CampaignUpdate(BaseModel):
    name: Optional[str] = Field(default=None, max_length=255)
    utm_source: Optional[str] = Field(default=None, max_length=100)
    utm_medium: Optional[str] = Field(default=None, max_length=100)
    utm_campaign: Optional[str] = Field(default=None, max_length=100)
    utm_term: Optional[str] = Field(default=None, max_length=100)
    utm_content: Optional[str] = Field(default=None, max_length=100)
    landing_page: Optional[str] = Field(default=None, max_length=500)
    target_url: Optional[str] = Field(default=None, max_length=1000)
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None
    status: Optional[str] = Field(default=None, pattern=r"^(active|paused|archived)$")
    notes: Optional[str] = None


# ---------------------------------------------------------------------------
# Admin: journey
# ---------------------------------------------------------------------------


class JourneyEventItem(BaseModel):
    id: int
    event_type: str
    label: Optional[str] = None
    page: Optional[str] = None
    metadata: Optional[Dict[str, Any]] = None
    created_at: datetime


class JourneyResponse(BaseModel):
    session: SessionItem
    events: List[JourneyEventItem]


# ---------------------------------------------------------------------------
# Admin: settings
# ---------------------------------------------------------------------------


class TrackingSettingsOut(BaseModel):
    tracking_enabled: bool
    retention_days: int
    excluded_ips: List[str]
    exclude_staff: bool
    mask_sensitive: bool
    updated_at: Optional[datetime] = None


class TrackingSettingsUpdate(BaseModel):
    tracking_enabled: Optional[bool] = None
    retention_days: Optional[int] = Field(default=None, ge=1, le=3650)
    excluded_ips: Optional[List[str]] = None
    exclude_staff: Optional[bool] = None
    mask_sensitive: Optional[bool] = None