<?php
/**
 * Google Sheets Order Sync Manager
 *
 * @package ShopExplorer\GoogleSheets
 * @since 1.0.0
 */

namespace SHOPEXPLORER\GoogleSheets;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Order Sync Manager class
 *
 * Handles syncing WooCommerce orders to Google Sheets
 *
 * @since 1.0.0
 */
class SHOPEX_OrderSyncManager {

	/**
	 * Service Account Auth instance
	 *
	 * @var ServiceAccountAuth
	 */
	private $auth_manager;

	/**
	 * Constructor
	 */
	public function __construct() {
		$this->auth_manager = new SHOPEX_ServiceAccountAuth();
	}

	/**
	 * Get available order fields for syncing
	 *
	 * @return array
	 */
	public function get_available_fields() {
		return [
			'order_id' => [
				'label' => __( 'Order ID', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => true, // Always enabled
			],
			'order_status' => [
				'label' => __( 'Order Status', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_order_status', true ),
			],
			'order_total' => [
				'label' => __( 'Total Price', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_order_total', true ),
			],
			'product_names' => [
				'label' => __( 'Product Names', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_product_names', true ),
			],
			'product_skus' => [
				'label' => __( 'Product SKUs', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_product_skus', false ),
			],
			'total_items' => [
				'label' => __( 'Total Items', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_total_items', false ),
			],
			'customer_name' => [
				'label' => __( 'Customer Name', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_customer_name', true ),
			],
			'customer_email' => [
				'label' => __( 'Customer Email', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_customer_email', false ),
			],
			'order_date' => [
				'label' => __( 'Order Date', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_order_date', true ),
			],
			'payment_method' => [
				'label' => __( 'Payment Method', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_payment_method', false ),
			],
			'billing_address' => [
				'label' => __( 'Billing Address', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_billing_address', false ),
			],
			'shipping_address' => [
				'label' => __( 'Shipping Address', 'shop-explorer' ),
				'type' => 'core',
				'enabled' => get_option( 'shopex_sync_shipping_address', false ),
			],
		];
	}

	/**
	 * Get enabled fields only
	 *
	 * @return array
	 */
	public function get_enabled_fields() {
		$fields = $this->get_available_fields();
		return array_filter( $fields, function ( $field ) {
			return $field['enabled'];
		});
	}

	/**
	 * Get column headers for Google Sheets
	 *
	 * @return array
	 */
	public function get_column_headers() {
		$enabled_fields = $this->get_enabled_fields();
		return array_column( $enabled_fields, 'label' );
	}

	/**
	 * Get current field settings
	 *
	 * @return array
	 */
	public function get_field_settings() {
		return $this->get_available_fields();
	}

	/**
	 * Update field settings
	 *
	 * @param array $field_settings Field settings
	 * @return bool
	 */
	public function update_field_settings( $field_settings ) {
		$available_fields = $this->get_available_fields();

		foreach ( $field_settings as $field_key => $enabled ) {
			if ( isset( $available_fields[ $field_key ] ) && $field_key !== 'order_id' ) {
				update_option( 'shopex_sync_' . $field_key, (bool) $enabled );
			}
		}

		return true;
	}

	/**
	 * Get all orders data for syncing
	 *
	 * @param array $args Query arguments
	 * @return array
	 */
	public function get_orders_data( $args = [] ) {
		$default_args = [
			'limit' => -1,
			'status' => 'any',
			'return' => 'objects',
		];

		$args = wp_parse_args( $args, $default_args );

		if ( ! function_exists( 'wc_get_orders' ) ) {
			return [];
		}

		$orders = wc_get_orders( $args );
		$orders_data = [];

		foreach ( $orders as $order ) {
			$orders_data[] = $this->format_order_data( $order );
		}

		return $orders_data;
	}

	/**
	 * Format single order data
	 *
	 * @param \WC_Order $order WooCommerce order object
	 * @return array
	 */
	public function format_order_data( $order ) {
		$enabled_fields = $this->get_enabled_fields();
		$order_data = [];

		foreach ( array_keys( $enabled_fields ) as $field_key ) {
			switch ( $field_key ) {
				case 'order_id':
					$order_data[] = $order->get_id();
					break;

				case 'order_status':
					$order_data[] = ucfirst( $order->get_status() );
					break;

				case 'order_total':
					$order_data[] = $order->get_total();
					break;

				case 'product_names':
					$product_names = [];
					foreach ( $order->get_items() as $item ) {
						$product_names[] = $item->get_name();
					}
					$order_data[] = implode( ', ', $product_names );
					break;

				case 'product_skus':
					$product_skus = [];
					foreach ( $order->get_items() as $item ) {
						$product = $item->get_product();
						if ( $product ) {
							$sku = $product->get_sku();
							if ( $sku ) {
								$product_skus[] = $sku;
							}
						}
					}
					$order_data[] = implode( ', ', $product_skus );
					break;

				case 'total_items':
					$order_data[] = $order->get_item_count();
					break;

				case 'customer_name':
					if ( $order instanceof \WC_Order_Refund ) {
						$parent_order = wc_get_order( $order->get_parent_id() );
						$order_data[] = $parent_order ? trim( $parent_order->get_billing_first_name() . ' ' . $parent_order->get_billing_last_name() ) : '';
					} else {
						$order_data[] = trim( $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() );
					}
					break;

				case 'customer_email':
					if ( $order instanceof \WC_Order_Refund ) {
						$parent_order = wc_get_order( $order->get_parent_id() );
						$order_data[] = $parent_order ? $parent_order->get_billing_email() : '';
					} else {
						$order_data[] = $order->get_billing_email();
					}
					break;

				case 'order_date':
					$date = $order->get_date_created();
					$order_data[] = $date ? $date->date( 'Y-m-d H:i:s' ) : '';
					break;

				case 'payment_method':
					if ( $order instanceof \WC_Order_Refund ) {
						$parent_order = wc_get_order( $order->get_parent_id() );
						$order_data[] = $parent_order && method_exists( $parent_order, 'get_payment_method_title' ) ? $parent_order->get_payment_method_title() : '';
					} else {
						$order_data[] = method_exists( $order, 'get_payment_method_title' ) ? $order->get_payment_method_title() : '';
					}
					break;

				case 'billing_address':
					if ( $order instanceof \WC_Order_Refund ) {
						$parent_order = wc_get_order( $order->get_parent_id() );
						$billing = $parent_order ? $parent_order->get_formatted_billing_address() : '';
					} else {
						$billing = $order->get_formatted_billing_address();
					}
					$order_data[] = str_replace( '<br/>', ', ', $billing );
					break;

				case 'shipping_address':
					if ( $order instanceof \WC_Order_Refund ) {
						$parent_order = wc_get_order( $order->get_parent_id() );
						$shipping = $parent_order ? $parent_order->get_formatted_shipping_address() : '';
					} else {
						$shipping = $order->get_formatted_shipping_address();
					}
					$order_data[] = str_replace( '<br/>', ', ', $shipping );
					break;

				default:
					$order_data[] = '';
					break;
			}
		}

		return $order_data;
	}

	/**
	 * Sync all orders to Google Sheets
	 *
	 * @param string $spreadsheet_id Google Sheets spreadsheet ID
	 * @param string $sheet_name Sheet name/tab
	 * @return array Result with success status and message
	 */
	public function sync_all_orders( $spreadsheet_id, $sheet_name = 'Orders' ) {
		try {
			if ( ! $this->auth_manager->has_credentials() ) {
				return [
					'success' => false,
					'message' => __( 'Google Sheets credentials not configured. Please configure your service account credentials.', 'shop-explorer' ),
				];
			}

			// Get access token
			$access_token = $this->auth_manager->get_access_token();
			if ( ! $access_token ) {
				return [
					'success' => false,
					'message' => __( 'Failed to get access token. Please check your credentials.', 'shop-explorer' ),
				];
			}

			// Get orders data
			$orders_data = $this->get_orders_data();
			if ( empty( $orders_data ) ) {
				return [
					'success' => false,
					'message' => __( 'No orders found to sync.', 'shop-explorer' ),
				];
			}

			// Prepare data with headers
			$headers = $this->get_column_headers();
			$sheet_data = array_merge( [ $headers ], $orders_data );

			// Clear existing data and add new data
			$this->clear_sheet( $access_token, $spreadsheet_id, $sheet_name );
			$result = $this->write_to_sheet( $access_token, $spreadsheet_id, $sheet_name, $sheet_data );

			if ( $result ) {
				return [
					'success' => true,
					/* translators: %s: is the product id */
					'message' => sprintf( __( 'Successfully synced %d orders to Google Sheets.', 'shop-explorer' ), count( $orders_data ) ),
					'synced_count' => count( $orders_data ),
				];
			} else {
				return [
					'success' => false,
					'message' => __( 'Failed to write data to Google Sheets. Please check spreadsheet permissions.', 'shop-explorer' ),
				];
			}
		} catch ( \Exception $e ) {
			return [
				'success' => false,
				'message' => __( 'Failed to sync orders: ', 'shop-explorer' ) . $e->getMessage(),
			];
		}
	}

	/**
	 * Sync single order to Google Sheets
	 *
	 * @param int    $order_id Order ID
	 * @param string $spreadsheet_id Google Sheets spreadsheet ID
	 * @param string $sheet_name Sheet name/tab
	 * @return array Result with success status and message
	 */
	public function sync_single_order( $order_id, $spreadsheet_id, $sheet_name = 'Orders' ) {
		try {
			$order = wc_get_order( $order_id );
			if ( ! $order ) {
				return [
					'success' => false,
					'message' => __( 'Order not found.', 'shop-explorer' ),
				];
			}

			if ( ! $this->auth_manager->has_credentials() ) {
				return [
					'success' => false,
					'message' => __( 'Google Sheets credentials not configured.', 'shop-explorer' ),
				];
			}

			$access_token = $this->auth_manager->get_access_token();
			if ( ! $access_token ) {
				return [
					'success' => false,
					'message' => __( 'Failed to get access token.', 'shop-explorer' ),
				];
			}

			// Format order data
			$order_data = $this->format_order_data( $order );

			// Find existing row or append new one
			$existing_data = $this->get_sheet_data( $access_token, $spreadsheet_id, $sheet_name );
			$row_index = $this->find_order_row( $existing_data, $order_id );

			if ( $row_index !== null ) {
				// Update existing row
				$result = $this->update_sheet_row( $access_token, $spreadsheet_id, $sheet_name, $row_index, $order_data );
			} else {
				// Append new row
				$result = $this->append_to_sheet( $access_token, $spreadsheet_id, $sheet_name, [ $order_data ] );
			}

			if ( $result ) {
				return [
					'success' => true,
					/* translators: %s: is the product id */
					'message' => sprintf( __( 'Successfully synced order #%d to Google Sheets.', 'shop-explorer' ), $order_id ),
				];
			} else {
				return [
					'success' => false,
					'message' => __( 'Failed to write data to Google Sheets.', 'shop-explorer' ),
				];
			}
		} catch ( \Exception $e ) {
			return [
				'success' => false,
				'message' => __( 'Failed to sync order: ', 'shop-explorer' ) . $e->getMessage(),
			];
		}
	}

	/**
	 * Clear sheet data
	 *
	 * @param string $access_token Access token
	 * @param string $spreadsheet_id Spreadsheet ID
	 * @param string $sheet_name Sheet name
	 * @return bool
	 */
	private function clear_sheet( $access_token, $spreadsheet_id, $sheet_name ) {
		$api_url = "https://sheets.googleapis.com/v4/spreadsheets/{$spreadsheet_id}/values/{$sheet_name}:clear";

		$response = \wp_remote_post( $api_url, [
			'headers' => [
				'Authorization' => 'Bearer ' . $access_token,
				'Content-Type' => 'application/json',
			],
			'timeout' => 30,
		] );

		return ! \is_wp_error( $response ) && \wp_remote_retrieve_response_code( $response ) === 200;
	}

	/**
	 * Write data to sheet
	 *
	 * @param string $access_token Access token
	 * @param string $spreadsheet_id Spreadsheet ID
	 * @param string $sheet_name Sheet name
	 * @param array  $data Data to write
	 * @return bool
	 */
	private function write_to_sheet( $access_token, $spreadsheet_id, $sheet_name, $data ) {
		$api_url = "https://sheets.googleapis.com/v4/spreadsheets/{$spreadsheet_id}/values/{$sheet_name}?valueInputOption=USER_ENTERED";

		$response = \wp_remote_request( $api_url, [
			'method' => 'PUT',
			'headers' => [
				'Authorization' => 'Bearer ' . $access_token,
				'Content-Type' => 'application/json',
			],
			'body' => \json_encode( [
				'values' => $data,
			] ),
			'timeout' => 30,
		] );

		return ! \is_wp_error( $response ) && \wp_remote_retrieve_response_code( $response ) === 200;
	}

	/**
	 * Append data to sheet
	 *
	 * @param string $access_token Access token
	 * @param string $spreadsheet_id Spreadsheet ID
	 * @param string $sheet_name Sheet name
	 * @param array  $data Data to append
	 * @return bool
	 */
	private function append_to_sheet( $access_token, $spreadsheet_id, $sheet_name, $data ) {
		$api_url = "https://sheets.googleapis.com/v4/spreadsheets/{$spreadsheet_id}/values/{$sheet_name}:append?valueInputOption=USER_ENTERED";

		$response = \wp_remote_post( $api_url, [
			'headers' => [
				'Authorization' => 'Bearer ' . $access_token,
				'Content-Type' => 'application/json',
			],
			'body' => \json_encode( [
				'values' => $data,
			] ),
			'timeout' => 30,
		] );

		return ! \is_wp_error( $response ) && \wp_remote_retrieve_response_code( $response ) === 200;
	}

	/**
	 * Get sheet data
	 *
	 * @param string $access_token Access token
	 * @param string $spreadsheet_id Spreadsheet ID
	 * @param string $sheet_name Sheet name
	 * @return array|null
	 */
	private function get_sheet_data( $access_token, $spreadsheet_id, $sheet_name ) {
		$api_url = "https://sheets.googleapis.com/v4/spreadsheets/{$spreadsheet_id}/values/{$sheet_name}";

		$response = \wp_remote_get( $api_url, [
			'headers' => [
				'Authorization' => 'Bearer ' . $access_token,
			],
			'timeout' => 30,
		] );

		if ( \is_wp_error( $response ) || \wp_remote_retrieve_response_code( $response ) !== 200 ) {
			return null;
		}

		$body = \wp_remote_retrieve_body( $response );
		$data = \json_decode( $body, true );

		return isset( $data['values'] ) ? $data['values'] : null;
	}

	/**
	 * Find order row in sheet data
	 *
	 * @param array $sheet_data Sheet data
	 * @param int   $order_id Order ID to find
	 * @return int|null Row index (1-based) or null if not found
	 */
	private function find_order_row( $sheet_data, $order_id ) {
		if ( ! $sheet_data ) {
			return null;
		}

		foreach ( $sheet_data as $index => $row ) {
			if ( isset( $row[0] ) && $row[0] === $order_id ) {
				return $index + 1; // Google Sheets uses 1-based indexing
			}
		}

		return null;
	}

	/**
	 * Update specific row in sheet
	 *
	 * @param string $access_token Access token
	 * @param string $spreadsheet_id Spreadsheet ID
	 * @param string $sheet_name Sheet name
	 * @param int    $row_index Row index (1-based)
	 * @param array  $data Row data
	 * @return bool
	 */
	private function update_sheet_row( $access_token, $spreadsheet_id, $sheet_name, $row_index, $data ) {
		$range = "{$sheet_name}!A{$row_index}";
		$api_url = "https://sheets.googleapis.com/v4/spreadsheets/{$spreadsheet_id}/values/{$range}?valueInputOption=USER_ENTERED";

		$response = \wp_remote_request( $api_url, [
			'method' => 'PUT',
			'headers' => [
				'Authorization' => 'Bearer ' . $access_token,
				'Content-Type' => 'application/json',
			],
			'body' => \json_encode( [
				'values' => [ $data ],
			] ),
			'timeout' => 30,
		] );

		return ! \is_wp_error( $response ) && \wp_remote_retrieve_response_code( $response ) === 200;
	}
}
