"""
Banner consent analytics — time-series, device breakdown, bounce rate.

Reads from BannerConsentAuditLogDB for aggregated analytics.
"""

import re
from datetime import datetime, timedelta, timezone
from typing import Any, Optional

from sqlalchemy import text
from sqlalchemy.orm import Session


class BannerAnalyticsService:
    """Provides aggregated consent analytics for a site."""

    def __init__(self, db: Session) -> None:
        self.db = db

    def get_time_series(
        self,
        tenant_id: str,
        site_id: str,
        period: str = "daily",
        days: int = 30,
    ) -> list[dict[str, Any]]:
        """Opt-in rate per day/week over the last N days."""
        trunc = "day" if period == "daily" else "week"
        cutoff = datetime.now(timezone.utc) - timedelta(days=days)
        q = text(f"""
            SELECT DATE_TRUNC(:trunc, created_at) AS period,
                   COUNT(*) FILTER (WHERE action = 'consent_given') AS given,
                   COUNT(*) FILTER (WHERE action = 'consent_updated') AS updated,
                   COUNT(*) FILTER (WHERE action IN ('consent_withdrawn', 'consent_revoked')) AS withdrawn,
                   COUNT(*) AS total
            FROM compliance_banner_consent_audit_log
            WHERE tenant_id = :tid AND site_id = :sid AND created_at >= :cutoff
            GROUP BY 1 ORDER BY 1
        """)
        rows = self.db.execute(q, {"tid": tenant_id, "sid": site_id, "cutoff": cutoff, "trunc": trunc}).fetchall()
        return [
            {
                "period": r.period.isoformat() if r.period else None,
                "given": r.given,
                "updated": r.updated,
                "withdrawn": r.withdrawn,
                "total": r.total,
                "opt_in_rate": round((r.given + r.updated) / r.total * 100, 1) if r.total > 0 else 0,
            }
            for r in rows
        ]

    def get_category_breakdown(
        self,
        tenant_id: str,
        site_id: str,
        days: int = 30,
    ) -> dict[str, dict[str, int]]:
        """Acceptance count per category."""
        cutoff = datetime.now(timezone.utc) - timedelta(days=days)
        q = text("""
            SELECT categories FROM compliance_banner_consent_audit_log
            WHERE tenant_id = :tid AND site_id = :sid AND created_at >= :cutoff
              AND action IN ('consent_given', 'consent_updated')
        """)
        rows = self.db.execute(q, {"tid": tenant_id, "sid": site_id, "cutoff": cutoff}).fetchall()
        counts: dict[str, int] = {}
        total = len(rows)
        for r in rows:
            cats = r.categories if isinstance(r.categories, list) else []
            for cat in cats:
                counts[cat] = counts.get(cat, 0) + 1
        return {
            cat: {"count": count, "total": total, "rate": round(count / total * 100, 1) if total > 0 else 0}
            for cat, count in sorted(counts.items())
        }

    def get_device_breakdown(
        self,
        tenant_id: str,
        site_id: str,
        days: int = 30,
    ) -> dict[str, int]:
        """Mobile/Desktop/Tablet classification from user_agent."""
        cutoff = datetime.now(timezone.utc) - timedelta(days=days)
        q = text("""
            SELECT user_agent FROM compliance_banner_consent_audit_log
            WHERE tenant_id = :tid AND site_id = :sid AND created_at >= :cutoff
              AND user_agent IS NOT NULL
        """)
        rows = self.db.execute(q, {"tid": tenant_id, "sid": site_id, "cutoff": cutoff}).fetchall()
        result = {"desktop": 0, "mobile": 0, "tablet": 0, "unknown": 0}
        mobile_re = re.compile(r"Mobile|Android|iPhone|iPod", re.IGNORECASE)
        tablet_re = re.compile(r"iPad|Tablet|PlayBook|Silk", re.IGNORECASE)
        for r in rows:
            ua = r.user_agent or ""
            if tablet_re.search(ua):
                result["tablet"] += 1
            elif mobile_re.search(ua):
                result["mobile"] += 1
            elif ua:
                result["desktop"] += 1
            else:
                result["unknown"] += 1
        return result

    def get_overview_stats(
        self,
        tenant_id: str,
        site_id: str,
        days: int = 30,
    ) -> dict[str, Any]:
        """High-level stats: total consents, active, withdrawn, opt-in rate."""
        cutoff = datetime.now(timezone.utc) - timedelta(days=days)
        q = text("""
            SELECT
                COUNT(*) FILTER (WHERE action = 'consent_given') AS given,
                COUNT(*) FILTER (WHERE action = 'consent_updated') AS updated,
                COUNT(*) FILTER (WHERE action IN ('consent_withdrawn', 'consent_revoked')) AS withdrawn,
                COUNT(*) AS total
            FROM compliance_banner_consent_audit_log
            WHERE tenant_id = :tid AND site_id = :sid AND created_at >= :cutoff
        """)
        r = self.db.execute(q, {"tid": tenant_id, "sid": site_id, "cutoff": cutoff}).fetchone()
        total = r.total if r else 0
        given = (r.given or 0) + (r.updated or 0) if r else 0
        return {
            "period_days": days,
            "total_interactions": total,
            "consents_given": r.given if r else 0,
            "consents_updated": r.updated if r else 0,
            "consents_withdrawn": r.withdrawn if r else 0,
            "opt_in_rate": round(given / total * 100, 1) if total > 0 else 0,
        }
