<?php

namespace app\service;

use app\service\GoogleAdsClientService;
use app\model\ThirdUserAdvertiser;
use app\util\Helper;
use app\util\ArgumentNames;
use app\util\ArgumentParser;

use Google\Ads\GoogleAds\Lib\V18\GoogleAdsClient;
use Google\Ads\GoogleAds\Util\FieldMasks;
use Google\Ads\GoogleAds\Util\V18\ResourceNames;
use Google\Ads\GoogleAds\V18\Common\ResponsiveSearchAdInfo;
use Google\Ads\GoogleAds\V18\Enums\AdGroupAdStatusEnum\AdGroupAdStatus;
use Google\Ads\GoogleAds\V18\Enums\GoogleAdsFieldCategoryEnum\GoogleAdsFieldCategory;
use Google\Ads\GoogleAds\V18\Enums\GoogleAdsFieldDataTypeEnum\GoogleAdsFieldDataType;
use Google\Ads\GoogleAds\V18\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V18\Resources\Ad;
use Google\Ads\GoogleAds\V18\Resources\AdGroupAd;
use Google\Ads\GoogleAds\V18\Resources\GoogleAdsField;
use Google\Ads\GoogleAds\V18\Services\AdGroupAdOperation;
use Google\Ads\GoogleAds\V18\Services\AdOperation;
use Google\Ads\GoogleAds\V18\Services\MutateAdGroupAdsRequest;

use Google\Ads\GoogleAds\V18\Common\AdTextAsset;
use Google\Ads\GoogleAds\V18\Enums\ServedAssetFieldTypeEnum\ServedAssetFieldType;
use Google\Ads\GoogleAds\V18\Services\GoogleAdsRow;
use Google\Ads\GoogleAds\V18\Services\MutateAdsRequest;
use Google\Ads\GoogleAds\V18\Services\SearchGoogleAdsFieldsRequest;
use Google\Ads\GoogleAds\V18\Services\SearchGoogleAdsRequest;
use Google\Ads\GoogleAds\V18\Services\SearchGoogleAdsStreamRequest;
use Google\Protobuf\Internal\RepeatedField;
use think\facade\Db as ThinkDb;
use app\model\Ad as AdModel;


use Google\ApiCore\ApiException;

class GoogleAdsAssetService extends BaseService
{
//    private $googleAdsClient;
    private $customerId;

    public function __construct($customerId = null)
    {

    }

    // 从数据库动态获取 google RefreshToken
//    private function getRefreshTokenFromDatabase($advertiserId)
//    {
//        // 通过 advertiser_id 查询 ThirdUserAdvertiser,联表查询 ThirdUser 数据
//        $userAdvertiser = ThirdUserAdvertiser::with('googleUser')  // 联表查询 user 关联
//        ->where('advertiser_id', $advertiserId)  // 根据 advertiser_id 查询
//        ->find();  // 获取第一个结果
//
//// 如果找到广告主数据
//        if ($userAdvertiser && $userAdvertiser->googleUser) {
//            // 获取关联用户的 access_token
//            return $userAdvertiser->googleUser ? $userAdvertiser->googleUser->access_token : null;
//        } else {
////            return $this->errorResponse('101', '未找到该广告主或关联的用户');
//        }
//    }


    /* @param int $customerId the customer ID
     * @param $options
     * @return mixed
     * @throws ApiException
     */
    public function runListAssets(int $customerId,$options): mixed
    {

        $googleAdsClient = new GoogleAdsClientService($options['refresh_token'], $options['login_customer_id']);
        // Creates a single shared budget to be used by the campaigns added below.
        $assetsResourceName = self::getAssets($googleAdsClient->getGoogleAdsClientWithloginCustomerId(), $customerId);
//        dump(json_encode($assetsResourceName));
        if (is_array($assetsResourceName)) {
            self::saveAssets($assetsResourceName);
        }

        return $assetsResourceName;
    }

    /* @param int $customerId the customer ID
     * @param $options
     * @return mixed
     * @throws ApiException
     */
    public function runListCreatives(int $customerId,$options): mixed
    {

        $googleAdsClient = new GoogleAdsClientService($options['refresh_token'], $options['login_customer_id']);
        // Creates a single shared budget to be used by the campaigns added below.
        $assetsResourceName = self::getAssetsNew($googleAdsClient->getGoogleAdsClientWithloginCustomerId(), $customerId);
//        dump(json_encode($assetsResourceName));
        if (is_array($assetsResourceName)) {
            self::saveAssetsNew($assetsResourceName);
        }

        return $assetsResourceName;
    }


    /* @param int $customerId the customer ID
     * @param $options
     * @return mixed
     * @throws ApiException
     */
    public function runListAds(int $customerId): mixed
    {

//        $googleAdsClient = $this->googleAdsClient;
        $googleAdsClient = new GoogleAdsClientService($customerId);

        // Creates a single shared budget to be used by the campaigns added below.
        $groupAdsResourceName = self::getAds($googleAdsClient->getGoogleAdsClient(), $customerId);
//        dump(json_encode($groupadsResourceName));
        if (is_array($groupAdsResourceName)) {
            self::saveAds($groupAdsResourceName);
        }

        return $groupAdsResourceName;
    }


    /**
     *  在数据库中保存广告素材信息
     * @param $assetsResourceName
     * @return void
     */
    public static function saveAssetsNew($assetsResourceName)
    {
        $tableName = 'bps_ads_creative';
        $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'public' . $tableName;
        foreach ($assetsResourceName as $data) {
            // 修改后的插入 SQL 语句
            $sql = "INSERT INTO {$tableName}
        (creative_id, account_id,platform, type, name,  url, status,  created_at, updated_at)
        VALUES (:creative_id, :account_id,:platform, :type, :name,  :url, :status, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
        ON CONFLICT (creative_id,platform)
        DO UPDATE SET
            account_id = EXCLUDED.account_id,
            type = EXCLUDED.type,
            name = EXCLUDED.name,
            url = EXCLUDED.url,
            status = EXCLUDED.status,
            updated_at = CURRENT_TIMESTAMP"; // update_at 使用 CURRENT_TIMESTAMP 自动更新

            ThinkDb::execute($sql, $data);
        }
    }

    /**
     *  在数据库中保存广告素材信息
     * @param $assetsResourceName
     * @return void
     */
    public static function saveAssets($assetsResourceName)
    {
        $tableName = 'bps_google_ads_asset';
        $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'public' . $tableName;
        foreach ($assetsResourceName as $data) {
            // 修改后的插入 SQL 语句
            $sql = "INSERT INTO {$tableName}
        (asset_id, customer_id, asset_type, asset_name, resource_name, asset_url, status, asset_source,metadata, create_at, update_at)
        VALUES (:asset_id, :customer_id, :asset_type, :asset_name, :resource_name, :asset_url, :status,:source, :metadata, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
        ON CONFLICT (asset_id)
        DO UPDATE SET
            customer_id = EXCLUDED.customer_id,
            asset_type = EXCLUDED.asset_type,
            asset_name = EXCLUDED.asset_name,
            resource_name = EXCLUDED.resource_name,
            asset_url = EXCLUDED.asset_url,
            status = EXCLUDED.status,
            asset_source = EXCLUDED.asset_source,
            metadata = EXCLUDED.metadata,
            update_at = CURRENT_TIMESTAMP"; // update_at 使用 CURRENT_TIMESTAMP 自动更新

            ThinkDb::execute($sql, $data);
        }
    }



    /**
     * Runs the example.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     */
    // [START get_campaigns]

    public static function getAssetsNew(GoogleAdsClient $googleAdsClient, int $customerId)
    {
        $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
        // 查询广告素材及其关联的广告、广告组和广告系列
//        $query ="SELECT asset.id,asset.name, asset.image_asset.mime_type, asset.image_asset.full_size.url, customer.id FROM asset";
        $query = "SELECT asset.id,
                    asset.name,
                    asset.type,
                    asset.resource_name,
                    asset.source,
                    asset.image_asset.full_size.url,
                    asset.image_asset.mime_type,
                    asset.image_asset.file_size,
                    asset.image_asset.full_size.height_pixels,
                    asset.image_asset.full_size.width_pixels,
                    asset.youtube_video_asset.youtube_video_id,
                    asset.youtube_video_asset.youtube_video_title,
                    customer.id
                FROM asset
                WHERE
                asset.type IN ('IMAGE', 'YOUTUBE_VIDEO')
                LIMIT 10000";

        // Issues a search stream request.
        /** @var GoogleAdsServerStreamDecorator $stream */
        $stream        = $googleAdsServiceClient->searchStream(
            SearchGoogleAdsStreamRequest::build($customerId, $query)
        );
        $resourceNames = [];
        // Iterates over all rows in all messages and prints the requested field values for
        // the campaign in each row.
        foreach ($stream->iterateAllElements() as $googleAdsRow) {
            /** @var GoogleAdsRow $googleAdsRow */
            // 将最终的 URL 列表转换为 PHP 数组
//                $finalUrlsArray = iterator_to_array($finalUrlsList);
            $resourceName               = [];
            $asset_type = $googleAdsRow->getAsset()->getType();
            if ($asset_type === 2) {
                $resourceName['url']                        = $googleAdsRow->getAsset()->getYoutubeVideoAsset()->getYoutubeVideoId();
//                $resourceName['metadata'] ['youtube_video_id']    = $googleAdsRow->getAsset()->getYoutubeVideoAsset()->getYoutubeVideoId();
//                $resourceName['metadata'] ['youtube_video_title'] = $googleAdsRow->getAsset()->getYoutubeVideoAsset()->getYoutubeVideoTitle();
                 $resourceName['name']    = $resourceName['metadata'] ['youtube_video_title'];
                 $resourceName['type']    = 2;
//                $resourceName['metadata'] = json_encode($resourceName['metadata']);
            } elseif ($asset_type === 4) {
                 $resourceName['name']    = $googleAdsRow->getAsset()->getName();
                 $resourceName['type']    = 1;
                $resourceName['url']                  = $googleAdsRow->getAsset()->getImageAsset()->getFullSize()->getUrl();
//                $resourceName['metadata'] ['mimeType']      = $googleAdsRow->getAsset()->getImageAsset()->getMimeType();
//                $resourceName['metadata'] ['filesize']      = $googleAdsRow->getAsset()->getImageAsset()->getFileSize();
//                $resourceName['metadata'] ['height_pixels'] = $googleAdsRow->getAsset()->getImageAsset()->getFullSize()->getHeightPixels();
//                $resourceName['metadata'] ['width_pixels']  = $googleAdsRow->getAsset()->getImageAsset()->getFullSize()->getWidthPixels();
//                $resourceName['metadata'] = json_encode($resourceName['metadata']);
            } else {
                continue;
            }
            $resourceName['creative_id']      = $googleAdsRow->getAsset()->getId();

            $resourceName['status']    = 2; //未定义,先占坑
            $resourceName['platform']    = 2; //未定义,先占坑
//            $resourceName['resource_name'] = $googleAdsRow->getAsset()->getResourceName();
//            $resourceName['source'] = $googleAdsRow->getAsset()->getSource();
            $resourceName['account_id']   = $googleAdsRow->getCustomer()->getId();

            $resourceNames[] = $resourceName;
        }
        return $resourceNames;
    }

    public static function getAssets(GoogleAdsClient $googleAdsClient, int $customerId)
    {
        $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
        // 查询广告素材及其关联的广告、广告组和广告系列
//        $query ="SELECT asset.id,asset.name, asset.image_asset.mime_type, asset.image_asset.full_size.url, customer.id FROM asset";
        $query = "SELECT asset.id,
                    asset.name,
                    asset.type,
                    asset.resource_name,
                    asset.source,
                    asset.image_asset.full_size.url,
                    asset.image_asset.mime_type,
                    asset.image_asset.file_size,
                    asset.image_asset.full_size.height_pixels,
                    asset.image_asset.full_size.width_pixels,
                    asset.youtube_video_asset.youtube_video_id,
                    asset.youtube_video_asset.youtube_video_title,
                    customer.id
                FROM asset
                WHERE
                asset.type IN ('IMAGE', 'YOUTUBE_VIDEO')
                LIMIT 10000";

        // Issues a search stream request.
        /** @var GoogleAdsServerStreamDecorator $stream */
        $stream        = $googleAdsServiceClient->searchStream(
            SearchGoogleAdsStreamRequest::build($customerId, $query)
        );
        $resourceNames = [];
        // Iterates over all rows in all messages and prints the requested field values for
        // the campaign in each row.
        foreach ($stream->iterateAllElements() as $googleAdsRow) {
            /** @var GoogleAdsRow $googleAdsRow */
            // 将最终的 URL 列表转换为 PHP 数组
//                $finalUrlsArray = iterator_to_array($finalUrlsList);
            $resourceName               = [];
            $resourceName['asset_type'] = $googleAdsRow->getAsset()->getType();
            if ($resourceName['asset_type'] === 2) {
                $resourceName['asset_url']                        = $googleAdsRow->getAsset()->getYoutubeVideoAsset()->getYoutubeVideoId();
                $resourceName['metadata'] ['youtube_video_id']    = $googleAdsRow->getAsset()->getYoutubeVideoAsset()->getYoutubeVideoId();
                $resourceName['metadata'] ['youtube_video_title'] = $googleAdsRow->getAsset()->getYoutubeVideoAsset()->getYoutubeVideoTitle();
                 $resourceName['asset_name']    = $resourceName['metadata'] ['youtube_video_title'];
                $resourceName['metadata'] = json_encode($resourceName['metadata']);
            } elseif ($resourceName['asset_type'] === 4) {
                 $resourceName['asset_name']    = $googleAdsRow->getAsset()->getName();
                $resourceName['asset_url']                  = $googleAdsRow->getAsset()->getImageAsset()->getFullSize()->getUrl();
                $resourceName['metadata'] ['mimeType']      = $googleAdsRow->getAsset()->getImageAsset()->getMimeType();
                $resourceName['metadata'] ['filesize']      = $googleAdsRow->getAsset()->getImageAsset()->getFileSize();
                $resourceName['metadata'] ['height_pixels'] = $googleAdsRow->getAsset()->getImageAsset()->getFullSize()->getHeightPixels();
                $resourceName['metadata'] ['width_pixels']  = $googleAdsRow->getAsset()->getImageAsset()->getFullSize()->getWidthPixels();
                $resourceName['metadata'] = json_encode($resourceName['metadata']);
            } else {
                continue;
            }
            $resourceName['asset_id']      = $googleAdsRow->getAsset()->getId();

            $resourceName['status']    = 2; //未定义,先占坑
            $resourceName['resource_name'] = $googleAdsRow->getAsset()->getResourceName();
            $resourceName['source'] = $googleAdsRow->getAsset()->getSource();
            $resourceName['customer_id']   = $googleAdsRow->getCustomer()->getId();

            $resourceNames[] = $resourceName;
        }
        return $resourceNames;
    }




    /**
     * Runs the example.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     */
    // [START get_campaigns]

    public static function getAds(GoogleAdsClient $googleAdsClient, int $customerId)
    {
        $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
        // Creates a query that retrieves all groups.

//            $response = $googleAdsServiceClient->search($customerId, $query);
        $query = "SELECT
                ad_group_ad.ad.id,    
                ad_group.id,
                campaign.id,
                customer.id,
                ad_group_ad.ad.name,                
                ad_group_ad.status,                
                ad_group_ad.ad.resource_name                
                FROM ad_group_ad               
                WHERE                
                ad_group_ad.status != 'REMOVED' ";
        // Issues a search stream request.
        /** @var GoogleAdsServerStreamDecorator $stream */
        $stream        = $googleAdsServiceClient->searchStream(
            SearchGoogleAdsStreamRequest::build($customerId, $query)
        );
        $resourceNames = [];
        // Iterates over all rows in all messages and prints the requested field values for
        // the campaign in each row.
        foreach ($stream->iterateAllElements() as $googleAdsRow) {
            /** @var GoogleAdsRow $googleAdsRow */
            // 假设 $googleAdsRow 是从 Google Ads API 中获取的对象
//                $finalUrlsList = $googleAdsRow->getAdGroupAd()->getAd()->getFinalUrls();
            // 将最终的 URL 列表转换为 PHP 数组
//                $finalUrlsArray = iterator_to_array($finalUrlsList);
            $resourceName['ad_id']       = $googleAdsRow->getAdGroupAd()->getAd()->getId();
            $resourceName['ad_name']     = $googleAdsRow->getAdGroupAd()->getAd()->getName();
            $resourceName['ad_group_id'] = $googleAdsRow->getAdGroup()->getId();
            $resourceName['campaign_id'] = $googleAdsRow->getCampaign()->getId();
            $resourceName['customer_id'] = $googleAdsRow->getCustomer()->getId();
//            $resourceName['final_urls']  = $finalUrlsArray;
            $resourceName['status']        = $googleAdsRow->getAdGroupAd()->getStatus();
            $resourceName['resource_name'] = $googleAdsRow->getAdGroupAd()->getAd()->getResourceName();
            $resourceNames[]               = $resourceName;
        }
        return $resourceNames;
    }



    /**
     * This example updates the CPC bid and status for a given ad group. To get ad groups, run
     * GetAdAds.php.
     */
    /* @param int $customerId the customer ID
     * @param $options
     * @return mixed
     * @throws ApiException
     */
    public function runUpdateAd($options): mixed
    {
//        $googleAdsClient = $this->googleAdsClient;
        $googleAdsClient = new GoogleAdsClientService($options['customer_id']);
        // Creates a single shared budget to be used by the campaigns added below.

        $resourceNames = self::updateAd($googleAdsClient->getGoogleAdsClient(), $options['customer_id'], $options['group_id'], $options['ad_id'], $options['status']);

        return $resourceNames;
    }


    /**
     * Runs the updateAd example.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int $adGroupId the ad group ID that the ad group ad belongs to
     * @param int $adId the ID of the ad to pause
     */
    public static function updateAd(
        GoogleAdsClient $googleAdsClient,
        int             $customerId,
        int             $adGroupId,
        int             $adId,
        int             $status
    )
    {
        // Creates ad group ad resource name.
        $adGroupAdResourceName = ResourceNames::forAdGroupAd($customerId, $adGroupId, $adId);

        // Creates an ad and sets its status to PAUSED.
        $adGroupAd = new AdGroupAd();
        $adGroupAd->setResourceName($adGroupAdResourceName);
//        $adGroupAd->setStatus(AdGroupAdStatus::PAUSED);
        $adGroupAd->setStatus($status);

        // Constructs an operation that will pause the ad with the specified resource name,
        // using the FieldMasks utility to derive the update mask. This mask tells the Google Ads
        // API which attributes of the ad group you want to change.
        $adGroupAdOperation = new AdGroupAdOperation();
        $adGroupAdOperation->setUpdate($adGroupAd);
        $adGroupAdOperation->setUpdateMask(FieldMasks::allSetFieldsOf($adGroupAd));

        // Issues a mutate request to pause the ad group ad.
        $adGroupAdServiceClient = $googleAdsClient->getAdGroupAdServiceClient();
        $response               = $adGroupAdServiceClient->mutateAdGroupAds(MutateAdGroupAdsRequest::build(
            $customerId,
            [$adGroupAdOperation]
        ));

        // Prints the resource name of the paused ad group ad.
        /** @var AdGroupAd $pausedAdGroupAd */
        $pausedAdGroupAd = $response->getResults()[0];
//        printf(
//            "Ad group ad with resource name: '%s' is paused.%s",
//            $pausedAdGroupAd->getResourceName(),
//            PHP_EOL
//        );
        return $pausedAdGroupAd->getResourceName();
    }

    /**
     * 更新广告状态
     */
    public function updateAdStatus(int $customerId, int $adGroupId, int $adId, int $status)
    {
        // 从数据库获取 Ad
        $ad = AdModel::find($adId);
        if (!$ad) {
//            throw new ValidateException('Ad not found');
            return false;
        }
        // 更新数据库中的状态
//        $ad->updateStatus($status);
        if ($this->modifyDbAdStatus($adId, $status)) {
            // 更新 Google Ads 上的状态
//            $googleAdsClient = $this->googleAdsClient;
            $googleAdsClient = new GoogleAdsClientService($customerId);
            $resourceName    = self::updateAd($googleAdsClient->getGoogleAdsClient(), $customerId, $adGroupId, $adId, $status);
            return true;
        }

        return false;
    }

    /**
     * 获取广告状态
     */
    public function getAdStatus(int $adId)
    {
        // 从数据库获取 Ad
        $ad = AdModel::find($adId);
        if (!$ad) {
//            throw new ValidateException('Ad not found');
        }

        // 返回广告状态
        return $ad->getStatusTextAttr(null, $ad->toArray());
    }



    /**
     * 判断广告是否启用
     */
//    public function isAdEnabled(int $adId)
//    {
//        $ad = Ad::find($adId);
//        if (!$ad) {
//            throw new ValidateException('Ad not found');
//        }
//
//        return $ad->isEnabled();
//    }

    /**
     * 判断广告是否暂停
     */
//    public function isAdPaused(int $adId)
//    {
//        $ad = Ad::find($adId);
//        if (!$ad) {
//            throw new ValidateException('Ad not found');
//        }
//
//        return $ad->isPaused();
//    }

    /**
     * 判断广告是否停止
     */
//    public function isAdStopped(int $adId)
//    {
//        $ad = Ad::find($adId);
//        if (!$ad) {
//            throw new ValidateException('Ad not found');
//        }
//
//        return $ad->isStopped();
//    }


    /**
     * This example updates the CPC bid and status for a given ad group. To get ad groups, run
     * GetAdAds.php.
     */
    /* @param int $customerId the customer ID
     * @param $options
     * @return mixed
     * @throws ApiException
     */
    public function runGetResponsiveSearchAds($options): mixed
    {
//        $googleAdsClient = $this->googleAdsClient;
        $googleAdsClient = new GoogleAdsClientService($options['customer_id']);
        // Creates a single shared budget to be used by the campaigns added below.
        if (!isset($options['group_id'])) {
            $options['group_id'] = null;
        }
        $resourceNames = self::getResponsiveSearchAds($googleAdsClient->getGoogleAdsClient(), $options['customer_id'], $options['group_id']);

        return $resourceNames;
    }

    /**
     * 获取指定广告组中未移除的自适应搜索广告。
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int|null $adGroupId the ad group ID for which responsive search ads will be retrieved.
     *     If `null`, returns from all ad groups
     */
    public static function getResponsiveSearchAds(
        GoogleAdsClient $googleAdsClient,
        int             $customerId,
        ?int            $adGroupId
    )
    {
        $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();

        // Creates a query that retrieves responsive search ads.
        $query =
            'SELECT ad_group.id, '
            . 'ad_group_ad.ad.id, '
            . 'ad_group_ad.ad.responsive_search_ad.headlines, '
            . 'ad_group_ad.ad.responsive_search_ad.descriptions, '
            . 'ad_group_ad.status '
            . 'FROM ad_group_ad '
            . 'WHERE ad_group_ad.ad.type = RESPONSIVE_SEARCH_AD '
            . 'AND ad_group_ad.status != "REMOVED"';
        if (!is_null($adGroupId)) {
            $query .= " AND ad_group.id = $adGroupId";
        }

        // Issues a search request.
        $response =
            $googleAdsServiceClient->search(SearchGoogleAdsRequest::build($customerId, $query));

        // Iterates over all rows in all pages and prints the requested field values for
        // the responsive search ad in each row.
        $isEmptyResult = true;
        $resources     = [];
        foreach ($response->iterateAllElements() as $googleAdsRow) {
            /** @var GoogleAdsRow $googleAdsRow */
            $isEmptyResult = false;
            $ad            = $googleAdsRow->getAdGroupAd()->getAd();
            $resource      = [];
//            printf(
//                "Responsive search ad with resource name '%s' and status '%s' was found.%s",
//                $ad->getResourceName(),
//                AdGroupAdStatus::name($googleAdsRow->getAdGroupAd()->getStatus()),
//                PHP_EOL
//            );
            $resource['resource_name'] = $ad->getResourceName();
            $resource['status']        = AdGroupAdStatus::name($googleAdsRow->getAdGroupAd()->getStatus());
            $responsiveSearchAdInfo    = $ad->getResponsiveSearchAd();
//            printf(
//                'Headlines:%1$s%2$sDescriptions:%1$s%3$s%1$s',
//                PHP_EOL,
//                self::convertAdTextAssetsToString($responsiveSearchAdInfo->getHeadlines()),
//                self::convertAdTextAssetsToString($responsiveSearchAdInfo->getDescriptions())
//            )
            $resource['content'] = sprintf(
                'Headlines:%1$s%2$sDescriptions:%1$s%3$s%1$s',
                PHP_EOL,
                self::convertAdTextAssetsToString($responsiveSearchAdInfo->getHeadlines()),
                self::convertAdTextAssetsToString($responsiveSearchAdInfo->getDescriptions())
            );
            $resources[]         = $resource;
        }
        return $resources;
//        if ($isEmptyResult) {
//            print 'No responsive search ads were found.' . PHP_EOL;
//        }
    }

    /**
     * Converts the list of AdTextAsset objects into a string representation.
     *
     * @param RepeatedField $assets the list of AdTextAsset objects
     * @return string the string representation of the provided list of AdTextAsset objects
     */
    private static function convertAdTextAssetsToString(RepeatedField $assets): string
    {
        $result = '';
        foreach ($assets as $asset) {
            /** @var AdTextAsset $asset */
            $result .= sprintf(
                "\t%s pinned to %s.%s",
                $asset->getText(),
                ServedAssetFieldType::name($asset->getPinnedField()),
                PHP_EOL
            );
        }
        return $result;
    }

    /**
     * This example updates the CPC bid and status for a given ad group. To get ad groups, run
     * GetAdAds.php.
     */
    /* @param int $customerId the customer ID
     * @param $options
     * @return mixed
     * @throws ApiException
     */
    public function runUpdateResponsiveSearchAd($options): mixed
    {
//        $googleAdsClient = $this->googleAdsClient;
        $googleAdsClient = new GoogleAdsClientService($options['customer_id']);
        // Creates a single shared budget to be used by the campaigns added below.
        $resourceName = self::updateResponsiveSearchAd($googleAdsClient->getGoogleAdsClient(), $options['customer_id'], $options['ad_id']);

        return $resourceName;
    }

    /**
     * updateResponsiveSearchAd.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int $adId the ad ID to update
     */
    // [START update_responsive_search_ad]
    public static function updateResponsiveSearchAd(
        GoogleAdsClient $googleAdsClient,
        int             $customerId,
        int             $adId
    )
    {
        // Creates an ad with the specified resource name and other changes.
        $ad = new Ad([
            'resource_name' => ResourceNames::forAd($customerId, $adId),
            'responsive_search_ad' => new ResponsiveSearchAdInfo([
                // Update some properties of the responsive search ad.
                'headlines' => [
                    new AdTextAsset([
                        'text' => 'Cruise to Pluto #' . Helper::getShortPrintableDatetime(),
                        'pinned_field' => ServedAssetFieldType::HEADLINE_1
                    ]),
                    new AdTextAsset(['text' => 'Tickets on sale now', 'pinned_field' => ServedAssetFieldType::HEADLINE_2]),
                    new AdTextAsset(['text' => 'Buy your ticket now'])
                ],
                'descriptions' => [
                    new AdTextAsset(['text' => 'Best space cruise ever.']),
                    new AdTextAsset([
                        'text' => 'The most wonderful space experience you will ever have.'])
                ]
            ]),
            'final_urls' => ['http://www.baidu.com'],
            'final_mobile_urls' => ['http://www.baidu.com/mobile']
        ]);

        // Constructs an operation that will update the ad, using the FieldMasks to derive the
        // update mask. This mask tells the Google Ads API which attributes of the ad you want to
        // change.
        $adOperation = new AdOperation();
        $adOperation->setUpdate($ad);
        $adOperation->setUpdateMask(FieldMasks::allSetFieldsOf($ad));

        // Issues a mutate request to update the ad.
        $adServiceClient = $googleAdsClient->getAdServiceClient();
        $response        =
            $adServiceClient->mutateAds(MutateAdsRequest::build($customerId, [$adOperation]));

        // Prints the resource name of the updated ad.
        /** @var Ad $updatedAd */
        $updatedAd = $response->getResults()[0];
        printf(
            "Updated ad with resource name: '%s'.%s",
            $updatedAd->getResourceName(),
            PHP_EOL
        );
        return $updatedAd->getResourceName();
    }
    // [END update_responsive_search_ad]


    /**
     * 根据给定的前缀搜索 Google Ads 字段,检索到关于这些字段的元数据(metadata)
     */
    /* @param int $customerId the customer ID
     * @param $options
     * @return mixed
     * @throws ApiException
     */
    public function runSearchForGoogleAdsFields($options): mixed
    {
//        $googleAdsClient = $this->googleAdsClient;
        $googleAdsClient = new GoogleAdsClientService($options['customer_id']);
        // Creates a single shared budget to be used by the campaigns added below.
        $googleAdsFieldData = self::searchForGoogleAdsFields($googleAdsClient->getGoogleAdsClient(), $options['name_prefix']);

        return $googleAdsFieldData;
    }

    /**
     * Runs the example SearchForGoogleAdsFields.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param string $namePrefix the name prefix to use in the query
     */
    public static function searchForGoogleAdsFields(GoogleAdsClient $googleAdsClient, string $namePrefix)
    {
        $googleAdsFieldServiceClient = $googleAdsClient->getGoogleAdsFieldServiceClient();
        // Searches for all fields whose name begins with the specified namePrefix.
        // A single "%" is the wildcard token in the Google Ads Query language.
        $query    = "SELECT name, category, selectable, filterable, sortable, selectable_with, "
            . "data_type, is_repeated WHERE name LIKE '$namePrefix%'";
        $response = $googleAdsFieldServiceClient->searchGoogleAdsFields(
            SearchGoogleAdsFieldsRequest::build($query)
        );

        if (iterator_count($response->getIterator()) === 0) {
            printf(
                "No GoogleAdsFields found with a name that begins with %s.%s",
                $namePrefix,
                PHP_EOL
            );
            return;
        }
        // Iterates over all rows and prints our the metadata of each matching GoogleAdsField.
        foreach ($response->iterateAllElements() as $googleAdsField) {
            /** @var GoogleAdsField $googleAdsField */
            $fieldInfo = [
                'name' => $googleAdsField->getName(),
                'category' => GoogleAdsFieldCategory::name($googleAdsField->getCategory()),
                'data_type' => GoogleAdsFieldDataType::name($googleAdsField->getDataType()),
                'selectable' => $googleAdsField->getSelectable() ? 'true' : 'false',
                'filterable' => $googleAdsField->getFilterable() ? 'true' : 'false',
                'sortable' => $googleAdsField->getSortable() ? 'true' : 'false',
                'repeated' => $googleAdsField->getIsRepeated() ? 'true' : 'false',
                'selectable_with' => []
            ];
            // Check if there are fields that are selectable with the current field
            if ($googleAdsField->getSelectableWith()->count() > 0) {
                $selectableWithFields = iterator_to_array($googleAdsField->getSelectableWith()->getIterator());
                sort($selectableWithFields); // Sort the fields alphabetically
                $fieldInfo['selectable_with'] = $selectableWithFields;
            }

            // Add the field info to the result array
            $googleAdsFieldData[] = $fieldInfo;
//
//            printf("%s:%s", $googleAdsField->getName(), PHP_EOL);
//            printf(
//                "  %-16s: %s%s",
//                "category:",
//                GoogleAdsFieldCategory::name($googleAdsField->getCategory()),
//                PHP_EOL
//            );
//            printf(
//                "  %-16s: %s%s",
//                "data type:",
//                GoogleAdsFieldDataType::name($googleAdsField->getDataType()),
//                PHP_EOL
//            );
//            printf(
//                "  %-16s: %s%s",
//                "selectable:",
//                $googleAdsField->getSelectable() ? 'true' : 'false',
//                PHP_EOL
//            );
//            printf(
//                "  %-16s: %s%s",
//                "filterable:",
//                $googleAdsField->getFilterable() ? 'true' : 'false',
//                PHP_EOL
//            );
//            printf(
//                "  %-16s: %s%s",
//                "sortable:",
//                $googleAdsField->getSortable() ? 'true' : 'false',
//                PHP_EOL
//            );
//            printf(
//                "  %-16s: %s%s",
//                "repeated:",
//                $googleAdsField->getIsRepeated() ? 'true' : 'false',
//                PHP_EOL
//            );
//
//            if ($googleAdsField->getSelectableWith()->count() > 0) {
//                // Prints the list of fields that are selectable with the field.
//                $selectableWithFields =
//                    iterator_to_array($googleAdsField->getSelectableWith()->getIterator());
//                // Sorts and then prints the list.
//                sort($selectableWithFields);
//                print '  selectable with:' . PHP_EOL;
//                foreach ($selectableWithFields as $selectableWithField) {
//                    /** @var string $selectableWithField */
//                    printf("    $selectableWithField%s", PHP_EOL);
//                }
//            }
        }

        return $googleAdsFieldData; // Return the result array
    }


}