<?php

namespace app\service;


use app\util\Helper;
use app\util\ArgumentNames;
use app\util\ArgumentParser;

use Google\Ads\GoogleAds\Lib\V18\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V18\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V18\GoogleAdsException;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Util\FieldMasks;
use Google\Ads\GoogleAds\Util\V18\ResourceNames;
use Google\Ads\GoogleAds\V18\Enums\AdGroupStatusEnum\AdGroupStatus;
use Google\Ads\GoogleAds\V18\Enums\AdGroupTypeEnum\AdGroupType;
use Google\Ads\GoogleAds\V18\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V18\Resources\AdGroup;
use Google\Ads\GoogleAds\V18\Services\AdGroupOperation;
use Google\Ads\GoogleAds\V18\Services\MutateAdGroupsRequest;
use Google\ApiCore\ApiException;

class GoogleAdsGroupService
{
    private $googleAdsClient;

    public function __construct()
    {
//        $this->customerId = getenv('GOOGLE_ADS_CUSTOMER_ID');

        // OAuth2 Token Authentication
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Google Ads Client initialization
        $this->googleAdsClient = (new GoogleAdsClientBuilder())
            ->fromFile()
            ->withOAuth2Credential($oAuth2Credential)
            ->build();
    }


    /**
     * This example updates a campaign by setting the status to `PAUSED`. To get campaigns, run
     * GetCampaigns.php.
     */
    /* @param int $customerId the customer ID
     * @param $options
     * @return mixed
     * @throws ApiException
     */
    public function runAddGroup($options): mixed
    {
        $googleAdsClient = $this->googleAdsClient;
        // Creates a single shared budget to be used by the campaigns added below.
        $resourceNames = self::addGroup($googleAdsClient, $options['customer_id'], $options['campaign_id']);

        return $resourceNames;
    }


    /**
     * Runs the addGroup example.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int $campaignId the campaign ID to add ad groups to
     */
    public static function addGroup(
        GoogleAdsClient $googleAdsClient,
        int             $customerId,
        int             $campaignId
    )
    {
        $campaignResourceName = ResourceNames::forCampaign($customerId, $campaignId);

        $operations = [];

        // Constructs an ad group and sets an optional CPC value.
        $adGroup1 = new AdGroup([
            'name' => 'Earth to Mars Cruises #' . Helper::getPrintableDatetime(),
            'campaign' => $campaignResourceName,
            'status' => AdGroupStatus::ENABLED,
            'type' => AdGroupType::SEARCH_STANDARD,
            'cpc_bid_micros' => 10000000
        ]);

        $adGroupOperation1 = new AdGroupOperation();
        $adGroupOperation1->setCreate($adGroup1);
        $operations[] = $adGroupOperation1;

        // Constructs another ad group.
        $adGroup2 = new AdGroup([
            'name' => 'Earth to Venus Cruises #' . Helper::getPrintableDatetime(),
            'campaign' => $campaignResourceName,
            'status' => AdGroupStatus::ENABLED,
            'type' => AdGroupType::SEARCH_STANDARD,
            'cpc_bid_micros' => 20000000
        ]);

        $adGroupOperation2 = new AdGroupOperation();
        $adGroupOperation2->setCreate($adGroup2);
        $operations[] = $adGroupOperation2;

        // Issues a mutate request to add the ad groups.
        $adGroupServiceClient = $googleAdsClient->getAdGroupServiceClient();
        $response             = $adGroupServiceClient->mutateAdGroups(MutateAdGroupsRequest::build(
            $customerId,
            $operations
        ));
        $resourceNames        = [];

        printf("Added %d ad groups:%s", $response->getResults()->count(), PHP_EOL);

        foreach ($response->getResults() as $addedAdGroup) {
            /** @var AdGroup $addedAdGroup */
            print $addedAdGroup->getResourceName() . PHP_EOL;
            $resourceNames[] = $addedAdGroup->getResourceName();
        }
        return $resourceNames;
    }



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

        $resourceNames = self::updateGroup($googleAdsClient, $options['customer_id'], $options['group_id'], $options['bid_micro_amount'], $options['status']);

        return $resourceNames;
    }

    /**
     * Runs the updateAdGroup example.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int $adGroupId the ID of ad group to update
     * @param int $bidMicroAmount the bid amount in micros to use for the ad group bid
     */
    // [START update_ad_group]
    public static function updateGroup(
        GoogleAdsClient $googleAdsClient,
        int             $customerId,
        int             $adGroupId,
                        $bidMicroAmount,
        int             $status
    )
    {

        // Creates an ad group object with the specified resource name and other changes.
        $adGroup = new AdGroup([
            'resource_name' => ResourceNames::forAdGroup($customerId, $adGroupId),
            'cpc_bid_micros' => $bidMicroAmount,
//            'status' => AdGroupStatus::PAUSED
            'status' => $status
        ]);

        // Constructs an operation that will update the ad group 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.
        $adGroupOperation = new AdGroupOperation();
        $adGroupOperation->setUpdate($adGroup);
        $adGroupOperation->setUpdateMask(FieldMasks::allSetFieldsOf($adGroup));

        // Issues a mutate request to update the ad group.
        $adGroupServiceClient = $googleAdsClient->getAdGroupServiceClient();
        $response             = $adGroupServiceClient->mutateAdGroups(MutateAdGroupsRequest::build(
            $customerId,
            [$adGroupOperation]
        ));

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