<?php

namespace SheetWise\Admin;

use SheetWise\Vendor\Google\Client;
use SheetWise\Vendor\Google\Service\Drive;
use SheetWise\Vendor\Google\Service\Sheets;

class GoogleSheet {
	/**
	 * The sheet id
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	protected $sheet_id = null;

	/**
	 * The sheet object
	 *
	 * @since 1.0.0
	 *
	 * @var null
	 */
	protected $sheet = null;

	/**
	 * GoogleSheet constructor.
	 *
	 * @since 1.0.0
	 *
	 * @param null $sheet_id
	 */
	public function __construct( $sheet_id = null ) {
		if ( ! is_null( $sheet_id ) ) {
			$this->sheet_id = $sheet_id;
			$this->sheet    = $this->get_sheet_by_id( $sheet_id );
		}
	}

	/**
	 * Get the sheet by id
	 *
	 * @since 1.0.0
	 *
	 * @param $sheet_id
	 *
	 * @return Sheets\Spreadsheet
	 */
	public function get_sheet_by_id( $sheet_id ) {
		$client = $this->get_client();

		if ( is_null( $client ) ) {
			return null;
		}

		$service = new Sheets( $client );

		$response = $service->spreadsheets->get( $sheet_id );

		if ( ! is_a( $response, Sheets\Spreadsheet::class ) ) {
			return null;
		}

		return $response;
	}

	/**
	 * Get the service
	 *
	 * @since 1.0.0
	 *
	 * @return Sheets
	 */
	public function get_service() {
		return new Sheets( $this->get_client() );
	}

	/**
	 * Creates and return the Google API Client. Returns null if failed to create the client
	 *
	 * @since 1.0.0
	 *
	 * @param $scopes
	 */
	private function get_client( $scopes = [] ) {
		$credential = get_option( 'swise_service_account_credential', false );

		if ( ! $credential ) {
			return null;
		}

		$credential = json_decode( $credential, true );

		$default_scopes = [
			'https://www.googleapis.com/auth/drive',
			'https://www.googleapis.com/auth/spreadsheets',
		];

		$scopes = array_merge( $scopes, $default_scopes );

		return new Client(
			[
				'credentials' => $credential,
				'scopes'      => $scopes,
			]
		);
	}

	/**
	 * Get all the spreadsheets of the user
	 *
	 * @since 1.0.0
	 *
	 * @param array $args
	 *
	 * @return array
	 */
	public function get_all( $args = [] ) {
		$list = [];

		$default = [
			'q' => "mimeType='application/vnd.google-apps.spreadsheet'",
		];

		$args   = wp_parse_args( $args, $default );
		$client = $this->get_client();

		if ( is_null( $client ) ) {
			return $list;
		}

		// get the spreadsheet files of the user
		$service    = new Drive( $client );
		$list_files = $service->files->listFiles( $args );

		if ( ! is_a( $list_files, Drive\FileList::class ) ) {
			return $list;
		}

		// get only the spreadsheets
		$files = $list_files->getFiles();

		foreach ( $files as $file ) {
			if ( $file->getMimeType() !== 'application/vnd.google-apps.spreadsheet' ) {
				continue;
			}

			$list[] = [
				'id'   => $file->getId(),
				'name' => $file->getName(),
			];
		}

		return $list;
	}

	/**
	 * Write headers to row 1 of a spreadsheet
	 *
	 * @since 2.0.0
	 *
	 * @param string $spreadsheet_id The spreadsheet ID
	 * @param array  $headers        Array of header strings
	 * @param string $sheet_title    Sheet tab name (default: Sheet1)
	 *
	 * @return \SheetWise\Vendor\Google\Service\Sheets\UpdateValuesResponse|null
	 */
	public function write_headers( $spreadsheet_id, $headers, $sheet_title = 'Sheet1' ) {
		$client = $this->get_client();

		if ( is_null( $client ) ) {
			return null;
		}

		$service     = new Sheets( $client );
		$range       = $sheet_title . '!1:1';
		$value_range = new Sheets\ValueRange();
		$value_range->setValues( [ $headers ] );

		try {
			return $service->spreadsheets_values->update(
				$spreadsheet_id,
				$range,
				$value_range,
				[ 'valueInputOption' => 'USER_ENTERED' ]
			);
		} catch ( \Exception $e ) {
			return null;
		}
	}

	/**
	 * Check if the service account has access to a spreadsheet
	 *
	 * @since 2.0.0
	 *
	 * @param string $spreadsheet_id The spreadsheet ID
	 *
	 * @return array {
	 *     @type bool   $shared Whether the service account can access the sheet
	 *     @type string $email  The service account email
	 * }
	 */
	public function check_sheet_access( $spreadsheet_id ) {
		$email = self::get_service_account_email();

		$result = [
			'shared' => false,
			'email'  => $email ?? '',
		];

		$client = $this->get_client();

		if ( is_null( $client ) ) {
			return $result;
		}

		try {
			$service = new Sheets( $client );
			$service->spreadsheets->get( $spreadsheet_id );
			$result['shared'] = true;
		} catch ( \Exception $e ) {
			$result['shared'] = false;
		}

		return $result;
	}

	/**
	 * Get the service account email from stored credentials
	 *
	 * @since 2.0.0
	 *
	 * @return string|null
	 */
	public static function get_service_account_email() {
		$credential = get_option( 'swise_service_account_credential', '' );

		if ( empty( $credential ) ) {
			return null;
		}

		$decoded = json_decode( $credential, true );

		return $decoded['client_email'] ?? null;
	}

	/**
	 * Get the rows of a spreadsheet
	 *
	 * @since 1.0.0
	 *
	 * @param string $spreadsheet_id
	 * @param string $range
	 *
	 * @return array
	 */
	public function get_rows( $spreadsheet_id, $range = '1:1' ) {
		$client = $this->get_client();

		if ( is_null( $client ) ) {
			return [];
		}

		$service = new Sheets( $client );

		$response = $service->spreadsheets_values->get( $spreadsheet_id, $range );

		if ( ! is_a( $response, Sheets\ValueRange::class ) ) {
			return [];
		}

		$values = $response->getValues();

		$value_arr = isset( $values[0] ) && is_array( $values[0] ) ? apply_filters( 'swise_spreadsheet_rows', $values[0], $spreadsheet_id ) : [];

		return $value_arr;
	}
}
