"""Canonical URL deduplication using GSC impressions from wordlift-sdk."""

from __future__ import annotations

import json
from dataclasses import dataclass
from pathlib import Path
from typing import TYPE_CHECKING

from google.auth.credentials import Credentials
from google.auth.transport.requests import Request
from google.oauth2 import service_account

from worai.core.gsc import load_credentials
from worai.errors import UsageError

if TYPE_CHECKING:  # pragma: no cover
    import pandas as pd

WEBMASTERS_READONLY_SCOPE = "https://www.googleapis.com/auth/webmasters.readonly"

_AUTH_HELP_MESSAGE = """Authentication is missing.

Provide one of:
1) --service-account <path-or-json>   (recommended for CI/non-interactive)
2) --client-secrets <client.json>     (to bootstrap OAuth token)
3) --token <oauth_token.json>         (if already created and valid)

How to create credentials:
- Search Console API auth requirements:
  https://developers.google.com/webmaster-tools/v1/how-tos/authorizing
- Create OAuth client (Desktop app):
  https://developers.google.com/workspace/guides/create-credentials
- Create service account:
  https://cloud.google.com/iam/docs/service-accounts-create
- Add account to Search Console property permissions:
  https://support.google.com/webmasters/answer/7687615
"""


@dataclass
class CanonicalsDedupeOptions:
    input_csv: str
    output_csv: str
    site_url: str
    interval: str = "28d"
    url_regex: str | None = None
    concurrency: str = "auto"
    request_timeout_sec: float = 30.0
    service_account: str | None = None
    client_secrets: str | None = None
    token: str = "oauth_token.json"
    oauth_port: int = 8080


def _load_oauth_credentials(token_path: str, client_secrets: str | None, port: int) -> Credentials:
    token = Path(token_path)
    if token.exists():
        from wordlift_sdk.google_search_console import load_authorized_user_credentials

        try:
            creds = load_authorized_user_credentials(token)
            if creds.expired and creds.refresh_token:
                creds.refresh(Request())
                token.write_text(creds.to_json(), encoding="utf-8")
            if creds.valid:
                return creds
        except Exception:
            pass

    if not client_secrets:
        raise UsageError(_AUTH_HELP_MESSAGE)
    return load_credentials(client_secrets, token_path, port)


def _load_service_account_credentials(service_account_value: str) -> Credentials:
    as_path = Path(service_account_value)
    if as_path.exists():
        return service_account.Credentials.from_service_account_file(
            str(as_path),
            scopes=[WEBMASTERS_READONLY_SCOPE],
        )
    try:
        info = json.loads(service_account_value)
    except json.JSONDecodeError as exc:
        raise UsageError(
            "--service-account must be a valid file path or a JSON body."
        ) from exc
    if not isinstance(info, dict):
        raise UsageError("--service-account JSON must be an object.")
    return service_account.Credentials.from_service_account_info(
        info,
        scopes=[WEBMASTERS_READONLY_SCOPE],
    )


def run_dedupe(options: CanonicalsDedupeOptions) -> "pd.DataFrame":
    from wordlift_sdk.google_search_console import create_canonical_csv_from_gsc_impressions

    if options.service_account:
        credentials = _load_service_account_credentials(options.service_account)
        return create_canonical_csv_from_gsc_impressions(
            input_csv=options.input_csv,
            output_csv=options.output_csv,
            site_url=options.site_url,
            credentials=credentials,
            interval=options.interval,
            url_regex=options.url_regex,
            concurrency=options.concurrency,
            request_timeout_sec=options.request_timeout_sec,
        )

    credentials = _load_oauth_credentials(
        token_path=options.token,
        client_secrets=options.client_secrets,
        port=options.oauth_port,
    )
    return create_canonical_csv_from_gsc_impressions(
        input_csv=options.input_csv,
        output_csv=options.output_csv,
        site_url=options.site_url,
        credentials=credentials,
        interval=options.interval,
        url_regex=options.url_regex,
        concurrency=options.concurrency,
        request_timeout_sec=options.request_timeout_sec,
    )
