<?php
/**
 * Google Sheets destination, via an Apps Script web app.
 *
 * @package Ordsync
 */

defined( 'ABSPATH' ) || exit;

/**
 * No Google Cloud Console, no service account, no OAuth.
 * The user pastes a small script into their own sheet and gives us the URL.
 */
class Ordsync_Dest_Sheets extends Ordsync_Destination {

	/**
	 * Key.
	 *
	 * @return string
	 */
	public function key() {
		return 'sheets';
	}

	/**
	 * Label.
	 *
	 * @return string
	 */
	public function label() {
		return __( 'Google Sheets', 'ordercarry-order-automation-for-woocommerce' );
	}

	/**
	 * Enabled and configured.
	 *
	 * @return bool
	 */
	public function is_enabled() {
		return parent::is_enabled() && '' !== $this->setting( 'url' );
	}

	/**
	 * Send one order to the sheet.
	 *
	 * @param array $payload Order payload.
	 * @return true|WP_Error
	 */
	public function send( array $payload ) {

		$payload['secret'] = Ordsync_Settings::secret();

		$result = $this->post( $this->setting( 'url' ), $payload );

		if ( is_wp_error( $result ) ) {
			return $this->explain( $result );
		}

		/*
		 * Apps Script answers 200 even when it refuses the row, so the real
		 * answer is in the body.
		 *
		 * Our script always replies {"ok":true}. Anything else - a rejection,
		 * or one of Google's HTML sign-in pages served with a 200 - means the
		 * row was NOT written. Demanding an explicit ok:true is what stops the
		 * plugin reporting success while silently losing orders.
		 */
		$decoded = json_decode( $this->last_body, true );

		if ( is_array( $decoded ) && isset( $decoded['ok'] ) && true === $decoded['ok'] ) {
			return true;
		}

		if ( is_array( $decoded ) && isset( $decoded['error'] ) ) {
			return new WP_Error(
				'ordsync_sheets_rejected',
				sprintf(
					/* translators: %s: error text returned by the Apps Script */
					__( 'Google Sheets refused the row: %s. Check that the secret in your Apps Script matches the one shown on this page.', 'ordercarry-order-automation-for-woocommerce' ),
					(string) $decoded['error']
				),
				array( 'status' => 400 )
			);
		}

		return new WP_Error(
			'ordsync_sheets_no_confirmation',
			__( 'Google replied, but not with the confirmation our script sends. The row was probably not saved. Redeploy the web app with "Who has access: Anyone", then paste the new URL here.', 'ordercarry-order-automation-for-woocommerce' ),
			array( 'status' => 400 )
		);
	}

	/**
	 * Turn a raw HTTP failure into something a shop owner can act on.
	 *
	 * Every one of these was hit for real during testing, and each one costs a
	 * support email if the message only says "HTTP 404".
	 *
	 * @param WP_Error $error Original error.
	 * @return WP_Error
	 */
	private function explain( WP_Error $error ) {

		$status = self::error_status( $error );

		$hints = array(
			404 => __( 'Google says this web app no longer exists. This usually means a new deployment was created, which changes the URL. In Apps Script go to Deploy > Manage deployments, copy the current Web app URL, and paste it here again.', 'ordercarry-order-automation-for-woocommerce' ),
			403 => __( 'Google refused the request. In Apps Script, redeploy with "Who has access" set to Anyone.', 'ordercarry-order-automation-for-woocommerce' ),
			401 => __( 'Google asked for a login. In Apps Script, redeploy with "Execute as: Me" and "Who has access: Anyone".', 'ordercarry-order-automation-for-woocommerce' ),
			400 => __( 'Google rejected the request. Check that the URL ends in /exec and that the deployment has been authorised at least once.', 'ordercarry-order-automation-for-woocommerce' ),
		);

		if ( ! isset( $hints[ $status ] ) ) {
			return $error;
		}

		return new WP_Error(
			$error->get_error_code(),
			$hints[ $status ],
			array( 'status' => $status )
		);
	}
}
