<?php

namespace app\service;

use GuzzleHttp\Client;
use think\facade\Db as ThinkDb;
use app\model\ThirdUserAdvertiser;
use app\model\ThirdUser;
use Webman\Event\Event;
use Webman\RedisQueue\Redis;
use Webman\RedisQueue\Client as QueueClient;
use app\event\GoogleAdsCustomers;

class GoogleOAuthService
{
    public function getAuthUrl($state = '')
    {
        $clientId     = getenv('GOOGLE_CLIENT_ID');
        $redirectUri  = getenv('GOOGLE_REDIRECT_URI');
        $scope        = 'https://www.googleapis.com/auth/adwords';
        $responseType = 'code';
        $accessType   = 'offline';

//        $state        = 'state_parameter_passthrough_value'; // 可选,保护防止CSRF

        // 将state保存到会话或数据库中,稍后验证
//        $_SESSION['oauth_state'] = $state;  // 使用PHP会话来保存state

//        $authUrl = "https://accounts.google.com/o/oauth2/v2/auth?client_id=$clientId&redirect_uri=$redirectUri&scope=$scope&response_type=$responseType&state=$state";
        if (!empty($state)) {
            // 生成随机的state参数,防止CSRF攻击
//            $state = bin2hex(random_bytes(16)); // 生成一个随机字符串
//            $this->saveThirdUser($state);
            $authUrl = "https://accounts.google.com/o/oauth2/v2/auth?client_id=$clientId&redirect_uri=$redirectUri&scope=$scope&response_type=$responseType&access_type=$accessType&state=$state";
        } else {
            $authUrl = "https://accounts.google.com/o/oauth2/v2/auth?client_id=$clientId&redirect_uri=$redirectUri&scope=$scope&response_type=$responseType&access_type=$accessType";

        }
        return $authUrl;
    }

    public function getThirdUserByRandomCode($state)
    {
        $tableName = 'bps_third_user';
        $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'bps' . $tableName;
        $result    = ThinkDb::name($tableName)->where('random_code', $state)->find();
        return $result;
    }

    public function getRefreshToken($authCode)
    {
        $client   = new Client();
        $response = $client->post('https://oauth2.googleapis.com/token', [
            'form_params' => [
                'code' => $authCode,
                'client_id' => getenv('GOOGLE_CLIENT_ID'),
                'client_secret' => getenv('GOOGLE_CLIENT_SECRET'),
                'redirect_uri' => getenv('GOOGLE_REDIRECT_URI'),
                'grant_type' => 'authorization_code',
            ],
        ]);

        return json_decode($response->getBody(), true);
    }

    public function saveThirdUser($state)
    {
        //发起授权前,新记录到bps_third_user表
        $data      = [
            'random_code' => $state,
            'is_default' => 't',
            'third_type' => 'google',
        ];
        $tableName = 'bps_third_user';
        $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'bps' . $tableName;

        $sql = " INSERT INTO {$tableName}
                    (random_code, is_default,  third_type)
                    VALUES (:random_code, :is_default,  :third_type";
        ThinkDb::execute($sql, $data);
    }

    public function getCustomerList($third_user_id = 0)
    {
        $tableName = 'bps_third_user_advertiser';
        $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'bps' . $tableName;

        $sql  = "SELECT * FROM {$tableName} WHERE doc_ = :third_user_id";
        $data = ['third_user_id' => $third_user_id];

        return ThinkDb::query($sql, $data);
    }

    //保存或更新某个主体部广告账号
    public function saveThirdUserAdvertiser($customer_id, $third_user_id, $login_customer_id, $customer)
    {
        // 确保 customer_id 和 third_user_id 是字符串
        $customer_id = (string)$customer_id;
        $tableName   = 'bps_third_user_advertiser';
        $tableName   = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'bps' . $tableName;
        $data        = [
            'doc_' => $third_user_id,
            'advertiser_id' => $customer_id,
            'advertiser_name' => $customer['descriptive_name'],
            'google_login_customer_id' => $login_customer_id,
        ];
        if ($customer['manager'] === true) {
            $data['google_manager'] = 't';
        } else {
            $data['google_manager'] = 'f';
        }
        if ($customer['test_account'] === true) {
            $data['google_test_account'] = 't';
        } else {
            $data['google_test_account'] = 'f';
        }
//        dump($data);
        $sql = "
                    INSERT INTO {$tableName}
                    (advertiser_id,advertiser_name, doc_,google_login_customer_id,google_manager,google_test_account)
                    VALUES (:advertiser_id, :advertiser_name,:doc_,:google_login_customer_id,:google_manager,:google_test_account)
                    ON CONFLICT (advertiser_id,doc_)
                    DO UPDATE SET
                    advertiser_name = EXCLUDED.advertiser_name,
                    google_login_customer_id = EXCLUDED.google_login_customer_id,
                    google_manager = EXCLUDED.google_manager,
                    google_test_account = EXCLUDED.google_test_account
                ";
//        dump($sql,$data);
        ThinkDb::execute($sql, $data);
    }

    //绑定某个主体的广告账号
    public function bindThirdUserAdvertiser($customer_id, $third_user_id)
    {
        $tableName = 'bps_third_user';
        $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'bps' . $tableName;
        $data      = [
            'id' => $third_user_id,
            'user_id' => $customer_id,];
        $sql       = "
                    UPDATE {$tableName}
                    SET user_id = :user_id
                    WHERE id = :id
                    ";
        ThinkDb::execute($sql, $data);
    }

    public function updateThirdUserDefault($third_user_id, $is_default = 't'): void
    {
        $tableName = 'bps_third_user';
        $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'bps' . $tableName;
        $data      = [
            'is_default' => $is_default,
            'id' => $third_user_id,];
        $sql       = "
                    UPDATE {$tableName}
                    SET is_default = :is_default
                    WHERE id = :id
                    ";
        ThinkDb::execute($sql, $data);
    }


    public function saveRefreshToken($refreshToken, $state = '')
    {
        // 使用ThinkORM保存数据到bps_third_user表
//        $thirdUser               = new \App\Models\ThirdUser();
//        $thirdUser->access_token = $accessToken;
//        $thirdUser->is_default   = true;
//        $thirdUser->random_code  = bin2hex(random_bytes(16)); // 生成随机码
//        $thirdUser->third_type   = 'google';
//        $thirdUser->user_id      = $userId;
//        $thirdUser->save();
        $data      = [
            'access_token' => $refreshToken,
            'is_default' => 'f',
            'third_type' => 'google',
        ];
        $tableName = 'bps_third_user';
        $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'bps' . $tableName;
        if (!empty($state)) {

            $thirdUser = ThirdUser::where('user_id', $state)->where('third_type', 'google')->find();  // 获取第一个结果
            //        dump($thirdUser);        return ($uid);
            if ($thirdUser) {
                $data['id'] = $thirdUser->id;
                $sql        = "
                    UPDATE {$tableName}
                    SET
                    access_token = :access_token,
                    is_default = :is_default,
                    third_type = :third_type
                    WHERE id = :id
                    ";
            } else {
                $data['user_id'] = $state;
                $sql             = "
                    INSERT INTO {$tableName}
                    (access_token, is_default,  third_type, user_id)
                    VALUES (:access_token, :is_default,  :third_type, :user_id)
                ";
            }
        } else {
            $sql = "
                    INSERT INTO {$tableName}
                    (access_token, is_default,  third_type)
                    VALUES (:access_token, :is_default,  :third_type)
                ";
        }
        ThinkDb::execute($sql, $data);

        $options = [];
        $options['refresh_token'] = $refreshToken;
        Event::emit(GoogleAdsCustomers::add_queue, $data);
        $this->queue($options);
    }

    public function updateRefreshToken($refreshToken)
    {
        $customer_id = getenv('GOOGLE_ADS_CUSTOMER_ID');
        //暂时update进行绑定
        $tableName = "bps.bps_third_user";
//            $sql = "UPDATE {$tableName} SET access_token = :access_token WHERE random_code = :random_code";
        $sql  = "UPDATE {$tableName} SET access_token = :access_token WHERE user_id = :user_id";
        $data = [
            'access_token' => $refreshToken, // 这里的 $accessToken 是您想要匹配的值
            'user_id' => $customer_id, // 这里的 $accessToken 是您想要匹配的值
        ];
        // 执行 SQL 语句
        $result = ThinkDb::execute($sql, $data);
    }


    public function revokeToken($accessToken, $third_user_id)
    {
        $client = new Client();
        $client->post('https://oauth2.googleapis.com/revoke', [
            'form_params' => [
                'token' => $accessToken,
            ],
        ]);

        // 在数据库中删除或标记该`access_token(其实是refresh_token)`为无效
        ThirdUserAdvertiser::where('doc_', $third_user_id)->delete();

        $tableName = 'bps_third_user';
        $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'bps' . $tableName;
        $sql       = "UPDATE {$tableName} SET access_token = :access_token WHERE id = :id";
        $data      = [
            'access_token' => '', // 这里的 $accessToken 是您想要匹配的值
            'id' => $third_user_id, // 这里的 $accessToken 是您想要匹配的值
        ];
        // 执行 SQL 语句
        $result = ThinkDb::execute($sql, $data);
//        ThirdUser::where('access_token', $accessToken)->delete();

    }

    public function useRefreshToken($refreshToken)
    {
        $client   = new Client();
        $response = $client->post('https://oauth2.googleapis.com/token', [
            'form_params' => [
                'refresh_token' => $refreshToken,
                'client_id' => getenv('GOOGLE_CLIENT_ID'),
                'client_secret' => getenv('GOOGLE_CLIENT_SECRET'),
                'grant_type' => 'refresh_token',
            ],
        ]);

        $data = json_decode($response->getBody(), true);
        return $data['access_token'];
    }


    /**
     * 批量获取全部Google广告账号数据
     *
     */
    public function getGoogleAdCustomers($options = [])
    {
        if (!empty($options['refresh_token'])) {
            $refreshToken = $options['refresh_token'];
            // 获取符合条件的客户ID数组
            $customers = ThirdUserAdvertiser::alias('tua')
                ->join('bps.bps_third_user tu', 'tua.doc_ = tu.id')  // 连接 bps_third_user 表
                ->where('tu.third_type', 'google')  // 筛选 third_type 为 google 的记录
                ->where('tu.access_token', $refreshToken)  // 筛选 third_type 为 google 的记录
                ->field('CAST(tua.advertiser_id AS BIGINT) as customer_id,tua.google_login_customer_id as login_customer_id,tua.google_test_account as test_account,tua.google_manager as manager, tu.access_token as refresh_token')  // 获取 advertiser_id 字段
                ->select();  // 执行查询
        } else {
            // 获取符合条件的客户ID数组
            $customers = ThirdUserAdvertiser::alias('tua')
                ->join('bps.bps_third_user tu', 'tua.doc_ = tu.id')  // 连接 bps_third_user 表
                ->where('tu.third_type', 'google')  // 筛选 third_type 为 google 的记录
                ->field('CAST(tua.advertiser_id AS BIGINT) as customer_id,tua.google_login_customer_id as login_customer_id,tua.google_test_account as test_account,tua.google_manager as manager, tu.access_token as refresh_token')  // 获取 advertiser_id 字段
                ->select();  // 执行查询
        }


        // 如果没有找到符合条件的广告主,抛出异常
        if ($customers->isEmpty()) {
            return [];
//            throw new ApiException('No customers found for google third type');
        }

        // 转换为简单的数组(提取 advertiser_id)
        return $customers->toArray();

    }

    public function queue($options = []): string
    {
        // 队列名
//        $queue = GoogleAdsCustomers::add_queue;
        $queue2 = GoogleAdsCustomers::init_queue;
        // 数据,可以直接传数组,无需序列化
//        $options = ['to' => 'tom@gmail.com', 'content' => 'hello'];
        // 投递消息
//        Redis::send($queue, $options['data']);
        QueueClient::send($queue2, $options);  //异步投递 延后15秒
        // 投递延迟消息,消息会在60秒后处理
//        Redis::send($queue, $options['data'], 60);

        return $queue2.' redis queue ok';
    }


}