"""Pulls aggregated conversion-event metrics from Google Analytics 4."""

import os
import sys
from pathlib import Path

from google.analytics.data_v1beta import BetaAnalyticsDataClient
from google.analytics.data_v1beta.types import (
    DateRange,
    Dimension,
    Metric,
    OrderBy,
    RunReportRequest,
)

from models import GA4ConversionRow

GA4_SCOPES = ["https://www.googleapis.com/auth/analytics.readonly"]


def fetch_conversion_breakdown(config: dict) -> list[GA4ConversionRow]:
    """Pull conversion event counts broken down by source / medium / campaign.

    Uses the GA4 `conversions` metric, which counts only events flagged as key events
    in the GA4 property — so we don't need a per-event allowlist in config. Rows where
    `conversions == 0` are filtered out before returning.

    Auth: prefers `ga4-token.json` (OAuth user creds, generated by `auth_ga4.py`).
    Falls back to the service-account JSON for setups where the service account is
    actually granted access to the GA4 property. Returns [] (with a warning) when
    neither works, so the rest of the pipeline can still run.
    """
    ga4_config = config.get("ga4", {})
    property_id = ga4_config.get("property_id")
    if not property_id:
        print(
            "GA4: skipping (ga4.property_id is not set in config.yaml).",
            file=sys.stderr,
            flush=True,
        )
        return []

    creds = _load_credentials()
    if creds is None:
        print(
            "GA4: skipping (no usable credentials — run auth_ga4.py to set up "
            "OAuth user creds, or grant GA4 access to the service account).",
            file=sys.stderr,
            flush=True,
        )
        return []

    lookback_days = ga4_config.get("lookback_days", 365)
    print(
        f"Fetching GA4 conversion breakdown for property {property_id}, "
        f"last {lookback_days} days...",
        file=sys.stderr,
        flush=True,
    )

    try:
        client = BetaAnalyticsDataClient(credentials=creds)
    except Exception as e:
        print(
            f"GA4: skipping (could not initialize client: {e}).",
            file=sys.stderr,
            flush=True,
        )
        return []

    request = RunReportRequest(
        property=f"properties/{property_id}",
        dimensions=[
            Dimension(name="eventName"),
            Dimension(name="sessionSource"),
            Dimension(name="sessionMedium"),
            Dimension(name="sessionCampaignName"),
        ],
        metrics=[
            Metric(name="eventCount"),
            Metric(name="conversions"),
            Metric(name="sessions"),
        ],
        date_ranges=[
            DateRange(start_date=f"{lookback_days}daysAgo", end_date="today")
        ],
        order_bys=[
            OrderBy(
                metric=OrderBy.MetricOrderBy(metric_name="conversions"),
                desc=True,
            )
        ],
        limit=100000,
    )
    try:
        response = client.run_report(request)
    except Exception as e:
        print(
            f"GA4: skipping (run_report failed, likely missing GA4 property access: {e}).",
            file=sys.stderr,
            flush=True,
        )
        return []

    rows: list[GA4ConversionRow] = []
    for r in response.rows:
        conversions = float(r.metric_values[1].value)
        if conversions == 0:
            continue
        rows.append(
            GA4ConversionRow(
                event_name=r.dimension_values[0].value,
                source=r.dimension_values[1].value,
                medium=r.dimension_values[2].value,
                campaign=r.dimension_values[3].value,
                event_count=int(r.metric_values[0].value),
                conversions=conversions,
                sessions=int(r.metric_values[2].value),
            )
        )

    print(
        f"  {len(rows)} rows with conversions returned.",
        file=sys.stderr,
        flush=True,
    )
    return rows


def _load_credentials():
    """Try OAuth user credentials first; fall back to service account; else None."""
    from google.auth.transport.requests import Request
    from google.oauth2.credentials import Credentials as UserCreds

    token_path = os.environ.get("GA4_TOKEN_JSON", "ga4-token.json")
    if os.path.exists(token_path):
        try:
            creds = UserCreds.from_authorized_user_file(token_path, GA4_SCOPES)
            if creds.expired and creds.refresh_token:
                creds.refresh(Request())
                Path(token_path).write_text(creds.to_json())
            return creds
        except Exception as e:
            print(
                f"GA4: could not load OAuth token from {token_path}: {e}",
                file=sys.stderr,
                flush=True,
            )

    sa_path = os.environ.get("GOOGLE_SERVICE_ACCOUNT_JSON")
    if sa_path and os.path.exists(sa_path):
        from google.oauth2 import service_account

        return service_account.Credentials.from_service_account_file(
            sa_path, scopes=GA4_SCOPES
        )

    return None


if __name__ == "__main__":
    import json
    from dataclasses import asdict

    import yaml
    from dotenv import load_dotenv

    load_dotenv()
    with open("config.yaml") as f:
        config = yaml.safe_load(f)
    rows = fetch_conversion_breakdown(config)
    print(f"\nFetched {len(rows)} GA4 conversion rows.")
    if rows:
        print("Top 5 by conversion count:")
        for row in rows[:5]:
            print(json.dumps(asdict(row), indent=2))
