"""
Google Business Profile Management API Client
==============================================

Uses OAuth 2.0 access tokens to access owner-specific GBP data
not available through the public Places API (e.g., owner responses to reviews, posts).

API docs: https://developers.google.com/my-business/reference/rest
"""

import logging
from typing import List, Dict, Optional

import requests

logger = logging.getLogger(__name__)


class GBPManagementService:
    """Google Business Profile Management API client."""

    ACCOUNT_MGMT_URL = "https://mybusinessaccountmanagement.googleapis.com/v1"
    BUSINESS_INFO_URL = "https://mybusinessbusinessinformation.googleapis.com/v1"

    def __init__(self, access_token: str):
        self.session = requests.Session()
        self.session.headers.update({
            'Authorization': f'Bearer {access_token}',
            'Content-Type': 'application/json',
        })
        self.session.timeout = 15

    def list_accounts(self) -> List[Dict]:
        """List all GBP accounts for the authenticated user."""
        try:
            resp = self.session.get(f"{self.ACCOUNT_MGMT_URL}/accounts")
            resp.raise_for_status()
            return resp.json().get('accounts', [])
        except Exception as e:
            logger.error(f"GBP list_accounts failed: {e}")
            return []

    def list_locations(self, account_name: str) -> List[Dict]:
        """List locations for a GBP account.

        Args:
            account_name: Full account resource name (e.g., 'accounts/123456')
        """
        try:
            resp = self.session.get(
                f"{self.BUSINESS_INFO_URL}/{account_name}/locations",
                params={'readMask': 'name,title,storefrontAddress,metadata'}
            )
            resp.raise_for_status()
            return resp.json().get('locations', [])
        except Exception as e:
            logger.error(f"GBP list_locations failed for {account_name}: {e}")
            return []

    def get_reviews(self, location_name: str, max_results: int = 50) -> List[Dict]:
        """Get reviews INCLUDING owner responses (reviewReply).

        This is the key advantage over Places API — reviewReply contains
        the business owner's response to each review.

        Args:
            location_name: Full location resource name (e.g., 'accounts/123/locations/456')
            max_results: Max reviews to return
        """
        try:
            reviews = []
            page_token = None
            while len(reviews) < max_results:
                params = {'pageSize': min(50, max_results - len(reviews))}
                if page_token:
                    params['pageToken'] = page_token
                resp = self.session.get(
                    f"{self.ACCOUNT_MGMT_URL}/{location_name}/reviews",
                    params=params
                )
                resp.raise_for_status()
                data = resp.json()
                reviews.extend(data.get('reviews', []))
                page_token = data.get('nextPageToken')
                if not page_token:
                    break
            return reviews
        except Exception as e:
            logger.error(f"GBP get_reviews failed for {location_name}: {e}")
            return []

    def get_local_posts(self, location_name: str) -> List[Dict]:
        """Get Google Posts for a location."""
        try:
            resp = self.session.get(
                f"{self.ACCOUNT_MGMT_URL}/{location_name}/localPosts",
                params={'pageSize': 20}
            )
            resp.raise_for_status()
            return resp.json().get('localPosts', [])
        except Exception as e:
            logger.error(f"GBP get_local_posts failed for {location_name}: {e}")
            return []

    def match_location_by_place_id(self, account_name: str, place_id: str) -> Optional[Dict]:
        """Find a location that matches a Google Place ID.

        Iterates locations and checks metadata.placeId.
        """
        locations = self.list_locations(account_name)
        for loc in locations:
            metadata = loc.get('metadata', {})
            if metadata.get('placeId') == place_id:
                return loc
        return None
