import json
import time
import logging
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import Flow
from googleapiclient.discovery import build
from google.auth.transport.requests import Request
from googleapiclient.errors import HttpError
from django.conf import settings
from django.utils import timezone
from apps.social.utils.google import SCOPES, API_VERSION_MYBUSINESS, API_VERSION_ACCOUNT_MGMT

logger = logging.getLogger(__name__)

class GoogleAPIError(Exception):
    pass

class GoogleBusinessService:

    @staticmethod
    def _get_credentials_object(account):
        creds_dict = account.credentials_json
        if 'token' not in creds_dict:
            raise GoogleAPIError("Missing token.")
        creds = Credentials.from_authorized_user_info(creds_dict, SCOPES)

        if creds.expired and creds.refresh_token:
            try:
                # FIX: Model field is 'name', not 'account_name'
                logger.info(f"Refreshing token for {account.name}...")
                creds.refresh(Request())
                account.credentials_json = json.loads(creds.to_json())
                account.save()
            except Exception as e:
                raise GoogleAPIError(f"Token refresh failed: {e}")
        return creds

    @staticmethod
    def get_service(account, api_name='mybusiness', api_version='v4'):
        creds = GoogleBusinessService._get_credentials_object(account)
        return build(api_name, api_version, credentials=creds)

    @staticmethod
    def get_auth_url(request):
        flow = Flow.from_client_secrets_file(
            settings.GMB_CLIENT_SECRETS_FILE,
            scopes=SCOPES,
            redirect_uri=settings.GMB_REDIRECT_URI
        )
        state = request.session.session_key
        flow.redirect_uri = settings.GMB_REDIRECT_URI
        auth_url, _ = flow.authorization_url(access_type='offline', prompt='consent', state=state)
        return auth_url

    @staticmethod
    def exchange_code_for_token(code):
        flow = Flow.from_client_secrets_file(
            settings.GMB_CLIENT_SECRETS_FILE,
            scopes=SCOPES,
            redirect_uri=settings.GMB_REDIRECT_URI
        )
        try:
            flow.fetch_token(code=code)
            return json.loads(flow.credentials.to_json())
        except Exception as e:
            raise GoogleAPIError(f"Token exchange failed: {e}")

    @staticmethod
    def fetch_locations(account):
        service = GoogleBusinessService.get_service(account, 'mybusinessaccountmanagement', API_VERSION_ACCOUNT_MGMT)
        locations = []
        page_token = None

        while True:
            try:
                request = service.accounts().listLocations(
                    parent=account.account_id, # Assuming account_id is stored correctly (e.g., "accounts/123")
                    pageSize=100,
                    pageToken=page_token,
                    readMask="name,title,storeCode"
                )
                response = request.execute()
                locations.extend(response.get('locations', []))
                page_token = response.get('nextPageToken')
                if not page_token:
                    break
                time.sleep(0.5)
            except HttpError as e:
                logger.error(f"Error fetching locations: {e}")
                break
        return locations

    @staticmethod
    def fetch_reviews_delta(account, location):
        """
        Fetches reviews. 
        'location' argument here is an instance of SocialContent model.
        """
        service = GoogleBusinessService.get_service(account, 'mybusiness', API_VERSION_MYBUSINESS)
        reviews = []
        next_page_token = None
        
        while True:
            try:
                request = service.accounts().locations().reviews().list(
                    # FIX: Model field is 'content_id', not 'location_id'
                    parent=location.content_id,
                    pageSize=50,
                    pageToken=next_page_token,
                    orderBy="update_time desc"
                )
                response = request.execute()
                
                batch = response.get('reviews', [])
                
                for r_data in batch:
                    update_str = r_data.get('updateTime')
                    
                    # Note: You are manually handling 'Z' here. parse_datetime() is safer, 
                    # but this works if you prefer it.
                    if update_str.endswith('Z'):
                        update_str = update_str[:-1] + '+00:00'
                    
                    try:
                        r_time = timezone.make_aware(timezone.datetime.strptime(update_str, "%Y-%m-%dT%H:%M:%S%z"))
                    except:
                        r_time = timezone.now()

                    # FIX: Model field is 'last_comment_sync_at', not 'last_review_sync_at'
                    if r_time <= location.last_comment_sync_at:
                        return reviews

                    reviews.append(r_data)
                
                next_page_token = response.get('nextPageToken')
                if not next_page_token:
                    break
                
                time.sleep(0.5)
                
            except HttpError as e:
                if e.resp.status == 429:
                    time.sleep(10)
                    continue
                logger.error(f"API Error fetching reviews: {e}")
                break
        return reviews

    @staticmethod
    def post_reply(account, review_name, comment_text):
        service = GoogleBusinessService.get_service(account, 'mybusiness', API_VERSION_MYBUSINESS)
        try:
            request = service.accounts().locations().reviews().reply(
                name=review_name,
                body={'comment': comment_text}
            )
            return request.execute()
        except HttpError as e:
            raise GoogleAPIError(f"Failed to post reply: {e}")