<?php

namespace includescore;

use gam_ads_ad_manager_and_ad_exchange_Logs;
use Google\AdsApi\AdManager\AdManagerSession;
use Google\AdsApi\AdManager\AdManagerSessionBuilder;
use Google\AdsApi\AdManager\Util\v202602\ReportDownloader;
use Google\AdsApi\AdManager\Util\v202602\StatementBuilder;
use Google\AdsApi\AdManager\v202602\Column;
use Google\AdsApi\AdManager\v202602\DateRangeType;
use Google\AdsApi\AdManager\v202602\Dimension;
use Google\AdsApi\AdManager\v202602\ExportFormat;
use Google\AdsApi\AdManager\v202602\ReportJob;
use Google\AdsApi\AdManager\v202602\ReportQuery;
use Google\AdsApi\AdManager\v202602\ReportQueryAdUnitView;
use Google\AdsApi\AdManager\v202602\ServiceFactory;
use Google\AdsApi\Common\OAuth2TokenBuilder;
use Google_Client;

class GamadsadmanagerandadexchangeHelper
{
    public static function gamadsmbai_decrypt_secret($data)
    {
        $key = wp_salt('auth');
        $iv  = base64_decode(get_option('gam_secret_iv'));
        return openssl_decrypt(base64_decode($data), 'AES-256-CBC', $key, 0, $iv);
    }
    // Google Client
    public static function gam_get_google_client()
    {
        try {
            $scrtkey = self::gamadsmbai_decrypt_secret(get_option('gam_web_client_secret'));
            if ($scrtkey) {
                $client = new Google_Client();
                $client->setClientId(get_option('gam_web_client_id'));
                $client->setClientSecret($scrtkey);
                $client->setRedirectUri(get_option('gam_redirect_uri'));
                $client->setAccessType('offline');
                $client->setPrompt('consent');
                $client->addScope('https://www.googleapis.com/auth/admanager');
                // $client->addScope('https://www.googleapis.com/auth/dfp');
                return $client;
            }
            return null;
        } catch (\Throwable $e) {
            gam_ads_ad_manager_and_ad_exchange_Logs::log('Get CLint Access Func Error: ' . $e->getMessage() . '. File: ' . __FILE__ . '. Line: ' . __LINE__);
            return [];
        }
    }

    // Fetch all user networks
    public static function gam_fetch_user_networks($refreshToken)
    {
        // define outside so catch can use it too
        // phpcs:ignore WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting
        // $oldLevel = error_reporting();
        try {
            $scrtkey = self::gamadsmbai_decrypt_secret(get_option('gam_web_client_secret'));
            // Temporarily silence warnings/notices inside this block
            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting
            // error_reporting(E_ERROR | E_PARSE); // disable warnings & notices
            $oAuth2Credential = (new OAuth2TokenBuilder())
                ->withClientId(get_option('gam_web_client_id'))
                ->withClientSecret($scrtkey)
                ->withRefreshToken($refreshToken)
                ->build();
            $session = (new AdManagerSessionBuilder())
                ->withOAuth2Credential($oAuth2Credential)
                ->withApplicationName('GAM Connect Plugin')
                ->build();

            $serviceFactory = new ServiceFactory();
            $networkService = $serviceFactory->createNetworkService($session);
            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting
            // error_reporting($oldLevel); // restore default
            return $networkService->getAllNetworks();
        } catch (\Throwable $e) {
            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting
            // error_reporting($oldLevel);
            gam_ads_ad_manager_and_ad_exchange_Logs::log('[GAM Fetch Networks Error] ' . $e->getMessage() . '. File: ' . __FILE__ . '. Line: ' . __LINE__);
            return [];
        }
    }

    public static function fetchAdunitsReports($refreshToken, $networkCode)
    {
        // phpcs:disable Squiz.PHP.DiscouragedFunctions.Discouraged
        ini_set('memory_limit', '2G');
        ini_set('max_execution_time', '1000');
        // phpcs:enable Squiz.PHP.DiscouragedFunctions.Discouraged
        try {
            $scrtkey = self::gamadsmbai_decrypt_secret(get_option('gam_web_client_secret'));
            $DataArray = [];
            $oAuth2Credential = (new OAuth2TokenBuilder())
                ->withClientId(get_option('gam_web_client_id'))
                ->withClientSecret($scrtkey)
                ->withRefreshToken($refreshToken)
                ->build();
            $session = (new AdManagerSessionBuilder())
                ->withOAuth2Credential($oAuth2Credential)
                ->withApplicationName('GAM Connect Plugin')
                ->withNetworkCode($networkCode)
                ->build();

            $serviceFactory = new ServiceFactory();
            $reportService = $serviceFactory->createReportService($session);
            $reportQuery = new ReportQuery();
            $reportQuery->setAdUnitView(ReportQueryAdUnitView::HIERARCHICAL);
            $reportQuery->setDimensions([
                Dimension::AD_UNIT_NAME,
                Dimension::AD_UNIT_ID,
            ]);
            $reportQuery->setColumns([
                Column::AD_EXCHANGE_LINE_ITEM_LEVEL_IMPRESSIONS
            ]);
            $dateRange = DateRangeType::TODAY;
            $reportQuery->setDateRangeType($dateRange);
            $reportQuery->setReportCurrency('USD');

            $reportJob = new ReportJob();
            $reportJob->setReportQuery($reportQuery);
            $reportJob = $reportService->runReportJob($reportJob);
            $reportDownloader = new ReportDownloader($reportService, $reportJob->getId());

            if ($reportDownloader->waitForReportToFinish()) {
                $filePath = sprintf('%s.csv.gz', tempnam(sys_get_temp_dir(), 'delivery-report-'));
                $reportDownloader->downloadReport(ExportFormat::CSV_DUMP, $filePath, false);
                $gzFile = gzopen($filePath, 'rb');
                if ($gzFile === false) {
                    die('Could not open the .csv.gz file.');
                }
                $firstLine = gzgets($gzFile);
                if ($firstLine === false) {
                    die('The file is empty or could not be read.');
                }
                while (!gzeof($gzFile)) {
                    $line = gzgets($gzFile);
                    if ($line === false) {
                        break;
                    }
                    // echo $line;
                    $makearray = str_getcsv($line); //is used to remove ,(comma) from a value inside line
                    // print_r($makearray);
                    $DataArray[] = [
                        'adunitname' => $makearray[0],
                        'adunitid' => $makearray[1],
                    ];
                }
                gzclose($gzFile);
                // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink -- Using unlink() here intentionally for temporary file cleanup
                unlink($filePath);
            } else {
                gam_ads_ad_manager_and_ad_exchange_Logs::log('Adunit fetch fails');
            }
            return $DataArray;
        } catch (\Throwable $e) {
            gam_ads_ad_manager_and_ad_exchange_Logs::log('Ad Unit Report Fetch Error ' . $e->getMessage() . '. File: ' . __FILE__ . '. Line: ' . __LINE__);
            return [];
        }
    }

    // JUST USE CUSTOME DATE TIME HELPER FOR GOOGLE
    public static function gam_convert_datetime($gmDateTime)
    {
        try {
            if (!$gmDateTime) return null;
            $date = $gmDateTime->getDate();
            $phpDateTime = new \DateTime(
                sprintf(
                    '%04d-%02d-%02d %02d:%02d:%02d',
                    $date->getYear(),
                    $date->getMonth(),
                    $date->getDay(),
                    $gmDateTime->getHour(),
                    $gmDateTime->getMinute(),
                    $gmDateTime->getSecond()
                ),
                new \DateTimeZone($gmDateTime->getTimeZoneId() ?: 'UTC')
            );

            return $phpDateTime->format('Y-m-d H:i:s');
        } catch (\Throwable $e) {
            gam_ads_ad_manager_and_ad_exchange_Logs::log('Convert DateTime Error: ' . $e->getMessage() . '. File: ' . __FILE__ . '. Line: ' . __LINE__);
            return null;
        }
    }


    public static function fetchOnlyAdUnits($refreshToken, $networkCode)
    {
        // phpcs:disable Squiz.PHP.DiscouragedFunctions.Discouraged
        ini_set('memory_limit', '2G');
        ini_set('max_execution_time', '1000');
        // phpcs:enable Squiz.PHP.DiscouragedFunctions.Discouraged
        try {
            $scrtkey = self::gamadsmbai_decrypt_secret(get_option('gam_web_client_secret'));
            $DataArray = [];
            $oAuth2Credential = (new OAuth2TokenBuilder())
                ->withClientId(get_option('gam_web_client_id'))
                ->withClientSecret($scrtkey)
                ->withRefreshToken($refreshToken)
                ->build();
            $session = (new AdManagerSessionBuilder())
                ->withOAuth2Credential($oAuth2Credential)
                ->withApplicationName('GAM Connect Plugin')
                ->withNetworkCode($networkCode)
                ->build();
            $serviceFactory = new ServiceFactory();
            $inventoryService = $serviceFactory->createInventoryService($session);
            $statementBuilder = (new StatementBuilder())->orderBy('id ASC')->limit(500);
            do {
                $page = $inventoryService->getAdUnitsByStatement($statementBuilder->toStatement());
                if ($page->getResults() !== null) {
                    foreach ($page->getResults() as $adUnit) {
                        $DataArray[] = [
                            'adunitid'      => $adUnit->getId(),
                            'adunitname'    => $adUnit->getName(),
                            'code'          => $adUnit->getAdUnitCode(),
                            'status'        => $adUnit->getStatus(),
                            'parentId'      => $adUnit->getParentId(),
                            'description'   => $adUnit->getDescription(),
                            'sizes'         => array_map(function ($size) {
                                return $size->getFullDisplayString(); // e.g. "300x250 (Display)"
                            }, (array) $adUnit->getAdUnitSizes()),
                            'lastModified'  => self::gam_convert_datetime($adUnit->getLastModifiedDateTime()),
                        ];
                    }
                }
                $statementBuilder->increaseOffsetBy(500);
            } while ($statementBuilder->getOffset() < $page->getTotalResultSetSize());
            return $DataArray;
        } catch (\Throwable $e) {
            gam_ads_ad_manager_and_ad_exchange_Logs::log('Ad Unit Fetch Error ' . $e->getMessage() . '. File: ' . __FILE__ . '. Line: ' . __LINE__);
            return [];
        }
    }

    public static function CheckMainGam()
    {
        try {
            $storedtoken = get_option('gam_ads_ad_manager_and_ad_exchange_tokens', []);
            // Fetch networks
            $networks = [];
            if (!empty($storedtoken['refresh_token'])) {
                $networkObjs = self::gam_fetch_user_networks($storedtoken['refresh_token']);
                foreach ($networkObjs as $net) {
                    $networks[] = [
                        'displayName' => $net->getDisplayName(),
                        'networkCode' => $net->getNetworkCode(),
                    ];
                }
                update_option('gam_ads_ad_manager_and_ad_exchange_networks', $networks);

                $networkCode = get_option('gam_ads_ad_manager_and_ad_exchange_network_code');
                if ($networkCode) {
                    $fetchAdunits = self::fetchOnlyAdUnits($storedtoken['refresh_token'], $networkCode);
                    update_option('gam_ads_ad_manager_and_ad_exchange_network_' . $networkCode . '_adunit', $fetchAdunits);
                    global $wpdb;
                    $table = $wpdb->prefix . 'gamadsmbai_adunits';
                    if (!empty($fetchAdunits)) {
                        $values = [];
                        //$values[] = array();
                        $placeholders = [];

                        foreach ($fetchAdunits as $row) {
                            $values[] = $row['adunitid'];
                            $values[] = $networkCode; // add network_code
                            $values[] = $row['adunitname'];
                            $values[] = $row['code'];
                            $values[] = $row['status'];
                            $values[] = $row['parentId'];
                            $values[] = $row['description'];
                            $values[] = wp_json_encode($row['sizes']);
                            $values[] = $row['lastModified'];

                            // 9 columns → 9 placeholders
                            $placeholders[] = "(%s, %s, %s, %s, %s, %s, %s, %s, %s)";
                        }

                        $sql = "INSERT INTO $table 
                        (adunit_id, network_code, adunit_name, code, status, parent_id, description, sizes, last_modified)
                        VALUES " . implode(", ", $placeholders) . " 
                        ON DUPLICATE KEY UPDATE 
                        adunit_name = VALUES(adunit_name),
                        code = VALUES(code),
                        status = VALUES(status),
                        parent_id = VALUES(parent_id),
                        description = VALUES(description),
                        sizes = VALUES(sizes),
                        last_modified = VALUES(last_modified)";

                        /** @noinspection SqlResolve */
                        /** @noinspection SqlNoDataSourceInspection */
                        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Safe because all values are passed via $wpdb->prepare() and No need of cache and $table is derived from $wpdb->prefix.
                        $wpdb->query($wpdb->prepare($sql, ...$values));
                    }
                }
            }
            return $networks;
        } catch (\Throwable $e) {
            gam_ads_ad_manager_and_ad_exchange_Logs::log('error: ' . $e->getMessage() . '. File: ' . __FILE__ . '. Line: ' . __LINE__);
            return [];
        }
    }
}

// GamadsadmanagerandadexchangeHelper::CheckMainGam();
