<?php

namespace app\service;

use app\util\Helper;
use app\util\ArgumentNames;
use app\util\ArgumentParser;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
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\Util\FieldMasks;
use Google\Ads\GoogleAds\Util\V18\ResourceNames;
use Google\Ads\GoogleAds\V18\Enums\ManagerLinkStatusEnum\ManagerLinkStatus;
use Google\Ads\GoogleAds\V18\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V18\Resources\CustomerClientLink;
use Google\Ads\GoogleAds\V18\Resources\CustomerManagerLink;
use Google\Ads\GoogleAds\V18\Services\CustomerClientLinkOperation;
use Google\Ads\GoogleAds\V18\Services\CustomerManagerLinkOperation;
use Google\Ads\GoogleAds\V18\Services\ListAccessibleCustomersRequest;
use Google\Ads\GoogleAds\V18\Services\MutateCustomerClientLinkRequest;
use Google\Ads\GoogleAds\V18\Services\MutateCustomerManagerLinkRequest;
use Google\Ads\GoogleAds\V18\Services\SearchGoogleAdsRequest;
use Google\ApiCore\ApiException;

class GoogleAdsAccountService
{
//    private $googleAdsClient;
//    private $customerId;
//    private const NUMBER_OF_CAMPAIGNS_TO_ADD = 1;
    private $loginCustomerId; // 增加 login-customer-id 属性

    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();
    }

    /**
     * Runs the example.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     */
    // [START list_accessible_customers]
    public static function runListAccessibleCustomers()
    {
         // Creates a client with the manager customer ID as login customer ID.
        $googleAdsClient = self::createGoogleAdsClient(0);

        $customerServiceClient = $googleAdsClient->getCustomerServiceClient();

        // Issues a request for listing all accessible customers.
        $accessibleCustomers =
            $customerServiceClient->listAccessibleCustomers(new ListAccessibleCustomersRequest());
        print 'Total results: ' . count($accessibleCustomers->getResourceNames()) . PHP_EOL;

        $resourceNameArray = [];
        // Iterates over all accessible customers' resource names and prints them.
        foreach ($accessibleCustomers->getResourceNames() as $resourceName) {
            /** @var string $resourceName */
            printf("Customer resource name: '%s'%s", $resourceName, PHP_EOL);
            $resourceNameArray[] = $resourceName;
        }
        return $resourceNameArray;
    }
    // [END list_accessible_customers]


    /**
     * Runs the example.
     *
     * @param $options
     *  This example assumes that the same credentials will work for both customers,
     *   but that may not be the case. If you need to use different credentials
     *   for each customer, then you may either update the client configuration or
     *   instantiate the clients accordingly, one for each set of credentials. Always make
     *   sure to update the configuration before fetching any services you need to use.
     * //     * @return mixed
     * @throws ApiException
     */
    public function runLinkManagerToClient($options)
    {

        // Extends an invitation to the client while authenticating as the manager.
        $managerCustomerId = $options['manager_customer_id'];
        $clientCustomerId  = $options['client_customer_id'];


        // Extends an invitation to the client while authenticating as the manager.
        $customerClientLinkResourceName = self::createInvitation(
            $managerCustomerId,
            $clientCustomerId

        );

        // Retrieves the manager link information.
        $managerLinkResourceName = self::getManagerLinkResourceName(
            $managerCustomerId,
            $clientCustomerId,
            $customerClientLinkResourceName
        );

        // Accepts the manager's invitation while authenticating as the client.
        return self::acceptInvitation($clientCustomerId, $managerLinkResourceName);


    }

    /**
     * Extends an invitation from a manager customer to a client customer.
     *
     * @param int $managerCustomerId the manager customer ID
     * @param int $clientCustomerId the customer ID
     * @return string the resource name of the customer client link created for the invitation
     */
    private static function createInvitation(
        int $managerCustomerId,
        int $clientCustomerId
    )
    {

        // Creates a client with the manager customer ID as login customer ID.
        $googleAdsClient = self::createGoogleAdsClient($managerCustomerId);

        // Creates a customer client link.
        $customerClientLink = new CustomerClientLink([
            // Sets the client customer to invite.
            'client_customer' => ResourceNames::forCustomer($clientCustomerId),
            'status' => ManagerLinkStatus::PENDING
        ]);

        // Creates a customer client link operation for creating the one above.
        $customerClientLinkOperation = new CustomerClientLinkOperation();
        $customerClientLinkOperation->setCreate($customerClientLink);

        // Issues a mutate request to create the customer client link.
        $customerClientLinkServiceClient = $googleAdsClient->getCustomerClientLinkServiceClient();
        $response                        = $customerClientLinkServiceClient->mutateCustomerClientLink(
            MutateCustomerClientLinkRequest::build(
                $managerCustomerId,
                $customerClientLinkOperation
            )
        );

        // Prints the result.
        $customerClientLinkResourceName = $response->getResult()->getResourceName();
        printf(
            "An invitation has been extended from the manager customer %d" .
            " to the client customer %d with the customer client link resource name '%s'.%s",
            $managerCustomerId,
            $clientCustomerId,
            $customerClientLinkResourceName,
            PHP_EOL
        );

        // Returns the resource name of the created customer client link.
        return $customerClientLinkResourceName;
    }

    /**
     * Retrieves the manager link resource name of a customer client link given its resource name.
     *
     * @param int $managerCustomerId the manager customer ID
     * @param int $clientCustomerId the customer ID
     * @param string $customerClientLinkResourceName the customer client link resource name
     * @return string the manager link resource name
     */
    private static function getManagerLinkResourceName(
        int    $managerCustomerId,
        int    $clientCustomerId,
        string $customerClientLinkResourceName
    )
    {
        // Creates a client with the manager customer ID as login customer ID.
        $googleAdsClient = self::createGoogleAdsClient($managerCustomerId);

        // Creates the query.
        $query = "SELECT customer_client_link.manager_link_id FROM customer_client_link" .
            " WHERE customer_client_link.resource_name = '$customerClientLinkResourceName'";

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

        // Gets the ID and resource name associated to the manager link found.
        $managerLinkId           = $response->getIterator()->current()
            ->getCustomerClientLink()
            ->getManagerLinkId();
        $managerLinkResourceName = ResourceNames::forCustomerManagerLink(
            $clientCustomerId,
            $managerCustomerId,
            $managerLinkId
        );

        // Prints the result.
        printf(
            "Retrieved the manager link of the customer client link:" .
            " its ID is %d and its resource name is '%s'.%s",
            $managerLinkId,
            $managerLinkResourceName,
            PHP_EOL
        );

        // Returns the resource name of the manager link found.
        return $managerLinkResourceName;
    }

    /**
     * Accepts an invitation.
     *
     * @param int $clientCustomerId the customer ID
     * @param string $managerLinkResourceName the resource name of the manager link to accept
     */
    private static function acceptInvitation(
        int    $clientCustomerId,
        string $managerLinkResourceName
    )
    {
        // Creates a client with the client customer ID as login customer ID.
        $googleAdsClient = self::createGoogleAdsClient($clientCustomerId);

        // Creates the customer manager link with the updated status.
        $customerManagerLink = new CustomerManagerLink();
        $customerManagerLink->setResourceName($managerLinkResourceName);
        $customerManagerLink->setStatus(ManagerLinkStatus::ACTIVE);

        // Creates a customer manager link operation for updating the one above.
        $customerManagerLinkOperation = new CustomerManagerLinkOperation();
        $customerManagerLinkOperation->setUpdate($customerManagerLink);
        $customerManagerLinkOperation->setUpdateMask(
            FieldMasks::allSetFieldsOf($customerManagerLink)
        );

        // Issues a mutate request to update the customer manager link.
        $customerManagerLinkServiceClient =
            $googleAdsClient->getCustomerManagerLinkServiceClient();
        $response                         = $customerManagerLinkServiceClient->mutateCustomerManagerLink(
            MutateCustomerManagerLinkRequest::build(
                $clientCustomerId,
                [$customerManagerLinkOperation]
            )
        );

        // Prints the result.
        printf(
            "The client %d accepted the invitation with the resource name '%s'.%s",
            $clientCustomerId,
            $response->getResults()[0]->getResourceName(),
            PHP_EOL
        );
        return $response->getResults()[0]->getResourceName();
    }
    // [END link_manager_to_client]

    /**
     * Creates a Google Ads client based on the default configuration file
     * and a given login customer id.
     *
     * @param int $loginCustomerId the login customer ID
     * @return GoogleAdsClient the created client
     */
    private static function createGoogleAdsClient(int $loginCustomerId)
    {
        // Generates a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())
            // Sets the properties based on the default properties file
            ->fromFile()
            ->build();

        if($loginCustomerId >0){
                    // Builds and returns the Google Ads client
        return (new GoogleAdsClientBuilder())
            // Sets the properties based on the default properties file
            ->fromFile()
            // eUses the OAuth2 credentials crated above.
            ->withOAuth2Credential($oAuth2Credential)
            // Overrides the login customer ID with the given one.
            ->withLoginCustomerId($loginCustomerId)
            ->build();
        }else{
                      // Builds and returns the Google Ads client
               return (new GoogleAdsClientBuilder())
            // Sets the properties based on the default properties file
            ->fromFile()
            // eUses the OAuth2 credentials crated above.
            ->withOAuth2Credential($oAuth2Credential)
            // Overrides the login customer ID with the given one.
            ->build();
        }


    }


}