<?php
/**
 * Adapter for "WPGSI: Spreadsheet Integration".
 *
 * Config shapes below were confirmed against the free plugin's source
 * (wpgsi, v3.8.4; see .superpowers/sdd/competitor-wpgsi.md):
 *  - Unlike every other competitor here, WPGSI has no single global
 *    "the spreadsheet" option. Each configured sync is a published
 *    `wpgsiIntegration` custom post ("Integration"), carrying its own
 *    `SpreadsheetID` and `DataSourceID` post meta
 *    (admin/class-wpgsi-admin.php:1400-1410). A site can have zero, one, or
 *    many Integrations, each wired to its own event and its own spreadsheet.
 *  - `DataSourceID` classifies the feed: `wc-new_product` / `wc-edit_product`
 *    / `wc-delete_product` are the only WooCommerce product events; a
 *    dedicated Integration per WC order status is how "which statuses sync"
 *    is expressed — `wc-new_order` plus `wc-<status>` for each of pending,
 *    processing, on-hold, completed, cancelled, refunded, failed. There is no
 *    single order-statuses option to read; it must be unioned across every
 *    Integration post.
 *  - There is no Coupon, Customer, or Stock event in WPGSI at all, so this
 *    adapter never invents `sync_coupons` / `sync_customers` settings keys.
 *  - `wpgsi_google_credential` stores a complete Google service-account JSON
 *    key (private key included) used for a JWT-bearer 2-legged auth flow —
 *    structurally incompatible with StoreSheet's OAuth-based
 *    `GoogleOAuthClient`. It is never read here beyond an existence check;
 *    the user reconnects Google through StoreSheet's own flow instead.
 *  - `wpgsi_installed` is set unconditionally on every plugin activation
 *    (includes/class-wpgsi-activator.php:29-32), including a fresh install
 *    with zero credential and zero Integrations, so it is never used as a
 *    presence signal.
 *
 * @package StoreSheet
 */

declare( strict_types=1 );

namespace StoreSheet\Importer\Adapters;

defined( 'ABSPATH' ) || exit;

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

final class WpgsiAdapter implements SourceAdapter {

	private const POST_TYPE           = 'wpgsiIntegration';
	private const META_SPREADSHEET_ID = 'SpreadsheetID';
	private const META_DATA_SOURCE_ID = 'DataSourceID';
	private const OPTION_CREDENTIAL   = 'wpgsi_google_credential';

	/** The only three WooCommerce product-event DataSourceID values WPGSI exposes. */
	private const PRODUCT_EVENTS = array( 'wc-new_product', 'wc-edit_product', 'wc-delete_product' );

	/** Bare WC order-status slugs, matched against `wc-<status>` DataSourceID values. */
	private const ORDER_STATUS_PATTERN = '/^wc-(pending|processing|on-hold|completed|cancelled|refunded|failed)$/';

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

	public function label(): string {
		return __( 'WPGSI: Spreadsheet Integration', 'storesheet' );
	}

	public function plugin_files(): array {
		return array( 'wpgsi/wpgsi.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;
			}
		}

		// `wpgsi_installed` is a false-positive activation timestamp — never
		// use it. A non-empty credential is the plugin's own "configured"
		// gate (see class doc block above), never merely option-exists.
		$credential = get_option( self::OPTION_CREDENTIAL, false );

		return is_array( $credential ) && array() !== $credential;
	}

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

		// get_posts() against an unregistered post_type still queries the
		// posts table and simply returns no rows, so this is safe to call
		// whether or not WPGSI is active.
		$post_ids = get_posts(
			array(
				'post_type'   => self::POST_TYPE,
				'post_status' => 'publish',
				'numberposts' => -1,
				'fields'      => 'ids',
			)
		);

		$spreadsheet     = null;
		$spreadsheet_ids = array();
		$sync_products   = null;
		$sync_orders     = null;
		$order_statuses  = array();

		foreach ( $post_ids as $post_id ) {
			$spreadsheet_id = (string) get_post_meta( $post_id, self::META_SPREADSHEET_ID, true );
			$data_source_id = (string) get_post_meta( $post_id, self::META_DATA_SOURCE_ID, true );

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

			if ( in_array( $data_source_id, self::PRODUCT_EVENTS, true ) ) {
				$sync_products = true;
			}

			if ( 'wc-new_order' === $data_source_id ) {
				$sync_orders = true;
			} elseif ( preg_match( self::ORDER_STATUS_PATTERN, $data_source_id, $matches ) ) {
				$sync_orders      = true;
				$order_statuses[] = $matches[1];
			}
		}

		if ( count( $spreadsheet_ids ) > 1 ) {
			$warnings[] = __( 'WPGSI uses per-feed integrations that can target different spreadsheets; StoreSheet imported the first — review the target.', 'storesheet' );
		}

		$order_statuses = array_values( array_unique( $order_statuses ) );

		$settings = array_filter(
			array(
				'sync_products'  => $sync_products,
				'sync_orders'    => $sync_orders,
				'order_statuses' => array() !== $order_statuses ? $order_statuses : null,
			),
			static function ( $v ) {
				return null !== $v;
			}
		);

		// WPGSI authenticates via a locally stored Google service-account
		// private key — never a client secret StoreSheet's OAuth flow could
		// reuse. See class doc block above; never read past the presence
		// check in is_present().
		$credentials = null;
		$warnings[]  = __( 'WPGSI used a Google service account — connect your Google account in StoreSheet on the next step.', 'storesheet' );

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

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