<?php
/**
 * Adapter for "WPSyncSheets Lite For WooCommerce" (Creative Werk Designs).
 *
 * Option shapes below were confirmed against the free plugin's source
 * (wpsyncsheets-woocommerce, v2.0.10 at audit time; see
 * .superpowers/sdd/competitor-wpsyncsheets.md):
 *  - Unlike every other competitor adapter, WPSyncSheets Lite talks to the
 *    Google Sheets/Drive API directly from WordPress using a site-owned
 *    OAuth 2.0 client (the merchant creates their own client id/secret in
 *    Google Cloud Console). `wpssw_google_settings` is an INDEXED array
 *    `[0]=client_id, [1]=client_secret, [2]=auth_code`
 *    (includes/class-wpsslw-settings.php:1361-1373). Because these are
 *    locally owned, portable credentials, this adapter — and only this
 *    adapter — imports them. Index `[2]` (the one-time auth code) and the
 *    refresh token JSON-encoded inside `wpssw_google_accessToken`
 *    (includes/class-wpsslw-google-api-functions.php:179-186) are NEVER
 *    read: the user re-authorizes through StoreSheet's own OAuth flow.
 *  - There is no single "the" spreadsheet option — Products, Orders,
 *    Coupons, and Customers each have their own spreadsheet-id option
 *    (`wpssw_product_spreadsheet_id`, `wpssw_woocommerce_spreadsheet`,
 *    `wpssw_coupon_spreadsheet_id`, `wpssw_customer_spreadsheet_id`), all
 *    storing a bare Google Drive/Sheets file id (never a URL). In common
 *    usage all four point at the same spreadsheet, but nothing in the
 *    competitor's code enforces that, so a distinct-id mismatch is called
 *    out with a warning rather than silently dropped.
 *  - Per-resource sync is a discrete `'yes'`/`'no'` option
 *    (`wpssw_{product,order,coupon,customer}_spreadsheet_setting`), set at
 *    includes/modules/class-wpsslw-{product,order,coupon,customer}.php.
 *  - Order-status selection lives in `wpssw_sheets`, a serialized
 *    associative array of `status-label => sheet-tab-name`
 *    (includes/modules/class-wpsslw-order.php:2627-2631); presence as a KEY
 *    means that status is synced. The 8 legacy `{status}_orders` booleans
 *    are read-only fallback in the competitor's own code and are ignored
 *    here — `wpssw_sheets` is authoritative.
 *  - Every option above is read through the competitor's own
 *    `wpsslw_option()` wrapper, which resolves to `get_site_option()` on
 *    multisite (includes/class-wpsslw-google-api.php:20-34). This adapter
 *    reads via plain `get_option()` (single-site scope only) — a known,
 *    accepted limitation for the free build; a multisite install's config
 *    living in `wp_sitemeta` will not be found here.
 *
 * @package StoreSheet
 */

declare( strict_types=1 );

namespace StoreSheet\Importer\Adapters;

defined( 'ABSPATH' ) || exit;

use StoreSheet\Importer\ImportPlan;
use StoreSheet\Importer\SourceAdapter;

final class WpSyncSheetsAdapter implements SourceAdapter {

	private const OPTION_GOOGLE_SETTINGS = 'wpssw_google_settings';

	private const OPTION_PRODUCT_SPREADSHEET  = 'wpssw_product_spreadsheet_id';
	private const OPTION_ORDER_SPREADSHEET    = 'wpssw_woocommerce_spreadsheet';
	private const OPTION_COUPON_SPREADSHEET   = 'wpssw_coupon_spreadsheet_id';
	private const OPTION_CUSTOMER_SPREADSHEET = 'wpssw_customer_spreadsheet_id';

	private const OPTION_PRODUCT_SETTING  = 'wpssw_product_spreadsheet_setting';
	private const OPTION_ORDER_SETTING    = 'wpssw_order_spreadsheet_setting';
	private const OPTION_COUPON_SETTING   = 'wpssw_coupon_spreadsheet_setting';
	private const OPTION_CUSTOMER_SETTING = 'wpssw_customer_spreadsheet_setting';

	private const OPTION_SHEETS = 'wpssw_sheets';

	/** Bare WC order-status slugs StoreSheet recognizes. */
	private const ALLOWED_STATUSES = array( 'pending', 'processing', 'on-hold', 'completed', 'cancelled', 'refunded', 'failed' );

	public function id(): string {
		return 'wpsyncsheets';
	}

	public function label(): string {
		return __( 'WPSyncSheets For WooCommerce', 'storesheet' );
	}

	public function plugin_files(): array {
		return array( 'wpsyncsheets-woocommerce/wpsyncsheets-lite-woocommerce.php' );
	}

	public function is_present(): bool {
		if ( ! function_exists( 'is_plugin_active' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}
		foreach ( $this->plugin_files() as $file ) {
			if ( is_plugin_active( $file ) ) {
				return true;
			}
		}

		// Single-site scope only — see class doc block above re: multisite.
		$google_settings = get_option( self::OPTION_GOOGLE_SETTINGS, array() );
		return is_array( $google_settings ) && array() !== $google_settings;
	}

	public function read_config(): ImportPlan {
		$warnings = array();

		// --- Spreadsheet: first non-empty id, Products > Orders > Coupons > Customers. ---
		$product_id  = (string) get_option( self::OPTION_PRODUCT_SPREADSHEET, '' );
		$order_id    = (string) get_option( self::OPTION_ORDER_SPREADSHEET, '' );
		$coupon_id   = (string) get_option( self::OPTION_COUPON_SPREADSHEET, '' );
		$customer_id = (string) get_option( self::OPTION_CUSTOMER_SPREADSHEET, '' );

		$candidates = array( $product_id, $order_id, $coupon_id, $customer_id );

		$spreadsheet_id = '';
		foreach ( $candidates as $candidate ) {
			if ( '' !== $candidate ) {
				$spreadsheet_id = $candidate;
				break;
			}
		}

		$spreadsheet = null;
		if ( '' !== $spreadsheet_id ) {
			$spreadsheet = array(
				'id'  => $spreadsheet_id,
				'url' => 'https://docs.google.com/spreadsheets/d/' . $spreadsheet_id . '/edit',
			);
		}

		$distinct_ids = array_unique(
			array_filter(
				$candidates,
				static function ( $v ) {
					return '' !== $v;
				}
			)
		);
		if ( count( $distinct_ids ) > 1 ) {
			$warnings[] = __( 'WPSyncSheets used a separate spreadsheet per resource; StoreSheet syncs all tabs into one — review the target spreadsheet.', 'storesheet' );
		}

		// --- Credentials: the ONLY adapter that imports a local Google client secret. ---
		// wpssw_google_settings is an indexed array [client_id, client_secret,
		// auth_code]. Index [2] (auth_code) and wpssw_google_accessToken (the
		// refresh token) are deliberately never read — see class doc block.
		$credentials     = null;
		$google_settings = get_option( self::OPTION_GOOGLE_SETTINGS, array() );
		if ( is_array( $google_settings ) ) {
			$client_id     = (string) ( $google_settings[0] ?? '' );
			$client_secret = (string) ( $google_settings[1] ?? '' );
			if ( '' !== $client_id && '' !== $client_secret ) {
				$credentials = array(
					'oauth_client_id'     => $client_id,
					'oauth_client_secret' => $client_secret,
				);
				$warnings[]  = __( 'WPSyncSheets used your own Google app credentials — StoreSheet imported the client ID/secret; you\'ll re-authorize on the next step.', 'storesheet' );
			}
		}

		// --- Order statuses: keys of wpssw_sheets, normalized to bare slugs. ---
		$order_statuses = array();
		$sheets         = get_option( self::OPTION_SHEETS, array() );
		if ( is_array( $sheets ) ) {
			$normalized = array();
			foreach ( array_keys( $sheets ) as $label ) {
				$normalized[] = $this->normalize_status_slug( (string) $label );
			}
			$order_statuses = array_values( array_intersect( $normalized, self::ALLOWED_STATUSES ) );
		}

		// --- Settings: only resources the competitor actually toggled 'yes'. ---
		$settings = array_filter(
			array(
				'sync_products'  => $this->is_yes( get_option( self::OPTION_PRODUCT_SETTING, '' ) ) ? true : null,
				'sync_orders'    => $this->is_yes( get_option( self::OPTION_ORDER_SETTING, '' ) ) ? true : null,
				'sync_coupons'   => $this->is_yes( get_option( self::OPTION_COUPON_SETTING, '' ) ) ? true : null,
				'sync_customers' => $this->is_yes( get_option( self::OPTION_CUSTOMER_SETTING, '' ) ) ? true : null,
				'order_statuses' => array() !== $order_statuses ? $order_statuses : null,
			),
			static function ( $v ) {
				return null !== $v;
			}
		);

		if ( ! empty( $settings['sync_customers'] ) ) {
			$warnings[] = __( 'WPSyncSheets also synced Customers — StoreSheet syncs Customers in the StoreSheet Pro build.', 'storesheet' );
		}

		return new ImportPlan( $this->id(), $this->label(), $credentials, $spreadsheet, $settings, array(), $warnings );
	}

	public function supports_sheet_adopt(): bool {
		return true;
	}

	/**
	 * WPSyncSheets' per-resource sync toggles are exact 'yes'/'no' strings.
	 * Anything other than the literal 'yes' (including 'no' and absence) is
	 * treated as "not synced" and omitted from settings entirely — see
	 * array_filter above.
	 *
	 * @param mixed $value Raw option value.
	 */
	private function is_yes( $value ): bool {
		return 'yes' === $value;
	}

	/**
	 * Normalize a wpssw_sheets status key to a bare WC status slug. The real
	 * keys are display labels of the form "<Status> Orders" — e.g.
	 * 'Processing Orders', 'On Hold Orders', 'Completed Orders' (see
	 * wpsyncsheets-woocommerce class-wpsslw-settings.php default sheets). So:
	 * lowercase + trim, strip the trailing ' Orders' suffix, spaces to hyphens,
	 * strip a leading 'wc-'. Deliberately NOT ltrim()/trim() with a char-mask,
	 * which would corrupt a slug like 'cancelled' into 'ancelled'.
	 *
	 * @param string $raw Raw status label/key.
	 */
	private function normalize_status_slug( string $raw ): string {
		$slug = strtolower( trim( $raw ) );
		$slug = (string) preg_replace( '/\s+orders$/', '', $slug );
		$slug = str_replace( ' ', '-', $slug );
		return (string) preg_replace( '/^wc-/', '', $slug );
	}
}
