import os
import time
import zipfile
import logging
import requests
from google.oauth2 import service_account
from googleapiclient.discovery import build
from google.auth.transport.requests import Request


class Download_V9_2:
  __SDF_V               = "SDF_VERSION_9_2"
  __BASE_URL            = "https://displayvideo.googleapis.com/v4"
  __SCOPES              = ["https://www.googleapis.com/auth/display-video"]
  __DISCOVERY_URL       = ("https://displayvideo.googleapis.com/$discovery/rest?version=v4")
  __FILE_TYPES          = ["FILE_TYPE_INSERTION_ORDER", "FILE_TYPE_LINE_ITEM"]
  __FILTER_MAP          = {
                            "CAMPAIGN"        : "FILTER_TYPE_CAMPAIGN_ID",
                            "LINE_ITEM"       : "FILTER_TYPE_LINE_ITEM_ID",
                            "INSERTION_ORDER" : "FILTER_TYPE_INSERTION_ORDER_ID",
                          }

  def __init__(self, service_account_json_path: str):
    self.service_account_json_path = service_account_json_path

  def __get_build(self):
    try:
      credentials = service_account.Credentials.from_service_account_file(self.service_account_json_path, scopes=self.__SCOPES)
      return build("displayvideo", "v4", credentials=credentials, discoveryServiceUrl=self.__DISCOVERY_URL, cache_discovery=False)
    except Exception:
      raise Exception("Can't build object ERR:101")

  def download_sdf(self, advertiser_id: int, entity_id: int, entity_type: str):
    filter_type = self.__FILTER_MAP.get(entity_type.upper())

    if not filter_type:
      raise ValueError("Invalid entity type")
    
    body = {
      "version"           : self.__SDF_V,
      "advertiserId"      : advertiser_id,
      "parentEntityFilter": {
        "filterIds"       : [entity_id],
        "filterType"      : filter_type,
        "fileType"        : self.__FILE_TYPES,
      }
    }
    
    logging.info(f"Creating SDF download task for {entity_type} with ID {entity_id} ...")
    
    dv360 = self.__get_build()
    
    task = dv360.sdfdownloadtasks().create(body = body).execute()
    task_name = task["name"]
    
    logging.info(f"Task created: {task_name}")
    
    # Polling with timeout
    MAX_WAIT  = 300
    waited    = 0
    
    while True:
      operation = dv360.sdfdownloadtasks().operations().get(name = task_name).execute()

      if operation.get("done"):
        if "error" in operation:
          raise Exception(operation["error"])

        resource_name = operation["response"]["resourceName"]
        break

      if waited >= MAX_WAIT:
        raise TimeoutError("SDF generation timed out")

      logging.info("Waiting for SDF generation...")
      time.sleep(5)
      waited += 5

    # Download SDF file using authorized HTTP client
    download_url = f"https://displayvideo.googleapis.com/download/{resource_name}?alt=media"
    
    response, content = dv360._http.request(download_url)
    if response.status != 200:
      raise Exception("Failed to download SDF")
    
    # Create unique output folder
    folder_name = f"sdf_output/{entity_type}_{entity_id}_{int(time.time())}"
    os.makedirs(folder_name, exist_ok=True)
    zip_path = os.path.join(folder_name, "sdf.zip")
    
    with open(zip_path, "wb") as f:
      f.write(content)

    # Extract ZIP
    with zipfile.ZipFile(zip_path, "r") as zip_ref:
      zip_ref.extractall(folder_name)

    logging.info("SDF Download and extraction completed successfully.")
    return folder_name
    

    



	# Tools helps to interact with downloaded SDF file
	# Parse it's SDF
	# Update the fields if required
	# Process to save to local disk
	# Remove those files too..
 
 
 
# This file is basically help us to download the SDF file from dv360
# account, and keep in very respective ful manner
