<?php
/**
 * The IAB related functionality of the plugin.
 *
 * @link       https://www.webtoffee.com/
 * @since      3.0.0
 *
 * @package    WebToffee
 * @subpackage CookieConsent/IAB class
 */

namespace WebToffee\CookieConsent\Lite\Frontend\Modules\Iab;

use WebToffee\CookieConsent\Lite\Admin\Modules\Banners\Includes\Controller;
use WebToffee\CookieConsent\Lite\Admin\Modules\Settings\Includes\Settings;
// Importing the finfo class from the global namespace
use finfo;
/**
 * The IAB related functionality of the plugin.
 *
 * Defines the plugin name, version, and two examples hooks for how to
 * enqueue the iab stylesheet and JavaScript.
 *
 * @package    WebToffee
 * @subpackage WebToffee\CookieConsent\Lite\Frontend
 * @author     WebToffee <info@webtoffee.com>
 */
class IAB {

	/**
	 * The ID of this plugin.
	 *
	 * @since    3.0.0
	 * @access   private
	 * @var      string    $plugin_name  The ID of this plugin.
	 */
	private $plugin_name;

	/**
	 * The version of this plugin.
	 *
	 * @since    3.0.0
	 * @access   private
	 * @var      string    $version    The current version of this plugin.
	 */
	private $version;

	/**
	 * Banner object
	 *
	 * @var object
	 */
	protected $banner;
	/**
	 * Banners array
	 *
	 * array
	 */
	protected $banners = array();

	/**
	 * Plugin settings
	 *
	 * @var object
	 */
	protected $settings;
	/**
	 * IAB vendor list directory path
	 *
	 * @var string $list_url
	 */
	public $list_url;
	/**
	 * $enabled
	 *
	 * @var boolean $enabled
	 */
	public $enabled = true;
	/**
	 * Instance of the current class
	 *
	 * @var object
	 */
	private static $instance;
	/**
	 * Initialize the class and set its properties.
	 *
	 * @since    3.0.0
	 * @param      string $plugin_name       The name of the plugin.
	 * @param      string $version    The version of this plugin.
	 */
	/**
	 * Return the current instance of the class
	 *
	 * @return object
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}
	public function __construct( $plugin_name = 'webtoffee-cookie-consent' ) {

		$this->plugin_name = $plugin_name;
		$this->settings    = new Settings();
		$is_iab_banner     = false;
		$this->banners     = Controller::get_instance()->get_active_banners();
		foreach ( $this->banners as $key => $banner ) {
			$banner_settings = $banner->get_settings();
			$is_iab_enabled  = isset( $banner_settings['settings']['iab_enabled'] ) ? $banner_settings['settings']['iab_enabled'] : false;
			if ( $is_iab_enabled ) {
				$is_iab_banner = true;
			}
		}
		$this->enabled  = $is_iab_banner;
		$this->list_url = 'https://cdn.webtoffee.com/iab-tcf/cmp/v3/';
		add_action( 'init', array( $this, 'init' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
	}
	public function init() {
		if ( ! $this->enabled ) {
			return;
		}
		$this->maybe_update_vendor_list();
	}
	/**
	 * checks whether vendor_list file updated needed.
	 *
	 * @return void
	 */
	public function maybe_update_vendor_list() {
		if ( ! get_transient( 'wcc_vendor_file_update' ) ) {
			$this->update_vendor_list();
			//Clear cache
			$languages = wcc_i18n_selected_languages();
			self::wcc_delete_vendors_cache();
			foreach ( $languages as $lang ) {
				self::wcc_delete_vendors_cache( $lang );
			}
		}
	}

	/**
	 * Enqueue IAB scripts
	 *
	 * @return void
	 */
	public function enqueue_scripts() {
		$is_iab_banner  = false;
		$is_gac_enabled = false;
		$this->banners  = Controller::get_instance()->get_active_banners();
		foreach ( $this->banners as $key => $banner ) {
			$banner_settings       = $banner->get_settings();
			$is_iab_enabled        = isset( $banner_settings['settings']['iab_enabled'] ) ? $banner_settings['settings']['iab_enabled'] : false;
			$is_google_acm_enabled = isset( $banner_settings['settings']['gacm_enabled'] ) ? $banner_settings['settings']['gacm_enabled'] : false;
			if ( $is_iab_enabled ) {
				$is_iab_banner = true;
			}
			if ( $is_google_acm_enabled ) {
				$is_gac_enabled = true;
			}
		}
		if ( true === wcc_disable_banner() || false === $is_iab_banner ) {
			return;
		}
		$css    = array();
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
		wp_enqueue_script( 'wcc-iab-script', plugin_dir_url( __FILE__ ) . 'assets/js/script' . $suffix . '.js', array(), $this->version, false );
		wp_localize_script(
			'wcc-iab-script',
			'iabConfig',
			array(
				'status'               => true,
				'baseUrl'              => $this->get_upload_path( 'cmp', true ),
				'latestFilename'       => 'v3/vendor-list.json',
				'languageFilename'     => 'v3/purposes-en.json',
				'appliedLaw'           => 'GDPR',
				'allowedVendors'       => $this->get_allowed_vendor_list(),
				'isGoogleACMEnabled'   => $is_gac_enabled,
				'allowedGoogleVendors' => $this->get_allowed_google_vendor_list(),
				'currentLanguage'      => wcc_current_language(),
			)
		);
		wp_localize_script(
			'wcc-iab-script',
			'iabTranslations',
			array(
				'storageDisclosures' => array(
					'title'   => __( 'Device Storage Disclosure', 'webtoffee-cookie-consent' ),
					'headers' => array(
						'name'     => __( 'Name', 'webtoffee-cookie-consent' ),
						'type'     => __( 'Type', 'webtoffee-cookie-consent' ),
						'duration' => __( 'Duration', 'webtoffee-cookie-consent' ),
						'domain'   => __( 'Domain', 'webtoffee-cookie-consent' ),
						'purposes' => __( 'Purposes', 'webtoffee-cookie-consent' ),
					),
				),
				'vendorDetails'      => array(
					'headers' => array(
						'purposes'            => __( 'Purposes( Consent )', 'webtoffee-cookie-consent' ),
						'special_purposes'    => __( 'Special Purposes', 'webtoffee-cookie-consent' ),
						'legitimate_purposes' => __( 'Purposes( Legitimate Interest )', 'webtoffee-cookie-consent' ),
						'features'            => __( 'Features', 'webtoffee-cookie-consent' ),
						'special_features'    => __( 'Special Features', 'webtoffee-cookie-consent' ),
						'data_categories'     => __( 'Data Categories', 'webtoffee-cookie-consent' ),
						'loading'             => __( 'Loading...', 'webtoffee-cookie-consent' ),
					),
					'others'  => array(
						'privacy'         => __( 'Privacy policy : ', 'webtoffee-cookie-consent' ),
						'legitimate'      => __( 'Legitimate Interest Claim : ', 'webtoffee-cookie-consent' ),
						'retention'       => __( 'Data Retention Period', 'webtoffee-cookie-consent' ),
						'enable'          => __( 'Enabled', 'webtoffee-cookie-consent' ),
						'disable'         => __( 'Disabled', 'webtoffee-cookie-consent' ),
						'consent_text'    => __( 'Consent', 'webtoffee-cookie-consent' ),
						'legitimate_text' => __( 'Legitimate Interest', 'webtoffee-cookie-consent' ),
					),
				),
				'deviceOverview'     => array(
					'title'   => __( 'Device Storage Overview', 'webtoffee-cookie-consent' ),
					'headers' => array(
						'duration_title'           => __( 'Maximum duration of cookies : ', 'webtoffee-cookie-consent' ),
						'cookie_refreshed'         => __( 'Cookie lifetime is being refreshed', 'webtoffee-cookie-consent' ),
						'cookie_not_refreshed'     => __( 'Cookie lifetime is not being refreshed', 'webtoffee-cookie-consent' ),
						'tracking_title'           => __( 'Tracking method : ', 'webtoffee-cookie-consent' ),
						'tracking_method'          => __( 'Cookie', 'webtoffee-cookie-consent' ),
						'tracking_method_extended' => __( 'and others.', 'webtoffee-cookie-consent' ),
					),
				),
			)
		);
	}

	/**
	 * Return upload path
	 *
	 * @param string $path Current path.
	 * @return $upload_path
	 */
	public static function get_upload_path( $path = '', $is_url = false ) {
		$uploads    = wp_upload_dir();
		$upload_dir = $uploads['basedir'] . '/webtoffee/' . $path;
		$upload_url = $uploads['baseurl'] . '/webtoffee/' . $path;
		if ( ! is_dir( $upload_dir ) ) {
			wp_mkdir_p( $upload_dir );
		}
		return $is_url ? $upload_url : trailingslashit( $upload_dir );
	}
	/**
	 * @since    3.0.0
	 * return excluded vendors array
	 */

	public function get_excluded_vendor_list() {
		$excl_vendors_arr = array();
		$excl_vendors_arr = apply_filters( 'wcc_excluded_vendor_list', $excl_vendors_arr );
		return $excl_vendors_arr;
	}
	/**
	 * @since    3.0.0
	 * return allowed vendors key array
	 */

	public function get_allowed_vendor_list() {
		$vendor_key_arr = array();
		if ( ! $this->enabled ) {
			return $vendor_key_arr;
		}
		$vendors_list_arr = $this->get_vendor_list();
		foreach ( $vendors_list_arr as $key => $value ) {

			if ( 'vendors' === $key ) {
				$vendors_arr = $value;
			}
		}
		//Generate mapped vendor list array
		$vendors_arr = $this->get_mappped_vendor_list( $vendors_list_arr );
		if ( ! empty( $vendors_arr ) ) {
			foreach ( $vendors_arr as $kl => $kv ) {

				$vendor_key_arr[] = $kl;
			}
		}
		//Fetch admin configured third party vendors
		$vendor_key_arr = $this->get_allowed_vendors( 'thirdpartyvendors', $vendor_key_arr );

		$excl_vendors_arr = $this->get_excluded_vendor_list();

		if ( ! empty( $excl_vendors_arr ) && ! empty( $vendor_key_arr ) ) {
			$allowed_vendor_key_arr = array_diff( $vendor_key_arr, $excl_vendors_arr );
		} else {
			$allowed_vendor_key_arr = $vendor_key_arr;
		}
		$allowed_vendor_key_arr = apply_filters( 'wcc_allowed_vendor_list', $allowed_vendor_key_arr );
		return array_values( $allowed_vendor_key_arr );
	}

	/**
	 * @since    3.0.2
	 * return vendor list
	 */
	public function get_allowed_vendors( $type, $vendor_key_arr ) {
		// Get the allowed vendor data from the options table
		$allowed_vendor = get_option( 'wcc_vendor_data', array() );

		// Check if the allowed vendor data is not empty and contains the requested type
		if ( ! empty( $allowed_vendor ) && isset( $allowed_vendor[ $type ] ) ) {

			// Get the specific vendor data for the requested type
			$vendor_data = $allowed_vendor[ $type ];

			// Extract the 'id' column from the vendor data
			$vendor_ids = array_column( $vendor_data, 'id' );

			// Convert the vendor IDs to integers
			$vendor_key_arr = array_map( 'intval', $vendor_ids );
		}
		return $vendor_key_arr;
	}
	/**
	 * @since    3.0.2
	 * return vendor list
	 */
	public function get_mappped_vendor_list( $vendor_data ) {

		$vendors     = array();
		$vendor_list = isset( $vendor_data['vendors'] ) && is_array( $vendor_data['vendors'] ) ? $vendor_data['vendors'] : array();

		foreach ( $vendor_list as $vendor ) {
			if ( $vendor && ! isset( $vendor['deletedDate'] ) ) {
				$vendors[ intval( $vendor['id'] ) ] = $vendor; // Collect vendor data
			}
		}
		return $vendors;
	}



	/**
	 * @since    3.0.0
	 * @return array|null Vendor list or null if not found
	 */

	public function get_vendor_list( $language = '' ) {
		$vendor_list_path = $this->get_vendor_list_path( $language );
		if ( ! $vendor_list_path ) {
			return null;
		}
		$vendors_list_arr = wp_cache_get( 'wcc_vendors_list', 'wcc_vendors' . $language );
		if ( ! $vendors_list_arr ) {
			// Use wcc_read_json_file() to fetch the JSON data
			$vendors_list_arr = wcc_read_json_file( $vendor_list_path );
			if ( null === $vendors_list_arr ) {
				return null;
			}
			// Cache the result for 12 hours
			wp_cache_set( 'wcc_vendors_list', $vendors_list_arr, 'wcc_vendors' . $language, 12 * HOUR_IN_SECONDS );
		}

		return $vendors_list_arr;
	}
	/**
	 * Return the vendor-list.json file's path
	 *
	 * @return string $vendor_list_path.
	 */
	public function get_vendor_list_path( $language ) {

		$vendor_list_path = '';

		$path = self::get_upload_path( 'cmp', true );

		// Get the upload directory path
		$upload_dir = wp_upload_dir();

		if ( ! empty( $language ) ) {
			// Specify the file path within the wp_uploads folder
			$vendor_list_path = $upload_dir['basedir'] . '/webtoffee/cmp/v3/purposes-' . $language . '.json';

			if ( file_exists( $vendor_list_path ) ) {
				return $vendor_list_path;
			} else {

				$vendor_list_path = $upload_dir['basedir'] . '/webtoffee/cmp/v3/vendor-list.json';
			}
		} else {

			$vendor_list_path = $upload_dir['basedir'] . '/webtoffee/cmp/v3/vendor-list.json';
		}
		if ( ! file_exists( $vendor_list_path ) ) {
			$this->update_vendor_list();
		}
		return $vendor_list_path;
	}
	/**
	 * @since    3.0.0
	 * Function to update vendor list
	 */
	public function update_vendor_list() {
		$languages = wcc_i18n_selected_languages();
		$this->download( $this->list_url . 'vendor-list.json' );
		//Download consent providers csv
		$this->download( $this->list_url . 'additional-consent-providers.csv' );
		foreach ( $languages as $lang ) {
			if ( 'en' !== $lang ) {
				$this->download( $this->list_url . 'purposes-' . $lang . '.json' );
			}
		}
		set_transient( 'wcc_vendor_file_update', true, WEEK_IN_SECONDS );
	}
	/**
	 * @since    3.0.0
	 * Download function
	 *
	 * @param string $src The URL of the file to download.
	 * @return void
	 */
	public function download( $src ) {
		require_once ABSPATH . 'wp-admin/includes/file.php';
		
		// Load the wp_generate_password function if it doesn't exist in the plugin folder.
		if ( ! function_exists( 'wp_generate_password' ) ) {
			require_once ABSPATH . 'wp-includes/pluggable.php';
		}

		$upload_dir = $this->get_upload_path( 'cmp/v3/' );
		if ( ! file_exists( $upload_dir ) ) {
			wp_mkdir_p( $upload_dir, 0755 );
		}

		// Check if the path contains "vendor-list.json"
		if ( strpos( $src, 'vendor-list.json' ) !== false ) {
			// Perform your custom action for "vendor-list.json"
			$this->create_vendor_list_file( $src, $upload_dir );
			return; // Exit the function to avoid further processing
		}

		// Download file with 25 second timeout.
		$tmpfile = download_url( $src, 25 );
		$file    = $upload_dir . basename( $src );

		// Check for errors.
		if ( ! is_wp_error( $tmpfile ) ) {
			// Remove current file if it exists.
			if ( file_exists( $file ) ) {
				wp_delete_file( $file );
			}
			// In case the server prevents deletion, we check it again.
			if ( ! file_exists( $file ) ) {
				copy( $tmpfile, $file );
			}
		}

		// Clean up temporary file.
		if ( is_string( $tmpfile ) && file_exists( $tmpfile ) ) {
			wp_delete_file( $tmpfile );
		}
	}
	/**
	 * Return the google vendor list
	 *
	 * @return array $googlevendors.
	 */
	public function get_google_vendors() {
		$vendor_list_path = $this->get_google_vendor_list_path();
		if ( ! $vendor_list_path ) {
			return;
		}
		$googlevendors = wp_cache_get( 'wcc_google_vendors_list', 'wcc_google_vendors' );
		if ( ! $googlevendors ) {
			/* Fetching Google ad tech vendors */
			$csv_file = $vendor_list_path;
			// Open the file for reading
			// Initialize WP_Filesystem
			global $wp_filesystem;
			if ( empty( $wp_filesystem ) ) {
				require_once ABSPATH . '/wp-admin/includes/file.php';
				WP_Filesystem();
			}
			
			if ( $wp_filesystem->exists( $csv_file ) ) {
				$googlevendors = array();
				$csv_content = $wp_filesystem->get_contents( $csv_file );
				$lines = explode( "\n", $csv_content );
				
				foreach ( $lines as $line ) {
					if ( ! empty( trim( $line ) ) ) {
						$row = str_getcsv( $line, ',', '"', '\\' );
						$googlevendors[] = $row; // Add each row as an array to $dataArray
					}
				}
			}
			wp_cache_set( 'wcc_google_vendors_list', $googlevendors, 'wcc_google_vendors', 12 * HOUR_IN_SECONDS );
		}
		return $googlevendors;
	}

	/**
	 * @since    3.0.0
	 * return excluded google vendors array
	 */

	public function get_excluded_google_vendor_list() {
		return apply_filters( 'wcc_excluded_google_vendor_list', array() );
	}
	/**
	 * @since    3.0.0
	 * return allowed google vendors key array
	 */

	public function get_allowed_google_vendor_list() {
		$google_vendor_key_arr  = array();
		$allowed_vendor_key_arr = array();
		if ( ! $this->enabled ) {
			return $google_vendor_key_arr;
		}
		$googlevendors = $this->get_google_vendors();
		if ( ! empty( $googlevendors ) ) {
			foreach ( $googlevendors as $provider_key => $provider ) {
				if ( 0 !== $provider_key ) {
					$google_vendor_key_arr[] = $provider[0];
				}
			}
		}
		//Fetch admin configured google vendors
		$google_vendor_key_arr = $this->get_allowed_vendors( 'googlevendors', $google_vendor_key_arr );
		$excl_vendors_arr      = $this->get_excluded_google_vendor_list();
		if ( ! empty( $excl_vendors_arr ) && ! empty( $google_vendor_key_arr ) ) {
			$allowed_vendor_key_arr = array_diff( $google_vendor_key_arr, $excl_vendors_arr );
		} else {
			$allowed_vendor_key_arr = $google_vendor_key_arr;
		}
		$allowed_vendor_key_arr = apply_filters( 'wt_cli_allowed_google_vendor_list', $allowed_vendor_key_arr );
		return array_values( $allowed_vendor_key_arr );
	}
	/**
	 * Return the google vendor-list.csv file's path
	 *
	 * @return string $vendor_list_path.
	 */
	public function get_google_vendor_list_path() {
		$vendor_list_path = '';
		// Get the upload directory path
		$upload_dir       = wp_upload_dir();
		$vendor_list_path = $upload_dir['basedir'] . '/webtoffee/cmp/v3/additional-consent-providers.csv';
		if ( ! file_exists( $vendor_list_path ) ) {
			$this->update_vendor_list();
		}
		return $vendor_list_path;
	}
	/**
	 * Create the vendor-list.json file
	 *
	 * @param object $src.
	 */
	public function create_vendor_list_file( $src, $upload_dir ) {
		// Use wp_remote_get() to fetch the data
		$response = wp_remote_get(
			$src,
			array(
				'timeout'   => 60,
				'sslverify' => false,
				'headers'   => array(
					'Accept-Encoding' => 'gzip, deflate, br',
				),
			)
		);

		// Check for errors
		if ( is_wp_error( $response ) ) {
			return;
		}

		// Get the response code
		$response_code = wp_remote_retrieve_response_code( $response );
		if ( $response_code !== 200 ) {
			return;
		}

		// Get the body
		$data = wp_remote_retrieve_body( $response );
		if ( empty( $data ) ) {
			return;
		}

		// Check if the data is gzipped
		if ( class_exists( 'finfo' ) ) {
			// Use finfo to check the MIME type
			$mime_type = ( new finfo( FILEINFO_MIME_TYPE ) )->buffer( $data );
			if ( 'application/gzip' === $mime_type ) {
				$data = gzdecode( $data );
			}
		} else {
			// Fallback to checking the gzip signature directly
			if ( substr( $data, 0, 2 ) === "\x1f\x8b" ) {
				$data = gzdecode( $data );
			}
		}

		// Process the data
		$decoded_data = json_decode( $data );
		if ( ! $decoded_data ) {
			return;
		}

		$merged_data = $this->merge_google_vendors_into_gvl( $decoded_data );

		// Get filesystem instance
		$filesystem = \WebToffee\CookieConsent\Lite\Includes\Filesystem::get_instance();

		// Save the modified JSON file using the filesystem class
		$file_path = $upload_dir . 'vendor-list.json';
		$json_data = wp_json_encode( $merged_data, JSON_UNESCAPED_UNICODE );

		$filesystem->put_contents( $file_path, $json_data );
	}
	/**
	 * Downloads the Google vendor list and merge into Global vendor list.
	 *
	 * @param object $gvl_data.
	 * @return object
	 */
	public function merge_google_vendors_into_gvl( $gvl_data ) {
		// Use wp_remote_get() to fetch the CSV data
		$response = wp_remote_get(
			$this->list_url . 'additional-consent-providers.csv',
			array(
				'timeout'   => 60,
				'sslverify' => false,
				'headers'   => array(
					'Accept-Encoding' => 'gzip, deflate, br',
				),
			)
		);

		// Check for errors
		if ( is_wp_error( $response ) ) {
			return $gvl_data;
		}

		// Get the response code
		$response_code = wp_remote_retrieve_response_code( $response );
		if ( $response_code !== 200 ) {
			return $gvl_data;
		}

		// Get the body
		$google_vendorlist_csv = wp_remote_retrieve_body( $response );
		if ( empty( $google_vendorlist_csv ) ) {
			return $gvl_data;
		}

		// Process the CSV data
		$lines = explode( PHP_EOL, $google_vendorlist_csv );
		array_shift( $lines ); // Remove header row

		$google_vendor_list = array();
		foreach ( $lines as $line ) {
			$row = str_getcsv( $line );
			if ( count( $row ) < 3 ) {
				continue;
			}
			$google_vendor_list[ $row[0] ] = array(
				'id'      => (int) $row[0],
				'name'    => $row[1],
				'privacy' => $row[2],
			);
		}

		if ( ! empty( $google_vendor_list ) ) {
			$gvl_data->googleVendors = json_decode( json_encode( $google_vendor_list ) ); // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
		}

		return $gvl_data;
	}
	// Delete Cache
	public static function wcc_delete_vendors_cache( $language = '' ) {
		// Delete the cache with the key 'wcc_vendors_list' and the appropriate group
		wp_cache_delete( 'wcc_vendors_list', 'wcc_vendors' . $language );
	}
	/**
	 * Check if IAB module is active;
	 *
	 * @return boolean
	 */
	public function is_active() {
		return class_exists( \Iab::class );
	}
}
