<?php
/**
 * Turn 14 Supplier Implementation
 *
 * @package    Common
 * @subpackage Suppliers
 */

namespace MOWCPS\Common\Suppliers;

use MOWCPS\Common\Abstracts\Base_Supplier_App;
use MOWCPS\Common\Constants\Constants;
use MOWCPS\Common\Constants\Plugin_Filters;
use MOWCPS\Common\Models\Connection_Model;
use MOWCPS\Common\Models\Sync_Details_DAO;
use MOWCPS\Common\Models\Supplier_Model;
use MOWCPS\Common\Services\API\API_Service;
use MOWCPS\Common\Services\Authorization\Authorization_Service;
use MOWCPS\Common\Services\Cache\Cache_Service;
use MOWCPS\Common\Services\Logging\Supplier_Logger;
use WP_Error;

if ( ! defined( 'ABSPATH' ) ) {
	die;
}

/**
 * Class Turn14
 */
class Turn14 extends Base_Supplier_App {

	/**
	 * Cache directory path
	 */
	private const CACHE_DIR = MOWCPS_PLUGIN_DIR . 'cache' . DIRECTORY_SEPARATOR;

	/**
	 * Cache key for brands response. Cleared on Turn14 supplier update/delete.
	 */
	public const CACHE_KEY_BRANDS = 'mowcps_turn14_brands';

	/**
	 * Authorization Service instance
	 *
	 * @var Authorization_Service
	 */
	private $auth_service;

	/**
	 * Constructor
	 */
	public function __construct() {
		parent::__construct( Constants::SUPPLIER_APP_TYPE_TURN14 );
		$this->auth_service = new Authorization_Service();
	}

	/**
	 * Perform connection test for Turn 14
	 *
	 * @param array $supplier_data Connection details.
	 * @return array|WP_Error Success response or error.
	 */
	public function perform_connection_test( $supplier_data ) {
		$authorization_config = isset( $supplier_data['details'] ) ? $supplier_data['details'] : $supplier_data;

		// Validate only client credentials for test (no brands validation).
		if ( empty( $authorization_config['client_id'] ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'Client ID is required for Turn 14.' ),
			);
		}

		if ( empty( $authorization_config['client_secret'] ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'Client Secret is required for Turn 14.' ),
			);
		}

		$authorization_config['domain'] = $authorization_config['is_production'] ? '' : 'test';

		// Load and process configuration with dynamic parameters.
		$processed_config = $this->load_and_process_configuration( $authorization_config );
		if ( is_wp_error( $processed_config ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_CONFIG_LOADING_FAILED, $this->supplier_name, $processed_config->get_error_message() ),
			);
		}

		// Get authorization configuration from processed config.
		$authorization = $processed_config[ Constants::AUTHORIZATION ] ?? array();

		if ( empty( $authorization ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_NO_AUTH_CONFIG, $this->supplier_name ),
			);
		}

		// Get token endpoint configuration from processed config.
		$auth_settings     = $authorization['auth_settings'] ?? array();
		$request_settings  = $auth_settings['request_settings'] ?? array();
		$response_settings = $auth_settings['response_settings'] ?? array();

		$access_token_url = $request_settings['access_token_url'] ?? '';
		$client_id        = $authorization_config['client_id'] ?? $request_settings['client_id'] ?? '';
		$client_secret    = $authorization_config['client_secret'] ?? $request_settings['client_secret'] ?? '';
		$grant_type       = $request_settings['grant_type'] ?? Constants::OAUTH2_GRANT_TYPE_CLIENT_CREDENTIALS;

		if ( empty( $access_token_url ) || empty( $client_id ) || empty( $client_secret ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'Missing required OAuth2 configuration (access_token_url, client_id, client_secret)' ),
			);
		}

		// Prepare token request (Turn14 sends credentials in body).
		$request_data = array(
			'grant_type' => $grant_type,
		);

		$auth_headers = array(
			'Content-Type' => 'application/json',
		);

		$request_data['client_id']     = $client_id;
		$request_data['client_secret'] = $client_secret;

		// Make token request using API Service.
		$token_response = API_Service::make_api_call(
			$access_token_url,
			array(
				'method'  => Constants::HTTP_REQUEST_METHOD_POST,
				'headers' => $auth_headers,
				'body'    => wp_json_encode( $request_data ),
				'timeout' => 30,
			)
		);

		if ( is_wp_error( $token_response ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'OAuth2 authentication failed: ' . $token_response->get_error_message() ),
			);
		}

		$token_body = wp_remote_retrieve_body( $token_response );
		$token_data = json_decode( $token_body, true );
		$token_key  = $response_settings['token_key'] ?? Constants::DEFAULT_TOKEN_KEY;

		if ( ! $token_data || empty( $token_data[ $token_key ] ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'Failed to get OAuth2 access token. Response: ' . $token_body ),
			);
		}

		$access_token = $token_data[ $token_key ];// TODO :- Change OAuth Service to handle supplier_id = 0 and implement it here. RESTAPI-369

		// Test brands endpoint to verify token works and fetch all brands (cached by domain).
		$brands_response = $this->fetch_brands( $access_token, $authorization_config['domain'] );

		if ( is_wp_error( $brands_response ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, $brands_response->get_error_message() ),
			);
		}

		return $this->get_test_result(
			true,
			sprintf( Constants::SUPPLIER_AUTH_SUCCESSFUL, $this->supplier_name ),
			200,
			array( 'brands' => $brands_response )
		);
	}

	/**
	 * Validate supplier-specific configuration
	 *
	 * @param array $configuration Supplier configuration.
	 * @return true|WP_Error True on success, WP_Error on failure.
	 */
	public function validate_supplier_specific_configuration( $configuration ) {
		// Validate client credentials (always required).
		if ( empty( $configuration['client_id'] ) ) {
			return new WP_Error(
				'missing_client_id',
				'Client ID is required for Turn 14.'
			);
		}

		if ( empty( $configuration['client_secret'] ) ) {
			return new WP_Error(
				'missing_client_secret',
				'Client Secret is required for Turn 14.'
			);
		}

		// Validate brands only if sync_all_brands is explicitly set (indicating supplier creation, not test).
		// During test, sync_all_brands won't be present, so brands won't be validated.
		if ( isset( $configuration['sync_all_brands'] ) ) {
			$sync_all_brands = $configuration['sync_all_brands'];
			if ( is_string( $sync_all_brands ) ) {
				$sync_all_brands = filter_var( $sync_all_brands, FILTER_VALIDATE_BOOLEAN );
			}

			// If not syncing all brands, validate brand selection.
			if ( ! $sync_all_brands ) {
				$brands = $configuration['brands'] ?? $configuration['selected_brands'] ?? array();

				if ( empty( $brands ) || ! is_array( $brands ) ) {
					return new WP_Error(
						'no_brands_selected',
						'At least one brand must be selected when not syncing all brands.'
					);
				}
			}
		}

		return true;
	}

	/**
	 * Fetch brands from Turn 14 API. Result is cached and cleared on Turn14 supplier update/delete.
	 *
	 * @param string $access_token Access token.
	 * @param string $domain       Domain name ('test' or '' for production).
	 * @return array|WP_Error Brands array or error.
	 */
	private function fetch_brands( $access_token, $domain ) {
		$do_fetch = function () use ( $access_token, $domain ) {
			$brands_url = 'https://api' . $domain . '.turn14.com/v1/brands';

			$api_request = array(
				'method'  => Constants::HTTP_REQUEST_METHOD_GET,
				'headers' => array(
					'Authorization' => 'Bearer ' . $access_token,
					'Content-Type'  => 'application/json',
				),
				'timeout' => 30,
			);

			$response = API_Service::make_api_call( $brands_url, $api_request );

			if ( is_wp_error( $response ) ) {
				return new WP_Error(
					'brands_fetch_failed',
					'Failed to fetch brands: ' . $response->get_error_message()
				);
			}

			$status_code = wp_remote_retrieve_response_code( $response );

			if ( 200 !== $status_code ) {
				$response_body = json_decode( wp_remote_retrieve_body( $response ), true );
				$error_message = $response_body['message'] ?? 'Failed to fetch brands from Turn 14 API.';

				return new WP_Error(
					'brands_fetch_error',
					$error_message
				);
			}

			$body        = json_decode( wp_remote_retrieve_body( $response ), true );
			$brands_data = $body['data'] ?? array();

			// Transform brands to simple format: [{ id: "335", name: "3D MAXpider" }, ...]
			// Only include brands that have at least one purchase_restriction with your_status === "approved"
			$brands = array();
			if ( is_array( $brands_data ) ) {
				foreach ( $brands_data as $brand ) {
					$brand_id   = $brand['id'] ?? '';
					$brand_name = $brand['attributes']['name'] ?? '';

					// Check if brand has approved purchase_restrictions
					$attributes               = $brand['attributes'] ?? array();
					$pricegroups              = $attributes['pricegroups'] ?? array();
					$has_approved_restriction = false;

					// Check all pricegroups for this brand
					foreach ( $pricegroups as $pricegroup ) {
						$purchase_restrictions = $pricegroup['purchase_restrictions'] ?? array();

						// Check all purchase_restrictions in this pricegroup
						foreach ( $purchase_restrictions as $restriction ) {
							if ( isset( $restriction['your_status'] ) && 'approved' === $restriction['your_status'] ) {
								$has_approved_restriction = true;
								break 2; // Break out of both inner loops
							}
						}
					}

					// Only include brand if it has approved purchase_restrictions and valid id/name
					if ( ! empty( $brand_id ) && ! empty( $brand_name ) && $has_approved_restriction ) {
						$brands[] = array(
							'id'   => $brand_id,
							'name' => $brand_name,
						);
					}
				}
			}

			return $brands;
		};

		return Cache_Service::remember(
			self::CACHE_KEY_BRANDS,
			Cache_Service::DEFAULT_EXPIRATION,
			$do_fetch
		);
	}

	/**
	 * Extract max page info from API response (Post-API call)
	 *
	 * Extracts max page from links.last and stores in option table
	 *
	 * @param array $data Filter data from API service.
	 * @return array Modified data.
	 */
	public static function extract_brand_max_pages( $data ) {
		// Check event specifier
		if ( ! isset( $data['event_specifier'] ) || 'alter_curated_api_response_data' !== $data['event_specifier'] ) {
			return $data;
		}

		$supplier_id = Sync_Details_DAO::get_instance()->get_supplier_id();

		if ( ! self::is_turn14_supplier( $supplier_id ) ) {
			return $data;
		}

		$sync_all_brands = self::get_supplier_setting( $supplier_id, 'sync_all_brands' );
		if ( is_string( $sync_all_brands ) ) {
			$sync_all_brands = filter_var( $sync_all_brands, FILTER_VALIDATE_BOOLEAN );
		}

		if ( $sync_all_brands ) {
					return $data;
		}

		$response_body = $data['response_body'] ?? array();
		$last_link     = $response_body['links']['last'] ?? '';

		if ( empty( $last_link ) ) {
				return $data;
		}

		// Extract: /v1/items/brand/281?page=15
		preg_match( '/brand\/(\d+)/', $last_link, $brand_matches );
		preg_match( '/page=(\d+)/', $last_link, $page_matches );

		$brand_id = $brand_matches[1] ?? '';
		$max_page = isset( $page_matches[1] ) ? (int) $page_matches[1] : 0;

		if ( $brand_id && $max_page > 0 ) {
			$connection_id   = Sync_Details_DAO::get_instance()->get_connection_id();
			$connection      = Connection_Model::get_by_id( $connection_id );
			$connection_name = $connection['name'] ?? '';

			// Use connection-specific key to avoid conflicts between Items/Pricing/Stock
			$max_page_key = "mowcps_turn14_brand_{$brand_id}_{$connection_name}_max_page";
			update_option( $max_page_key, $max_page, false );

			Supplier_Logger::debug(
				$supplier_id,
				"Turn 14 {$connection_name}: Brand {$brand_id} has {$max_page} total pages"
			);
		}

		return $data;
	}

	/**
	 * Inject brand ID into pagination URL & switch brands when needed
	 *
	 * @param array $data Filter data from pagination service.
	 * @return array Modified data.
	 */
	public static function inject_brand_into_pagination_url( $data ) {
		// Check event specifier
		if ( ! isset( $data['event_specifier'] ) || 'pagination_url_alter' !== $data['event_specifier'] ) {
			return $data;
		}

		$supplier_id = Sync_Details_DAO::get_instance()->get_supplier_id();

		if ( ! self::is_turn14_supplier( $supplier_id ) ) {
			return $data;
		}

		$connection_id = Sync_Details_DAO::get_instance()->get_connection_id();

		$sync_all_brands = self::get_supplier_setting( $supplier_id, 'sync_all_brands' );
		if ( is_string( $sync_all_brands ) ) {
			$sync_all_brands = filter_var( $sync_all_brands, FILTER_VALIDATE_BOOLEAN );
		}

		if ( $sync_all_brands ) {
			return $data;
		}

		// Get cache (initialize if doesn't exist)
		$cache = self::get_brand_cache( $supplier_id );

		$connection      = Connection_Model::get_by_id( $connection_id );
		$connection_name = $connection['name'] ?? '';

		// Initialize cache if needed
		if ( empty( $cache ) || empty( $cache['brands'] ) ) {
			Supplier_Logger::debug(
				$supplier_id,
				"Turn 14 {$connection_name}: Cache not found, initializing..."
			);
			self::initialize_brand_cache( $supplier_id, $connection_id );
			$cache = self::get_brand_cache( $supplier_id );

			if ( empty( $cache ) || empty( $cache['brands'] ) ) {
				return $data; // Still no brands - nothing to process
			}
		}

		// Get current brand and page from cache
		$brand_id     = $cache['brands'][0];
		$current_page = $cache['current_page'] ?? 1;

		// Get max_page for this brand (stored after first API call)
		$max_page_key = "mowcps_turn14_brand_{$brand_id}_{$connection_name}_max_page";
		$max_page     = get_option( $max_page_key, 0 );

		// Build URL with brand
		$url          = $data['returned_url'];
		$endpoint_map = array(
			'Items'   => 'items',
			'Pricing' => 'pricing',
			'Stock'   => 'inventory',
			'Images'  => 'items/data',
		);

		$endpoint_path = $endpoint_map[ $connection_name ] ?? 'items';

		// Replace: /v1/items?page=X → /v1/items/brand/281?page=Y
		$pattern     = '#(/v1/' . $endpoint_path . ')(\?page=\d+|$)#';
		$replacement = '$1/brand/' . $brand_id . '?page=' . $current_page;
		$url         = preg_replace( $pattern, $replacement, $url );

		$data['returned_url'] = $url;

		Supplier_Logger::debug(
			$supplier_id,
			"Turn 14 {$connection_name}: Brand {$brand_id} - Page {$current_page}" . ( $max_page > 0 ? " of {$max_page}" : '' ) . " → {$url}"
		);

		// DON'T increment here! Will increment in handle_process_completion AFTER successful processing
		// This makes it restart-safe - if sync aborts, same page is retried

		return $data;
	}

	/**
	 * Clean cache before fresh sync starts
	 *
	 * Runs when user manually starts sync, ensuring clean slate
	 *
	 * @param array $data Action data with supplier_id and connection_id.
	 * @return void
	 */
	public static function clean_cache_before_sync( $data ) {
		$supplier_id = $data['supplier_id'] ?? null;

		if ( ! $supplier_id || ! self::is_turn14_supplier( $supplier_id ) ) {
			return;
		}

		$connection_id = $data['connection_id'] ?? null;
		if ( ! $connection_id ) {
			return;
		}

		$connection      = Connection_Model::get_by_id( $connection_id );
		$connection_name = $connection['name'] ?? 'Unknown';

		// Clear cache for all connections to ensure fresh start
		self::delete_brand_cache( $supplier_id );

		Supplier_Logger::debug(
			$supplier_id,
			"Turn 14 {$connection_name}: Fresh sync starting. Cleaned old cache for clean start."
		);
	}

	/**
	 * Handle batch completion
	 *
	 * @param array $data Process completion data.
	 * @return array Modified data with updated next_process_flag.
	 */
	public static function handle_process_completion( $data ) {
		// Check event specifier
		if ( ! isset( $data['event_specifier'] ) || Plugin_Filters::EVENT_SUPPLIER_BATCH_COMPLETION !== $data['event_specifier'] ) {
			return $data;
		}

		$supplier_id = $data['supplier_id'];

		if ( ! self::is_turn14_supplier( $supplier_id ) ) {
			return $data;
		}

		$connection_id = Sync_Details_DAO::get_instance()->get_connection_id();

		if ( ! $connection_id ) {
			return $data;
		}

		$sync_all_brands = self::get_supplier_setting( $supplier_id, 'sync_all_brands' );
		if ( is_string( $sync_all_brands ) ) {
			$sync_all_brands = filter_var( $sync_all_brands, FILTER_VALIDATE_BOOLEAN );
		}

		if ( $sync_all_brands ) {
			return $data; // Let default flow handle
		}

		$connection      = Connection_Model::get_by_id( $connection_id );
		$connection_name = $connection['name'] ?? 'Unknown';

		// Get cache (already updated by handle_final_sync_end_status)
		$cache = self::get_brand_cache( $supplier_id );

		if ( empty( $cache['brands'] ) ) {
			// No brands - move to next connection
			Supplier_Logger::debug(
				$supplier_id,
				"Turn 14 {$connection_name}: No brands in cache. Moving to next connection..."
			);

			$data['next_process_flag'] = Constants::PROCESS_COMPLETED;
		} else {
			// More brands/pages to process - continue pagination
			Supplier_Logger::debug(
				$supplier_id,
				"Turn 14 {$connection_name}: More brands to process. Setting next_process_flag to INITIATE_PAGE_SYNC"
			);

			$data['next_process_flag'] = Constants::INITIATE_PAGE_SYNC;
		}

		return $data;
	}

	/**
	 * Handle final sync end status modification.
	 *
	 * Updates cache (increments page, checks brand completion), then checks if all brands
	 * are completed for the connection and returns "Sync Completed" instead of "Page X completed"
	 * when appropriate.
	 *
	 * @param array $data Filter data containing sync_end_status and other parameters.
	 * @return array Modified data with updated sync_end_status.
	 */
	public static function handle_final_sync_end_status( $data ) {
		// Check event specifier
		if ( ! isset( $data['event_specifier'] ) || Plugin_Filters::EVENT_ALTER_SYNC_END_STATUS_FINAL !== $data['event_specifier'] ) {
			return $data;
		}

		$supplier_id = $data['supplier_id'];

		if ( ! self::is_turn14_supplier( $supplier_id ) ) {
			return $data;
		}

		$connection_id = $data['connection_id'] ?? null;

		if ( ! $connection_id ) {
			return $data;
		}

		$sync_all_brands = self::get_supplier_setting( $supplier_id, 'sync_all_brands' );
		if ( is_string( $sync_all_brands ) ) {
			$sync_all_brands = filter_var( $sync_all_brands, FILTER_VALIDATE_BOOLEAN );
		}

		if ( $sync_all_brands ) {
			return $data; // Let default flow handle
		}

		$connection      = Connection_Model::get_by_id( $connection_id );
		$connection_name = $connection['name'] ?? 'Unknown';

		// Get cache
		$cache = self::get_brand_cache( $supplier_id );

		// Only process if we have brands and the status indicates a page was completed
		if ( ! empty( $cache['brands'] ) && preg_match( '/^Page .+ completed$/', $data['sync_end_status'] ) ) {
			// Page was successfully processed - increment (restart-safe!)
			++$cache['current_page'];

			$brand_id     = $cache['brands'][0];
			$max_page_key = "mowcps_turn14_brand_{$brand_id}_{$connection_name}_max_page";
			$max_page     = get_option( $max_page_key, 0 );

			// Check if current brand is done
			if ( $max_page > 0 && $cache['current_page'] > $max_page ) {
				// Brand completed - remove it
				array_shift( $cache['brands'] );
				$cache['current_page'] = 1; // Reset for next brand
				delete_option( $max_page_key );
			}

			// Check if all brands done
			if ( empty( $cache['brands'] ) ) {
				// All brands completed - delete cache
				self::delete_brand_cache( $supplier_id );

				Supplier_Logger::debug(
					$supplier_id,
					"Turn 14 {$connection_name}: All brands completed. Changing sync_end_status from '{$data['sync_end_status']}' to 'Sync Completed'"
				);

				// Update connection status to "Connection Sync Completed"
				$connection_analytics = Sync_Details_DAO::get_instance()->get_connection_analytics( $supplier_id, null, $connection_id );
				if ( $connection_analytics ) {
					$connection_analytics->sync_status_message = Constants::CONNECTION_SYNC_COMPLETED;
					$connection_analytics->sync_status_code    = Constants::COMPLETED_SYNC_RUNNING_STATUS;
					$connection_analytics->sync_end_time       = time();
					$connection_analytics->initiate_sync       = false;
					$connection_analytics->save();
				}

				$data['sync_end_status'] = Constants::COMPLETED_SYNC_RUNNING_STATUS;
			} else {
				// Save cache and continue pagination
				self::update_brand_cache( $supplier_id, $cache );

				Supplier_Logger::debug(
					$supplier_id,
					"Turn 14 {$connection_name}: Continuing with brand {$cache['brands'][0]}, page {$cache['current_page']}"
				);
			}
		} elseif ( ( empty( $cache ) || empty( $cache['brands'] ) ) && preg_match( '/^Page .+ completed$/', $data['sync_end_status'] ) ) {
			// Cache is already empty (all brands done) - just update the status
			$original_status         = $data['sync_end_status'];
			$data['sync_end_status'] = Constants::COMPLETED_SYNC_RUNNING_STATUS;

			Supplier_Logger::debug(
				$supplier_id,
				"Turn 14 {$connection_name}: All brands completed. Changing sync_end_status from '{$original_status}' to 'Sync Completed'"
			);
		}

		return $data;
	}

	/**
	 * Get brand cache
	 *
	 * @param int $supplier_id Supplier ID.
	 * @return array Cache with brands and current_page.
	 */
	private static function get_brand_cache( $supplier_id ) {
		$cache_file = self::CACHE_DIR . "turn14_brands_{$supplier_id}.json";

		if ( ! file_exists( $cache_file ) ) {
			return array();
		}

		$contents = file_get_contents( $cache_file );
		$cache    = json_decode( $contents, true ) ?? array();

		if ( is_array( $cache ) && isset( $cache['brands'] ) && isset( $cache['current_page'] ) ) {
			return $cache;
		}

		if ( ! empty( $cache ) && is_array( $cache ) && ! isset( $cache['brands'] ) ) {
			return array(
				'brands'       => $cache,
				'current_page' => 1,
			);
		}

		return array();
	}

	/**
	 * Update brand cache
	 *
	 * @param int   $supplier_id Supplier ID.
	 * @param array $cache       Cache data with brands and current_page.
	 * @return void
	 */
	private static function update_brand_cache( $supplier_id, $cache ) {
		if ( ! file_exists( self::CACHE_DIR ) ) {
			wp_mkdir_p( self::CACHE_DIR );
		}

		$cache_file = self::CACHE_DIR . "turn14_brands_{$supplier_id}.json";
		file_put_contents( $cache_file, wp_json_encode( $cache ) );
	}

	/**
	 * Delete brand cache
	 *
	 * @param int $supplier_id Supplier ID.
	 * @return void
	 */
	private static function delete_brand_cache( $supplier_id ) {
		$cache_file = self::CACHE_DIR . "turn14_brands_{$supplier_id}.json";

		if ( file_exists( $cache_file ) ) {
			unlink( $cache_file );
		}
	}

	/**
	 * Get current brand ID being processed
	 *
	 * @param int $supplier_id   Supplier ID.
	 * @param int $connection_id Connection ID.
	 * @return string|null Current brand ID or null.
	 */
	private static function get_current_brand_id( $supplier_id, $connection_id ) {
		$cache = self::get_brand_cache( $supplier_id );

		$connection = Connection_Model::get_by_id( $connection_id );

		// Initialize cache if needed (each connection creates its own cache)
		if ( empty( $cache ) || empty( $cache['brands'] ) ) {
			$connection_name = $connection['name'] ?? 'Unknown';
			Supplier_Logger::debug(
				$supplier_id,
				"Turn 14 {$connection_name}: Cache not found, initializing for this connection..."
			);
			self::initialize_brand_cache( $supplier_id, $connection_id );
			$cache = self::get_brand_cache( $supplier_id );
		}

		// Current brand is always first in brands array
		return ! empty( $cache['brands'] ) ? $cache['brands'][0] : null;
	}

	/**
	 * Initialize brand cache with selected brands
	 *
	 * @param int $supplier_id   Supplier ID.
	 * @param int $connection_id Connection ID.
	 * @return void
	 */
	private static function initialize_brand_cache( $supplier_id, $connection_id ) {
		$selected_brands = self::get_supplier_setting( $supplier_id, 'brands' );
		$brand_ids       = is_string( $selected_brands ) ? json_decode( $selected_brands, true ) : $selected_brands;

		if ( empty( $brand_ids ) || ! is_array( $brand_ids ) ) {
			Supplier_Logger::debug(
				$supplier_id,
				'Turn 14: No brands found in settings'
			);
			return;
		}

		// Create cache with brands and current_page
		$cache = array(
			'brands'       => $brand_ids,
			'current_page' => 1,
		);

		self::update_brand_cache( $supplier_id, $cache );

		$connection      = Connection_Model::get_by_id( $connection_id );
		$connection_name = $connection['name'] ?? 'Unknown';

		Supplier_Logger::debug(
			$supplier_id,
			"Turn 14 {$connection_name}: Initialized cache with " . count( $brand_ids ) . ' brands: ' . implode( ', ', $brand_ids )
		);
	}

	/**
	 * Check if supplier is Turn 14
	 *
	 * @param int $supplier_id Supplier ID.
	 * @return bool True if Turn 14 supplier.
	 */
	private static function is_turn14_supplier( $supplier_id ) {
		$supplier = Supplier_Model::get_by_id( $supplier_id );
		return ! empty( $supplier ) && 'turn14' === strtolower( $supplier['app_type'] );
	}

	/**
	 * Get supplier setting value from details field
	 *
	 * @param int    $supplier_id Supplier ID.
	 * @param string $key         Setting key.
	 * @return mixed Setting value or null.
	 */
	private static function get_supplier_setting( $supplier_id, $key ) {
		// Get supplier details from suppliers table.
		$supplier = Supplier_Model::get_by_id( $supplier_id );
		if ( ! $supplier ) {
			return null;
		}

		$details = $supplier['details'] ?? null;

		if ( ! empty( $details ) ) {
			if ( is_string( $details ) ) {
				$details = json_decode( $details, true );
			}

			if ( is_array( $details ) && isset( $details[ $key ] ) ) {
				return $details[ $key ];
			}
		}

		return null;
	}

	/**
	 * Modify stock quantity for Turn14 products at get_stock time.
	 *
	 * Uses manufacturer stock instead of warehouse inventory if available.
	 * This runs at the time of reading stock from API data, before it's mapped.
	 *
	 * @param array $data Filter data containing product data.
	 * @return array Modified data with updated product_data.
	 */
	public static function modify_turn14_stock_quantity( $data ) {
		if ( Plugin_Filters::EVENT_MODIFY_STOCK_QUANTITY !== $data['event_specifier'] ) {
			return $data;
		}

		$supplier_id = Sync_Details_DAO::get_instance()->get_supplier_id();

		if ( ! self::is_turn14_supplier( $supplier_id ) ) {
			return $data;
		}

		$connection_name = $data['product_data']['type'] ?? '';

		// Only process for Stock connection.
		if ( 'InventoryItem' !== $connection_name ) {
			return $data;
		}
		$product_data = $data['product_data'];
		if ( ! isset( $product_data['attributes'] ) ) {
			return $data;
		}
		$attributes = $product_data['attributes'];
		$final_qty  = 0;

		// If manufacturer stock is available, use it; otherwise sum the inventory array.
		if ( isset( $attributes['manufacturer']['stock'] ) ) {
			$final_qty = (int) $attributes['manufacturer']['stock'];

			Supplier_Logger::debug(
				$supplier_id,
				'Turn14: Using manufacturer stock (' . $final_qty . ') for product SKU: ' . ( $product_data['id'] ?? 'N/A' )
			);
		} elseif ( isset( $attributes['inventory'] ) && is_array( $attributes['inventory'] ) ) {
			$final_qty = (int) array_sum( $attributes['inventory'] );

			Supplier_Logger::debug(
				$supplier_id,
				'Turn14: Using summed inventory (' . $final_qty . ') for product SKU: ' . ( $product_data['id'] ?? 'N/A' )
			);
		}
		if ( ! isset( $product_data['attributes']['inventory'] ) ) {
			$product_data['attributes']['inventory'] = array();
		}
		$product_data['attributes']['inventory']['01'] = $final_qty;
		$data['product_data']                          = $product_data;

		return $data;
	}
}
