<?php

namespace FSPoster\App\Lib\google;

use Exception;
use FSPoster\App\Providers\Request;
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;

class GoogleMyBusiness
{

	private $at;
	private $cookies;
	private $client;


	public function __construct($sid, $hsid, $ssid, $proxy = '')
	{
		$this->cookies = [
			["Name" => "SID", "Value" => $sid, "Domain" => ".google.com", "Path" => "/", "Max-Age" => null, "Expires" => null, "Secure" => true, "Discard" => false, "HttpOnly" => true],
			["Name" => "HSID", "Value" => $hsid, "Domain" => ".google.com", "Path" => "/", "Max-Age" => null, "Expires" => null, "Secure" => true, "Discard" => false, "HttpOnly" => false],
			["Name" => "SSID", "Value" => $ssid, "Domain" => ".google.com", "Path" => "/", "Max-Age" => null, "Expires" => null, "Secure" => true, "Discard" => false, "HttpOnly" => false]
		];

		$cookieJar = new CookieJar(false, $this->cookies);

		$this->client = new Client([
			'cookies' => $cookieJar,
			'allow_redirects' => ['max' => 20],
			'proxy' => empty($proxy) ? null : $proxy,
			'verify' => false,
			'http_errors' => false,
			'headers' => ['User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0']
		]);
	}

	public function getUserInfo()
	{
		try {
			$myInfo = (string)$this->client->request('GET', 'https://business.google.com/locations')->getBody();
		} catch (Exception $e) {
			$myInfo = '';
		}

		$myInfo = str_replace("\n", "", $myInfo);


		//Find email key: "hib"
		preg_match('/window\._F_getIjData ?\=.+hib\:[a-z0-9]+\[([0-9]+)\].+\;/mi', $myInfo, $email_num);
		$email_num = isset($email_num[1]) ? (int)$email_num[1] : 62;

		//Find account ID: "R5a"
		preg_match('/window\._F_getIjData ?\=.+R5a\:[a-z0-9]+\[([0-9]+)\].+\;/mi', $myInfo, $account_id_num);
		$account_id_num = isset($account_id_num[1]) ? (int)$account_id_num[1] : null;

		preg_match('/window\.IJ_values \= (\[.*?\])\;/mi', $myInfo, $matches);
		if (isset($matches[1])) {
			$jsonInf = json_decode(str_replace(['\x', "'", ',]'], ['', '"', ']'], $matches[1]), true);

			preg_match('/url\((https?\:\/\/.+googleusercontent\.com.+)\)/Ui', $myInfo, $profilePhoto);

			if (is_null($account_id_num)) {
				$accountId = isset($jsonInf[3][0]) ? $jsonInf[3][0] : null;
			} else {
				$accountId = isset($jsonInf[$account_id_num]) ? $jsonInf[$account_id_num] : null;
			}

			$accountEmail = isset($jsonInf[$email_num]) ? $jsonInf[$email_num] : null;

			$userInfo = [
				'id' => $accountId,
				'name' => $accountEmail,
				'email' => $accountEmail,
				'profile_image' => isset($profilePhoto[1]) ? $profilePhoto[1] : null
			];

		} else {
			$userInfo = [
				'id' => null,
				'name' => null,
				'email' => null,
				'profile_image' => null
			];
		}

		return $userInfo;
	}

	public function sendPost($postTo, $text, $link = null, $linkButton = 'LEARN_MORE', $imageURL = '', $productName = null, $productPrice = null, $productCurrency = null, $productCategory = null)
	{
		if (!$this->getAT()) {
			return [
				'status' => 'error',
				'error_msg' => 'Error! Google MyBusiness session expired! Please remove and add your account again.'
			];
		}

		$isProduct = is_null($productName) ? false : true;

		if ($isProduct) {
			$res = $this->client->get('https://business.google.com/products/l/' . $postTo);

			$res = (string)$res->getBody();

			$res = str_replace("\n", "", $res);

			preg_match('/AF_initDataCallback\(\{key\: *\\\'ds\:0\\\'\, *isError\: *false *\, *hash\: *\\\'.+\\\'\, *data\:function\(\)\{return *(.+)\}\}\)\;\<\/script\>/iU', $res, $productsAllArr);

			$productsAllArr = json_decode($productsAllArr[1], true);

			$productPrice = explode('.', (string)$productPrice);
			$productPrice1 = (int)$productPrice[0];
			$productPrice2 = isset($productPrice[1]) ? (int)substr($productPrice[1] . '000000000', 0, 9) : null;

			$newProductArr = [
				uniqid(),
				[
					null,
					[[$productName, $text]],
					null,
					null,
					$this->uploadPhoto($postTo, $imageURL, true),
					[
						[$productCurrency, $productPrice1, $productPrice2],
						[$productCurrency, $productPrice1, $productPrice2]
					]
				],
				(!empty($link) && $linkButton != '-' ? [$link, $linkButton] : null)
			];

			$categoryExist = false;

			foreach ($productsAllArr[0][2] as $cKey => $categoriesInf) {
				$thisCategoryName = $categoriesInf[1][0][0];
				if ($productCategory == $thisCategoryName) {
					$categoryExist = true;
					$productsAllArr[0][2][$cKey][5][] = $newProductArr;
					break;
				}
			}

			if (!$categoryExist) {
				$productsAllArr[0][2][] = [
					uniqid(),
					[[$productCategory]],
					[],
					3,
					[],
					[$newProductArr],
					null,
					[]
				];
			}

			$productsAllArr[0][0] = 'a64954ab-ea5c-4ace-8d66-b630ef675889';
			$productsAllArr[0][1] = [["Products"]];

			$fReqParam = [[["HTNPzb", json_encode([$postTo, $productsAllArr[0], null, null, 3, null, "1392645184277392271"]), null, "generic"]]];
		} else {
			$fReqParam = [
				[
					[
						"h6IfIc",
						json_encode(
							[
								$postTo,
								[
									null,
									$text,
									null,
									null,
									(!empty($link) && $linkButton != '-' ? [null, $link, $linkButton, $linkButton] : null),
									[],
									null,
									null,
									null,
									null,
									null,
									null,
									null,
									$this->uploadPhoto($postTo, $imageURL),
									1,
									null,
									null
								]
							]
						),
						null,
						"generic"
					]
				]
			];
		}

		try {
			$post = (string)$this->client->request('POST', 'https://business.google.com/_/GeoMerchantFrontendUi/data/batchexecute', [
				'form_params' => ['f.req' => json_encode($fReqParam), 'at' => $this->getAT()],
				'headers' => ['Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8']
			])->getBody();
		} catch (Exception $e) {
			return [
				'status' => 'error',
				'error_msg' => 'Error! ' . $e->getMessage()
			];
		}

		if (!$isProduct) {
			preg_match('/localPosts\/([0-9]+)/', $post, $postId);

			if (!isset($postId[1])) {
				$getErrorMessage = json_decode(str_replace([")]}'", "\n", '\n'], '', $post), true);
				$errorMessage = isset($getErrorMessage[0][5][2][0][1][0][0][2]) ? 'Error: ' . $getErrorMessage[0][5][2][0][1][0][0][2] : esc_html__('Error! Could not share the post!', 'fs-poster');

				return [
					'status' => 'error',
					'error_msg' => $errorMessage
				];
			}
		}

		return [
			'status' => 'ok',
			'id' => $postTo . ($isProduct ? ':product' : ':post')
		];
	}

	private function getAT()
	{
		if (is_null($this->at)) {
			try {
				$plusMainPage = (string)$this->client->request('GET', 'https://business.google.com/locations')->getBody();
			} catch (Exception $e) {
				$plusMainPage = '';
			}

			preg_match('/\"SNlM0e\":\"([^\"]+)/', $plusMainPage, $at);
			$this->at = isset($at[1]) ? $at[1] : null;
		}

		return $this->at;
	}

	public function uploadPhoto($location, $imageUrl = null, $forProduct = false)
	{
		if (empty($imageUrl)) {
			return null;
		}

		$fReqParam = [
			[
				[
					"iWixD",
					json_encode(
						[
							$location,
							$imageUrl,
							[null, $imageUrl, null, null, 1]
						]
					),
					null,
					"generic"
				]
			]
		];

		try {
			$uploadData = (string)$this->client->request('POST', 'https://business.google.com/_/GeoMerchantFrontendUi/data/batchexecute', [
				'form_params' => ['f.req' => json_encode($fReqParam), 'at' => $this->getAT()],
				'headers' => ['Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8']
			])->getBody();
		} catch (Exception $e) {
			$uploadData = '';
		}

		$uploadData = str_replace([")]}'", "\n", '\n'], '', $uploadData);
		$uploadData = json_decode($uploadData);
		$uploadData = isset($uploadData[0][2]) ? $uploadData[0][2] : "[]";

		$uploadData = json_decode($uploadData);

		$uploadData = isset($uploadData[2]) ? [$uploadData[2]] : null;

		if ($forProduct) {
			if (!isset($uploadData[0][1]) || !isset($uploadData[0][5]))
				return null;

			$imgURL = $uploadData[0][1];
			$imgSizes = $uploadData[0][5];

			$fReqParam = [
				[
					[
						"I3qire",
						json_encode([
							$location,
							[
								$imgURL,
								$imgSizes,
								null
							]
						]),
						null,
						"generic"
					]
				]
			];

			try {
				$uploadData = (string)$this->client->request('POST', 'https://business.google.com/_/GeoMerchantFrontendUi/data/batchexecute', [
					'form_params' => ['f.req' => json_encode($fReqParam), 'at' => $this->getAT()],
					'headers' => ['Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8']
				])->getBody();
			} catch (Exception $e) {
				$uploadData = '';
			}

			$uploadData = str_replace(["\n", '\n'], '', $uploadData);

			$uploadData = preg_replace('/^.+\[/iU', '[', $uploadData);
			$uploadData = preg_replace('/[0-9]+\[.+$/iU', '', $uploadData);
			$uploadData = json_decode($uploadData, true);

			if (!is_array($uploadData) || !isset($uploadData[0][2]))
				return null;

			$uploadData = json_decode($uploadData[0][2], true);

			return isset($uploadData[0]) ? [$uploadData[0]] : null;
		}

		return $uploadData;
	}

	public function getMyLocations()
	{
		try {
			$locationsStr = (string)$this->client->request('GET', 'https://business.google.com/locations')->getBody();
		} catch (Exception $e) {
			$locationsStr = '';
		}

		preg_match_all('/\<a.+href\=[\'\"]\.?\/dashboard\/.\/([0-9]+)[^0-9].+\<span.*\>(.+)\<\/span\>.+\<span.*\>(.+)\<\/span\>\<\/a\>/Ui', $locationsStr, $locations);

		$locationsArr = [];

		foreach ($locations[1] as $arrKey => $cId) {
			if (!isset($locations[2][$arrKey]) || !isset($locations[3][$arrKey]))
				continue;

			$title = strip_tags($locations[2][$arrKey]);
			$categ = strip_tags($locations[3][$arrKey]);

			$locationsArr[] = [
				'id' => $cId,
				'name' => $title,
				'category' => $categ
			];
		}

		return $locationsArr;
	}

	/**
	 * @return array
	 */
	public function checkAccount()
	{
		$result = [
			'error' => true,
			'error_msg' => null
		];

		if ($this->getAT()) {
			$result['error'] = false;
		}

		return $result;
	}
}
