"""Dashboard context dataclasses — template rendering contexts.

Each dataclass corresponds to a page or partial template and carries
all data needed for a single render. Built in route handlers from
Firestore data, cached where possible.
"""

from __future__ import annotations

from dataclasses import dataclass


@dataclass
class DashboardProjectCard:
    """Rendered from Firestore customers/{id}/projects/{id} + latest_scan/ subdoc."""

    project_id: str
    project_label: str
    client_label: str | None
    cloud: str
    frameworks: list[str]
    status: str
    score: float | None
    score_delta: float | None
    passed: int
    failed: int
    severity_counts: dict[str, int]
    last_scan_at: str | None
    drift_monitoring: bool
    drift_mode: str | None
    drift_last_event_at: str | None
    has_cloud_intelligence: bool
    cross_validation_score: float | None


@dataclass
class PostureSummaryContext:
    """(SPEC-015) Aggregate posture bar.

    Zero additional Firestore reads except one scan_history read
    for 7-day-ago snapshot.
    """

    total_projects: int
    aggregate_score: float | None
    total_critical: int
    total_high: int
    total_medium: int
    total_low: int
    drift_events_24h: int
    worst_project_label: str | None
    worst_project_id: str | None
    worst_project_score: float | None
    score_trend: str


@dataclass
class ProjectsOverviewContext:
    """Template context for /dashboard/ index."""

    customer_email: str
    tier: str
    project_limit: int | None
    projects: list[DashboardProjectCard]
    active_count: int
    archived_count: int
    client_labels: list[str]
    selected_client: str | None
    posture: PostureSummaryContext
    show_consent_banner: bool
    tos_version: str
    privacy_version: str


@dataclass
class ProjectDetailContext:
    """Template context for /dashboard/projects/{project_id}."""

    customer_email: str
    tier: str
    project: DashboardProjectCard
    summary: dict[str, object]
    frameworks_detail: list[dict[str, object]]
    score_history: list[dict[str, object]]
    drift_events: list[dict[str, object]]
    active_tab: str
    theme_preference: str | None
    show_consent_banner: bool
    tos_version: str
    privacy_version: str


@dataclass
class SettingsContext:
    """Template context for /dashboard/settings."""

    customer_email: str
    tier: str
    status: str
    subscription_expires_at: str
    cancellation_pending: bool
    api_key_last4: str
    paddle_portal_url: str
    license_download_url: str
    bundle_download_url: str
    bundle_version: str
    show_consent_banner: bool
    tos_version: str
    privacy_version: str


@dataclass
class ScanDetailContext:
    """Template context for /dashboard/projects/{id}/scans/{scan_id}."""

    customer_email: str
    tier: str
    project: DashboardProjectCard
    scan_id: str
    scanned_at: str
    frameworks: list[str]
    score: float
    severity_counts: dict[str, int]
    can_share: bool
    shared_links_count: int
    theme_preference: str | None
    show_consent_banner: bool
    tos_version: str
    privacy_version: str


@dataclass
class LinkAccountContext:
    """Template context for /dashboard/link-account."""

    error: str | None


@dataclass
class CommandPaletteResult:
    """(SPEC-015) Single result in command palette search."""

    type: str
    icon: str
    label: str
    subtitle: str | None
    url: str


@dataclass
class ControlEntry:
    """(SPEC-015) Single control in controls view."""

    control_id: str
    control_title: str
    framework: str
    status: str
    resource_count: int
    failing_resources: int
    severity: str
    cross_mapped: list[str]
    evidence_summary: str | None


@dataclass
class ControlsViewContext:
    """(SPEC-015) Template context for controls partial."""

    project_id: str
    controls: list[ControlEntry]
    total_controls: int
    passing: int
    failing: int
    manual: int
    frameworks_available: list[str]
    selected_framework: str
    selected_status: str
    page: int
    total_pages: int


@dataclass
class SharedScanContext:
    """Template context for /dashboard/shared/{token} — no auth."""

    scan_id: str
    scanned_at: str
    project_label: str
    cloud: str
    frameworks: list[str]
    score: float
    severity_counts: dict[str, int]
    findings: list[dict[str, object]]
    scope: str
    password_required: bool


@dataclass
class MemberInfo:
    """Team member record from customers/{id}/members/{email_hash}."""

    email_hash: str
    email: str
    role: str  # "owner" | "admin" | "viewer"
    status: str  # "active" | "pending" | "removed"
    invited_by: str
    invited_at: str
    accepted_at: str | None
    last_accessed_at: str | None


@dataclass
class MembersContext:
    """Template context for /dashboard/settings/members."""

    members: list[MemberInfo]
    active_count: int
    pending_count: int
    member_limit: int | None  # None = unlimited
    can_invite: bool  # role in ("owner", "admin") AND under limit


@dataclass
class AuditLogEvent:
    """Single audit log entry from customers/{id}/audit_log/{auto_id}."""

    event_id: str
    event: str
    actor_email: str
    actor_role: str
    timestamp: str
    ip_hash: str
    metadata: dict[str, str | int | bool | None]


@dataclass
class AuditLogPage:
    """Cursor-paginated audit log results."""

    events: list[AuditLogEvent]
    next_cursor: str | None
    total_hint: int | None  # Approximate count for UI (optional)


@dataclass
class AuditLogContext:
    """Template context for /dashboard/audit-log."""

    page: AuditLogPage
    event_filter: str | None
    actor_filter: str | None
    start_date: str | None
    end_date: str | None
    actors: list[str]  # Distinct actor emails for filter dropdown
    event_types: list[str]  # All 16 event type strings for filter dropdown


@dataclass
class WebhookInfo:
    """Webhook endpoint record from customers/{id}/webhooks/{webhook_id}."""

    webhook_id: str
    url: str
    event_types: list[str]
    status: str  # "active" | "unhealthy" | "disabled"
    created_at: str
    last_delivery_at: str | None
    consecutive_failures: int
    signing_secret_last4: str  # Last 4 chars of raw secret (for display)
    raw_secret: str | None = None  # Only populated on create (one-time)


@dataclass
class WebhookDelivery:
    """Webhook delivery attempt from webhook_deliveries subcollection."""

    delivery_id: str
    webhook_id: str
    event_type: str
    status: str  # "success" | "failed"
    response_code: int | None
    attempted_at: str


@dataclass
class WebhooksContext:
    """Template context for /dashboard/settings/webhooks."""

    webhooks: list[WebhookInfo]
    webhook_limit: int  # Always 3
    can_create: bool  # role in ("owner", "admin") AND under limit
