"""Google Search Console sync via Search Analytics API.

Uses a service account JSON key file for auth. The google-api-python-client
is synchronous, so sync runs in asyncio.to_thread().
"""

import asyncio
from datetime import timedelta
from pathlib import Path
from urllib.parse import urlparse

from ..core import config, execute, utcnow, utcnow_iso

# GSC returns max 25K rows per request
_ROWS_PER_PAGE = 25_000


def _fetch_gsc_data(
    start_date: str,
    end_date: str,
    max_pages: int,
) -> list[dict]:
    """Synchronous GSC fetch — called via asyncio.to_thread().

    Returns list of dicts with keys: date, page, query, country, device,
    clicks, impressions, ctr, position.
    """
    from google.oauth2.service_account import Credentials
    from googleapiclient.discovery import build

    key_path = Path(config.GSC_SERVICE_ACCOUNT_PATH)
    assert key_path.exists(), f"GSC service account key not found: {key_path}"

    credentials = Credentials.from_service_account_file(
        str(key_path),
        scopes=["https://www.googleapis.com/auth/webmasters.readonly"],
    )
    service = build("searchconsole", "v1", credentials=credentials)

    all_rows = []
    start_row = 0

    for _page_num in range(max_pages):
        body = {
            "startDate": start_date,
            "endDate": end_date,
            "dimensions": ["date", "page", "query", "country", "device"],
            "rowLimit": _ROWS_PER_PAGE,
            "startRow": start_row,
        }
        response = service.searchanalytics().query(
            siteUrl=config.GSC_SITE_URL,
            body=body,
        ).execute()

        rows = response.get("rows", [])
        if not rows:
            break

        for row in rows:
            keys = row["keys"]
            all_rows.append({
                "date": keys[0],
                "page": keys[1],
                "query": keys[2],
                "country": keys[3],
                "device": keys[4],
                "clicks": row.get("clicks", 0),
                "impressions": row.get("impressions", 0),
                "ctr": row.get("ctr", 0.0),
                "position": row.get("position", 0.0),
            })

        if len(rows) < _ROWS_PER_PAGE:
            break
        start_row += _ROWS_PER_PAGE

    return all_rows


def _normalize_url(full_url: str) -> str:
    """Strip a full URL to just the path (no domain).

    Example: 'https://padelnomics.io/en/markets/germany/berlin' → '/en/markets/germany/berlin'
    """
    parsed = urlparse(full_url)
    return parsed.path or "/"


async def sync_gsc(days_back: int = 3, max_pages: int = 10) -> int:
    """Sync GSC search analytics into seo_search_metrics. Returns rows synced."""
    assert 1 <= days_back <= 90, "days_back must be 1-90"
    assert 1 <= max_pages <= 20, "max_pages must be 1-20"

    if not config.GSC_SERVICE_ACCOUNT_PATH or not config.GSC_SITE_URL:
        return 0  # GSC not configured — skip silently

    started_at = utcnow()

    # GSC has ~2 day delay; fetch from days_back ago to 2 days ago
    end_date = (utcnow() - timedelta(days=2)).strftime("%Y-%m-%d")
    start_date = (utcnow() - timedelta(days=days_back + 2)).strftime("%Y-%m-%d")

    try:
        rows = await asyncio.to_thread(
            _fetch_gsc_data, start_date, end_date, max_pages,
        )

        rows_synced = 0
        for row in rows:
            page_url = _normalize_url(row["page"])
            await execute(
                """INSERT OR REPLACE INTO seo_search_metrics
                   (source, metric_date, page_url, query, country, device,
                    clicks, impressions, ctr, position_avg)
                   VALUES ('gsc', ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
                (
                    row["date"], page_url, row["query"], row["country"],
                    row["device"], row["clicks"], row["impressions"],
                    row["ctr"], row["position"],
                ),
            )
            rows_synced += 1

        duration_ms = int((utcnow() - started_at).total_seconds() * 1000)
        await execute(
            """INSERT INTO seo_sync_log
               (source, status, rows_synced, started_at, completed_at, duration_ms)
               VALUES ('gsc', 'success', ?, ?, ?, ?)""",
            (rows_synced, started_at.strftime("%Y-%m-%d %H:%M:%S"), utcnow_iso(), duration_ms),
        )
        return rows_synced

    except Exception as exc:
        duration_ms = int((utcnow() - started_at).total_seconds() * 1000)
        await execute(
            """INSERT INTO seo_sync_log
               (source, status, rows_synced, error, started_at, completed_at, duration_ms)
               VALUES ('gsc', 'failed', 0, ?, ?, ?, ?)""",
            (str(exc), started_at.strftime("%Y-%m-%d %H:%M:%S"), utcnow_iso(), duration_ms),
        )
        raise
