<?php

/**
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace App\Services;


use App\Facade\TableName;
use GetOpt\GetOpt;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Lib\V14\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V14\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V14\GoogleAdsException;
use Google\Ads\GoogleAds\Util\V14\ResourceNames;
use Google\Ads\GoogleAds\V14\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V14\Services\ClickConversion;
use Google\Ads\GoogleAds\V14\Services\ClickConversionResult;
use Google\Ads\GoogleAds\V14\Services\CustomVariable;
use Google\Ads\GoogleAds\V14\Services\UploadClickConversionsRequest;
use Google\Ads\GoogleAds\V14\Services\UploadClickConversionsResponse;
use Google\ApiCore\ApiException;
use Illuminate\Support\Facades\DB;

/**
 * This code example imports offline conversion values for specific clicks to your account.
 * To get Google Click ID for a click, use the "click_view" resource:
 * https://developers.google.com/google-ads/api/fields/latest/click_view.
 * To set up a conversion action, run the AddConversionAction.php example.
 */
class UploadOfflineConversion
{
    public static function reg(int $UserID, array $params)
    {
        $userinfo=DB::table(TableName::QPAccountsDB() . 'AccountsInfo')
            ->where('UserID', $UserID)->select("Channel","CustomID","LastLogonPackage")->first();

        $Channel = $userinfo->Channel;
        $package = $userinfo->LastLogonPackage;
        $adConfig=config('googleAd')[$package]??config('googleAd')[$Channel];
        if(!isset($adConfig))return;
        self::runbefore($adConfig['customerId'],$adConfig['reg'],1,$params['gclid'],$params['gbraid'],$params['wbraid']);
    }
    public static function pay(int $Channel, array $params,$payamt,string $package)
    {
        $adConfig=config('googleAd')[$package]??config('googleAd')[$Channel];

        if(!isset($adConfig))return;
        self::runbefore($adConfig['customerId'],$adConfig['pay'],$payamt,$params['gclid'],$params['gbraid'],$params['wbraid']);
    }

    public static function d0(int $Channel, array $params,string $package)
    {
        $adConfig=config('googleAd')[$package]??config('googleAd')[$Channel];
        if(!isset($adConfig))return;
        self::runbefore($adConfig['customerId'],$adConfig['d0'],1,$params['gclid'],$params['gbraid'],$params['wbraid']);
    }
    public static function d1(int $Channel, array $params,string $package)
    {
        $adConfig=config('googleAd')[$package]??config('googleAd')[$Channel];
        if(!isset($adConfig))return;
        self::runbefore($adConfig['customerId'],$adConfig['d1'],1,$params['gclid'],$params['gbraid'],$params['wbraid']);
    }

    private static function runbefore(int     $customerId,
                                      int     $conversionActionId,
                                      float   $conversionValue,
                                      ?string $gclid,
                                      ?string $gbraid,
                                      ?string $wbraid
    )
    {

        if($gbraid=='{gbraid}')$gbraid=null;
        if($wbraid=='{wbraid}')$wbraid=null;

        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct a Google Ads client configured from a properties file and the
        // OAuth2 credentials above.
        $googleAdsClient = (new GoogleAdsClientBuilder())
            ->fromFile()
            ->withOAuth2Credential($oAuth2Credential)
            // We set this value to true to show how to use GAPIC v2 source code. You can remove the
            // below line if you wish to use the old-style source code. Note that in that case, you
            // probably need to modify some parts of the code below to make it work.
            // For more information, see
            // https://developers.devsite.corp.google.com/google-ads/api/docs/client-libs/php/gapic.
            ->usingGapicV2Source(true)
            ->build();

        try {
            self::upload(
                $googleAdsClient,
                $customerId,
                $conversionActionId,
                $gclid,
                $gbraid,
                $wbraid,
                date("yyyy-mm-dd hh:mm:ss") . "-03:00",
                $conversionValue,
                null,
                null
            );
        } catch (GoogleAdsException $googleAdsException) {
            Util::WriteLog("googleAd", sprintf(
                "Request with ID '%s' has failed.%sGoogle Ads failure details:%s",
                $googleAdsException->getRequestId(),
                PHP_EOL,
                PHP_EOL
            ));
            foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) {
                /** @var GoogleAdsError $error */
                Util::WriteLog("googleAd", sprintf(
                    "\t%s: %s%s",
                    $error->getErrorCode()->getErrorCode(),
                    $error->getMessage(),
                    PHP_EOL
                ));
            }
            exit(1);
        } catch (ApiException $apiException) {
            Util::WriteLog("googleAd", sprintf(
                "ApiException was thrown with message '%s'.%s",
                $apiException->getMessage(),
                PHP_EOL
            ));
            exit(1);
        }
    }
    /**
     * Runs the example.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int $conversionActionId the ID of the conversion action to upload to
     * @param string|null $gclid the GCLID for the conversion (should be newer than the number of
     *     days set on the conversion window of the conversion action). If set, GBRAID and WBRAID
     *     must be null
     * @param string|null $gbraid The GBRAID identifier for an iOS app conversion. If set, GCLID and
     *     WBRAID must be null
     * @param string|null $wbraid The WBRAID identifier for an iOS web conversion. If set, GCLID and
     *     GBRAID must be null
     * @param string $conversionDateTime the date and time of the conversion (should be after the
     *     click time). The format is "yyyy-mm-dd hh:mm:ss+|-hh:mm", e.g.
     *     “2019-01-01 12:32:45-08:00”
     * @param float $conversionValue the value of the conversion
     * @param string|null $conversionCustomVariableId the ID of the conversion custom variable to
     *     associate with the upload
     * @param string|null $conversionCustomVariableValue the value of the conversion custom
     *     variable to associate with the upload
     */
    // [START upload_offline_conversion]
    private static function upload(
        GoogleAdsClient $googleAdsClient,
        int             $customerId,
        int             $conversionActionId,
        ?string         $gclid,
        ?string         $gbraid,
        ?string         $wbraid,
        string          $conversionDateTime,
        float           $conversionValue,
        ?string         $conversionCustomVariableId,
        ?string         $conversionCustomVariableValue
    )
    {
        // Verifies that exactly one of gclid, gbraid, and wbraid is specified, as required.
        // See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks for details.
        $nonNullFields = array_filter(
            [$gclid, $gbraid, $wbraid],
            function ($field) {
                return !is_null($field);
            }
        );
        if (count($nonNullFields) !== 1) {
            throw new \UnexpectedValueException(
                sprintf(
                    "Exactly 1 of gclid, gbraid or wbraid is required, but %d ID values were "
                    . "provided",
                    count($nonNullFields)
                )
            );
        }

        // Creates a click conversion by specifying currency as USD.
        $clickConversion = new ClickConversion([
            'conversion_action'    =>
                ResourceNames::forConversionAction($customerId, $conversionActionId),
            'conversion_value'     => $conversionValue,
            'conversion_date_time' => $conversionDateTime,
            'currency_code'        => 'USD'
        ]);
        // Sets the single specified ID field.
        if (!is_null($gclid)) {
            $clickConversion->setGclid($gclid);
        } elseif (!is_null($gbraid)) {
            $clickConversion->setGbraid($gbraid);
        } else {
            $clickConversion->setWbraid($wbraid);
        }


        if (!is_null($conversionCustomVariableId) && !is_null($conversionCustomVariableValue)) {
            $clickConversion->setCustomVariables([new CustomVariable([
                'conversion_custom_variable' => ResourceNames::forConversionCustomVariable(
                    $customerId,
                    $conversionCustomVariableId
                ),
                'value'                      => $conversionCustomVariableValue
            ])]);
        }

        // Issues a request to upload the click conversion.
        $conversionUploadServiceClient = $googleAdsClient->getConversionUploadServiceClient();
        /** @var UploadClickConversionsResponse $response */
        $response = $conversionUploadServiceClient->uploadClickConversions(
            UploadClickConversionsRequest::build($customerId, [$clickConversion], true)
        );

        // Prints the status message if any partial failure error is returned.
        // Note: The details of each partial failure error are not printed here, you can refer to
        // the example HandlePartialFailure.php to learn more.
        if ($response->hasPartialFailureError()) {
            Util::WriteLog("googleAd", sprintf(
                "Partial failures occurred: '%s'.%s",
                $response->getPartialFailureError()->getMessage(),
                PHP_EOL
            ));
        } else {
            // Prints the result if exists.
            /** @var ClickConversionResult $uploadedClickConversion */
            $uploadedClickConversion = $response->getResults()[0];
            Util::WriteLog("googleAd", sprintf(
                "Uploaded click conversion that occurred at '%s' from Google Click ID '%s' " .
                "to '%s'.%s",
                $uploadedClickConversion->getConversionDateTime(),
                $uploadedClickConversion->getGclid(),
                $uploadedClickConversion->getConversionAction(),
                PHP_EOL
            ));
        }
    }
    // [END upload_offline_conversion]
}
