<?php

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

class AIEO_DMM_Ad_Connectors extends AIEO_DMM_Module_Base {

	const NONCE  = 'aieo_ad_connectors';
	const CAP    = 'manage_woocommerce';
	const OPTION = 'aieo_ad_connectors';
	const CRON   = 'aieo_ad_connectors_sync';

	
	const PLATFORMS = array(
		'google' => array( 'paid_google', 'google_ads' ),
		'meta'   => array( 'paid_facebook', 'meta' ),
		'tiktok' => array( 'paid_tiktok', 'tiktok' ),
	);

	
	const SECRETS = array( 'developer_token', 'client_secret', 'refresh_token', 'access_token' );

	public function get_id() {
		return 'ad_connectors';
	}
	public function get_label() {
		return __( 'Ad-spend connectors', 'ai-eshop-optimizer' );
	}
	public function get_group() {
		return 'tools';
	}
	public function get_priority() {
		return 16;
	}

	public function register_hooks() {
		add_action( 'wp_ajax_aieo_adc_save', array( $this, 'ajax_save' ) );
		add_action( 'wp_ajax_aieo_adc_test', array( $this, 'ajax_test' ) );
		add_action( 'wp_ajax_aieo_adc_sync', array( $this, 'ajax_sync' ) );
		add_action( self::CRON, array( $this, 'cron_sync_all' ) );
		if ( ! wp_next_scheduled( self::CRON ) ) {
			wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', self::CRON );
		}
	}

	

	private static function key() {
		return hash( 'sha256', wp_salt( 'auth' ) . '|aieo_adconn', true );
	}
	private static function enc( $s ) {
		$s = (string) $s;
		if ( '' === $s ) {
			return '';
		}
		$iv = openssl_random_pseudo_bytes( 16 );
		$c  = openssl_encrypt( $s, 'aes-256-cbc', self::key(), OPENSSL_RAW_DATA, $iv );
		return base64_encode( $iv . $c );
	}
	private static function dec( $s ) {
		$raw = base64_decode( (string) $s, true );
		if ( ! is_string( $raw ) || strlen( $raw ) < 17 ) {
			return '';
		}
		$p = openssl_decrypt( substr( $raw, 16 ), 'aes-256-cbc', self::key(), OPENSSL_RAW_DATA, substr( $raw, 0, 16 ) );
		return false === $p ? '' : $p;
	}

	
	private function get_creds( $platform ) {
		$all = get_option( self::OPTION, array() );
		$row = isset( $all[ $platform ] ) && is_array( $all[ $platform ] ) ? $all[ $platform ] : array();
		$out = array();
		foreach ( $row as $k => $v ) {
			$out[ $k ] = in_array( $k, self::SECRETS, true ) ? self::dec( $v ) : $v;
		}
		return $out;
	}

	
	private function configured( $platform ) {
		$c = $this->get_creds( $platform );
		if ( 'google' === $platform ) {
			return ! empty( $c['customer_id'] ) && ! empty( $c['developer_token'] ) && ! empty( $c['client_id'] ) && ! empty( $c['refresh_token'] );
		}
		if ( 'meta' === $platform ) {
			return ! empty( $c['ad_account_id'] ) && ! empty( $c['access_token'] );
		}
		if ( 'tiktok' === $platform ) {
			return ! empty( $c['advertiser_id'] ) && ! empty( $c['access_token'] );
		}
		return false;
	}

	

	private function guard() {
		check_ajax_referer( self::NONCE, 'nonce' );
		if ( ! current_user_can( self::CAP ) ) {
			wp_send_json_error( array( 'msg' => 'forbidden' ), 403 );
		}
	}

	public function ajax_save() {
		$this->guard();
		$platform = isset( $_POST['platform'] ) ? sanitize_key( $_POST['platform'] ) : '';
		if ( ! isset( self::PLATFORMS[ $platform ] ) ) {
			wp_send_json_error( array( 'msg' => 'bad platform' ) );
		}
		$fields = array( 'customer_id', 'developer_token', 'client_id', 'client_secret', 'refresh_token', 'login_customer_id', 'ad_account_id', 'access_token', 'advertiser_id', 'auto' );
		$all    = get_option( self::OPTION, array() );
		$cur    = isset( $all[ $platform ] ) && is_array( $all[ $platform ] ) ? $all[ $platform ] : array();
		foreach ( $fields as $f ) {
			if ( ! isset( $_POST[ $f ] ) ) {
				continue;
			}
			$v = sanitize_text_field( wp_unslash( $_POST[ $f ] ) );
			if ( in_array( $f, self::SECRETS, true ) ) {
				
				if ( '' === $v ) {
					continue;
				}
				$cur[ $f ] = self::enc( $v );
			} else {
				$cur[ $f ] = $v;
			}
		}
		$all[ $platform ] = $cur;
		update_option( self::OPTION, $all, false );
		wp_send_json_success( array( 'configured' => $this->configured( $platform ) ) );
	}

	public function ajax_test() {
		$this->guard();
		$platform = isset( $_POST['platform'] ) ? sanitize_key( $_POST['platform'] ) : '';
		$to       = gmdate( 'Y-m-d', strtotime( '-1 day' ) );
		$from     = gmdate( 'Y-m-d', strtotime( '-7 day' ) );
		$res      = $this->fetch( $platform, $this->get_creds( $platform ), $from, $to );
		if ( isset( $res['error'] ) ) {
			wp_send_json_error( array( 'msg' => $res['error'] ) );
		}
		$total = 0.0;
		foreach ( $res['rows'] as $r ) {
			$total += $r['spend'];
		}
		wp_send_json_success( array( 'msg' => sprintf( __( 'OK — %1$d campaign-days, %2$s total spend (last 7 days). Not stored — use Sync to save.', 'ai-eshop-optimizer' ), count( $res['rows'] ), number_format( $total, 2 ) . ' €' ) ) );
	}

	public function ajax_sync() {
		$this->guard();
		$platform = isset( $_POST['platform'] ) ? sanitize_key( $_POST['platform'] ) : '';
		$from     = isset( $_POST['from'] ) ? sanitize_text_field( wp_unslash( $_POST['from'] ) ) : '';
		$to       = isset( $_POST['to'] ) ? sanitize_text_field( wp_unslash( $_POST['to'] ) ) : '';
		$d        = '/^\d{4}-\d{2}-\d{2}$/';
		if ( ! preg_match( $d, $to ) ) {
			$to = gmdate( 'Y-m-d', strtotime( '-1 day' ) );
		}
		if ( ! preg_match( $d, $from ) ) {
			$from = gmdate( 'Y-m-d', strtotime( $to . ' -30 day' ) );
		}
		$res = $this->sync( $platform, $from, $to );
		if ( isset( $res['error'] ) ) {
			wp_send_json_error( array( 'msg' => $res['error'] ) );
		}
		wp_send_json_success( array( 'msg' => sprintf( __( 'Synced %1$d campaign-day rows + %2$d channel-day rollups into the ledger.', 'ai-eshop-optimizer' ), $res['rows'], $res['days'] ) ) );
	}

	public function cron_sync_all() {
		$to   = gmdate( 'Y-m-d', strtotime( '-1 day' ) );
		$from = gmdate( 'Y-m-d', strtotime( '-7 day' ) );
		foreach ( array_keys( self::PLATFORMS ) as $platform ) {
			$c = $this->get_creds( $platform );
			if ( empty( $c['auto'] ) || ! $this->configured( $platform ) ) {
				continue;
			}
			$this->sync( $platform, $from, $to );
		}
	}

	

	private function fetch( $platform, $c, $from, $to ) {
		if ( ! $this->configured( $platform ) ) {
			return array( 'error' => __( 'Not configured — fill the credentials and Save first.', 'ai-eshop-optimizer' ) );
		}
		if ( 'google' === $platform ) {
			return $this->google_fetch( $c, $from, $to );
		}
		if ( 'meta' === $platform ) {
			return $this->meta_fetch( $c, $from, $to );
		}
		if ( 'tiktok' === $platform ) {
			return $this->tiktok_fetch( $c, $from, $to );
		}
		return array( 'error' => 'unknown platform' );
	}

	
	public function sync( $platform, $from, $to ) {
		$res = $this->fetch( $platform, $this->get_creds( $platform ), $from, $to );
		if ( isset( $res['error'] ) ) {
			return $res;
		}
		list( $chan, $src ) = self::PLATFORMS[ $platform ];
		$n        = 0;
		$by_day   = array();
		foreach ( $res['rows'] as $row ) {
			$date = preg_match( '/^\d{4}-\d{2}-\d{2}/', (string) $row['date'] ) ? substr( $row['date'], 0, 10 ) : $from;
			if ( '' !== (string) $row['campaign'] ) {
				AIEO_Attribution_Cost::upsert( 'campaign', $row['campaign'], $date, $date, $row['spend'], $src );
				$n++;
			}
			$by_day[ $date ] = ( $by_day[ $date ] ?? 0 ) + (float) $row['spend'];
		}
		foreach ( $by_day as $date => $amt ) {
			AIEO_Attribution_Cost::upsert( 'channel', $chan, $date, $date, $amt, $src );
		}
		return array( 'rows' => $n, 'days' => count( $by_day ) );
	}

	private function google_fetch( $c, $from, $to ) {
		
		$tr = wp_remote_post( 'https://oauth2.googleapis.com/token', array(
			'timeout' => 25,
			'body'    => array(
				'client_id'     => $c['client_id'],
				'client_secret' => $c['client_secret'] ?? '',
				'refresh_token' => $c['refresh_token'],
				'grant_type'    => 'refresh_token',
			),
		) );
		if ( is_wp_error( $tr ) ) {
			return array( 'error' => 'token: ' . $tr->get_error_message() );
		}
		$tok = json_decode( wp_remote_retrieve_body( $tr ), true );
		if ( empty( $tok['access_token'] ) ) {
			return array( 'error' => 'token: ' . ( $tok['error_description'] ?? 'no access_token' ) );
		}
		
		$cid     = preg_replace( '/\D/', '', (string) $c['customer_id'] );
		$headers = array(
			'Authorization'   => 'Bearer ' . $tok['access_token'],
			'developer-token' => $c['developer_token'],
			'Content-Type'    => 'application/json',
		);
		if ( ! empty( $c['login_customer_id'] ) ) {
			$headers['login-customer-id'] = preg_replace( '/\D/', '', (string) $c['login_customer_id'] );
		}
		$q = "SELECT campaign.name, metrics.cost_micros, segments.date FROM campaign WHERE segments.date BETWEEN '{$from}' AND '{$to}'";
		$r = wp_remote_post( "https://googleads.googleapis.com/v17/customers/{$cid}/googleAds:searchStream", array(
			'timeout' => 45,
			'headers' => $headers,
			'body'    => wp_json_encode( array( 'query' => $q ) ),
		) );
		if ( is_wp_error( $r ) ) {
			return array( 'error' => $r->get_error_message() );
		}
		$body = json_decode( wp_remote_retrieve_body( $r ), true );
		if ( isset( $body['error'] ) ) {
			return array( 'error' => 'google: ' . ( $body['error']['message'] ?? 'api error' ) );
		}
		$out = array();
		foreach ( (array) $body as $chunk ) {
			foreach ( ( $chunk['results'] ?? array() ) as $row ) {
				$out[] = array(
					'campaign' => $row['campaign']['name'] ?? '',
					'date'     => $row['segments']['date'] ?? $from,
					'spend'    => ( $row['metrics']['costMicros'] ?? 0 ) / 1000000,
				);
			}
		}
		return array( 'rows' => $out );
	}

	private function meta_fetch( $c, $from, $to ) {
		$acct = 'act_' . ltrim( (string) $c['ad_account_id'], 'act_' );
		$url  = add_query_arg( array(
			'level'          => 'campaign',
			'fields'         => 'campaign_name,spend',
			'time_increment' => 1,
			'time_range'     => wp_json_encode( array( 'since' => $from, 'until' => $to ) ),
			'limit'          => 500,
			'access_token'   => $c['access_token'],
		), "https://graph.facebook.com/v20.0/{$acct}/insights" );

		
		
		
		
		
		
		
		$out   = array();
		$pages = 0;
		while ( '' !== (string) $url && $pages < 1000 ) {
			$pages++;
			if ( function_exists( 'set_time_limit' ) ) {
				@set_time_limit( 60 ); 
			}
			$r = wp_remote_get( $url, array( 'timeout' => 45 ) );
			if ( is_wp_error( $r ) ) {
				return array( 'error' => $r->get_error_message() );
			}
			$j = json_decode( wp_remote_retrieve_body( $r ), true );
			if ( isset( $j['error'] ) ) {
				return array( 'error' => 'meta: ' . ( $j['error']['message'] ?? 'api error' ) );
			}
			foreach ( ( $j['data'] ?? array() ) as $row ) {
				$out[] = array(
					'campaign' => $row['campaign_name'] ?? '',
					'date'     => $row['date_start'] ?? $from,
					'spend'    => (float) ( $row['spend'] ?? 0 ),
				);
			}
			$url = isset( $j['paging']['next'] ) ? (string) $j['paging']['next'] : '';
		}
		return array( 'rows' => $out );
	}

	private function tiktok_fetch( $c, $from, $to ) {
		$base = 'https://business-api.tiktok.com/open_api/v1.3/report/integrated/get/';

		
		
		
		
		
		$out         = array();
		$page        = 1;
		$pages_total = 1;
		do {
			if ( function_exists( 'set_time_limit' ) ) {
				@set_time_limit( 60 ); 
			}
			$url = add_query_arg( array(
				'advertiser_id' => $c['advertiser_id'],
				'report_type'   => 'BASIC',
				'data_level'    => 'AUCTION_CAMPAIGN',
				'dimensions'    => wp_json_encode( array( 'campaign_id', 'stat_time_day' ) ),
				'metrics'       => wp_json_encode( array( 'spend', 'campaign_name' ) ),
				'start_date'    => $from,
				'end_date'      => $to,
				'page'          => $page,
				'page_size'     => 1000,
			), $base );
			$r = wp_remote_get( $url, array( 'timeout' => 45, 'headers' => array( 'Access-Token' => $c['access_token'] ) ) );
			if ( is_wp_error( $r ) ) {
				return array( 'error' => $r->get_error_message() );
			}
			$j = json_decode( wp_remote_retrieve_body( $r ), true );
			if ( (int) ( $j['code'] ?? -1 ) !== 0 ) {
				return array( 'error' => 'tiktok: ' . ( $j['message'] ?? 'api error' ) );
			}
			foreach ( ( $j['data']['list'] ?? array() ) as $row ) {
				$dim = $row['dimensions'] ?? array();
				$mt  = $row['metrics'] ?? array();
				$out[] = array(
					'campaign' => $mt['campaign_name'] ?? ( $dim['campaign_id'] ?? '' ),
					'date'     => $dim['stat_time_day'] ?? $from,
					'spend'    => (float) ( $mt['spend'] ?? 0 ),
				);
			}
			$pages_total = (int) ( $j['data']['page_info']['total_page'] ?? 1 );
			$page++;
		} while ( $page <= $pages_total && $page <= 1000 );

		return array( 'rows' => $out );
	}

	

	public function render_subtab() {
		$nonce = wp_create_nonce( self::NONCE );
		echo '<div class="aieo-dmm-section">';
		echo '<div class="aieo-dmm-card">';
		echo '<h3>' . esc_html__( 'Ad-spend connectors', 'ai-eshop-optimizer' ) . '</h3>';
		echo '<p style="opacity:.8;margin-top:0;max-width:820px">'
			. esc_html__( 'Connect Google Ads, Meta and TikTok once; AIEO pulls campaign spend nightly into the ad-spend ledger, so the ROI Wizard shows true ROAS / ROI without you ever leaving AIEO — one cockpit for spend AND your own reco / offer / channel attribution. Credentials are stored encrypted; the spend pull is read-only.', 'ai-eshop-optimizer' )
			. '</p></div>';

		$this->panel( 'google', __( 'Google Ads', 'ai-eshop-optimizer' ),
			array(
				'customer_id'       => __( 'Customer ID (10-digit, e.g. 123-456-7890)', 'ai-eshop-optimizer' ),
				'developer_token'   => __( 'Developer token (secret)', 'ai-eshop-optimizer' ),
				'client_id'         => __( 'OAuth Client ID', 'ai-eshop-optimizer' ),
				'client_secret'     => __( 'OAuth Client secret (secret)', 'ai-eshop-optimizer' ),
				'refresh_token'     => __( 'OAuth Refresh token (secret)', 'ai-eshop-optimizer' ),
				'login_customer_id' => __( 'Manager (MCC) ID — optional', 'ai-eshop-optimizer' ),
			),
			__( 'Ask your agency for: the Customer ID, and either manager-account (MCC) access for our account OR a developer token + read-only OAuth credentials (Client ID/secret + a refresh token). The developer token is in the Google Ads API Center on the manager account; OAuth credentials in Google Cloud Console → APIs & Services → Credentials.', 'ai-eshop-optimizer' ),
			array(
				__( 'Google Ads → API Center', 'ai-eshop-optimizer' )          => 'https://ads.google.com/aw/apicenter',
				__( 'Cloud Console → Credentials', 'ai-eshop-optimizer' )      => 'https://console.cloud.google.com/apis/credentials',
				__( 'OAuth Playground (refresh token)', 'ai-eshop-optimizer' ) => 'https://developers.google.com/oauthplayground/',
			)
		);

		$this->panel( 'meta', __( 'Meta (Facebook / Instagram)', 'ai-eshop-optimizer' ),
			array(
				'ad_account_id' => __( 'Ad Account ID (act_… or the digits)', 'ai-eshop-optimizer' ),
				'access_token'  => __( 'Access token with ads_read (secret)', 'ai-eshop-optimizer' ),
			),
			__( 'Ask your agency for: the Ad Account ID and a System-User access token with the ads_read permission — OR to add our Business/App as a partner with ads_read. Generated under business.facebook.com → System Users, or developers.facebook.com.', 'ai-eshop-optimizer' ),
			array(
				__( 'Business → System Users', 'ai-eshop-optimizer' ) => 'https://business.facebook.com/settings/system-users',
				__( 'Business → Ad Accounts', 'ai-eshop-optimizer' )  => 'https://business.facebook.com/settings/ad-accounts',
				__( 'Meta for Developers', 'ai-eshop-optimizer' )     => 'https://developers.facebook.com/apps/',
			)
		);

		$this->panel( 'tiktok', __( 'TikTok', 'ai-eshop-optimizer' ),
			array(
				'advertiser_id' => __( 'Advertiser ID', 'ai-eshop-optimizer' ),
				'access_token'  => __( 'Access token with reporting (secret)', 'ai-eshop-optimizer' ),
			),
			__( 'Ask your agency for: the Advertiser ID and a long-lived access token with report read access — OR to add us as an authorised user. From the TikTok for Business / Marketing API app.', 'ai-eshop-optimizer' ),
			array(
				__( 'TikTok Marketing API portal', 'ai-eshop-optimizer' ) => 'https://business-api.tiktok.com/portal/',
				__( 'TikTok Ads Manager', 'ai-eshop-optimizer' )         => 'https://ads.tiktok.com/',
			)
		);

		echo '</div>'; 
		$this->print_js( $nonce );
	}

	private function panel( $platform, $title, $fields, $guidance, $links = array() ) {
		$c = $this->get_creds( $platform );
		echo '<div class="aieo-dmm-card" data-adc="' . esc_attr( $platform ) . '">';
		echo '<h3 style="display:flex;align-items:center;gap:10px">' . esc_html( $title );
		echo ' <span class="adc-status" style="font-size:12px;font-weight:400;padding:2px 8px;border-radius:10px;background:' . ( $this->configured( $platform ) ? '#dff5e1' : '#f1f1f1' ) . '">' . ( $this->configured( $platform ) ? esc_html__( 'configured', 'ai-eshop-optimizer' ) : esc_html__( 'not set', 'ai-eshop-optimizer' ) ) . '</span></h3>';
		echo '<div style="display:flex;flex-wrap:wrap;gap:10px">';
		foreach ( $fields as $name => $label ) {
			$secret = in_array( $name, self::SECRETS, true );
			$saved  = $secret && ! empty( $c[ $name ] );
			$val    = $secret ? '' : ( isset( $c[ $name ] ) ? $c[ $name ] : '' );
			$ph     = $saved ? esc_attr__( '•••••• saved (leave blank to keep)', 'ai-eshop-optimizer' ) : '';
			echo '<label style="font-size:12px">' . esc_html( $label ) . '<br><input type="' . ( $secret ? 'password' : 'text' ) . '" data-f="' . esc_attr( $name ) . '" value="' . esc_attr( $val ) . '" placeholder="' . $ph . '" style="min-width:240px"></label>';
		}
		echo '</div>';
		echo '<label style="display:inline-flex;align-items:center;gap:6px;margin-top:10px"><input type="checkbox" data-f="auto" ' . ( ! empty( $c['auto'] ) ? 'checked' : '' ) . '> ' . esc_html__( 'Auto-sync nightly', 'ai-eshop-optimizer' ) . '</label>';
		echo '<div style="margin-top:10px;display:flex;gap:8px;align-items:center;flex-wrap:wrap">';
		echo '<button type="button" class="button button-primary adc-save">' . esc_html__( 'Save', 'ai-eshop-optimizer' ) . '</button>';
		echo '<button type="button" class="button adc-test">' . esc_html__( 'Test connection', 'ai-eshop-optimizer' ) . '</button>';
		echo '<input type="date" class="adc-from" style="width:140px"><input type="date" class="adc-to" style="width:140px">';
		echo '<button type="button" class="button adc-sync">' . esc_html__( 'Sync now', 'ai-eshop-optimizer' ) . '</button>';
		echo '<span class="adc-msg" style="opacity:.8"></span></div>';
		echo '<p style="opacity:.7;font-size:12px;margin:10px 0 0;max-width:820px"><strong>' . esc_html__( 'What to ask your ad agency:', 'ai-eshop-optimizer' ) . '</strong> ' . esc_html( $guidance ) . '</p>';
		if ( ! empty( $links ) ) {
			echo '<p style="font-size:12px;margin:6px 0 0;max-width:820px"><strong>' . esc_html__( 'Where to get these:', 'ai-eshop-optimizer' ) . '</strong> ';
			$parts = array();
			foreach ( $links as $label => $url ) {
				$parts[] = '<a href="' . esc_url( $url ) . '" target="_blank" rel="noopener noreferrer">' . esc_html( $label ) . ' &#8599;</a>';
			}
			echo implode( ' &nbsp;&middot;&nbsp; ', $parts ); 
			echo '</p>';
		}
		echo '</div>';
	}

	private function print_js( $nonce ) {
		$ajax = admin_url( 'admin-ajax.php' );
		?>
		<script>
		(function () {
			var AJAX=<?php echo wp_json_encode( $ajax ); ?>, NONCE=<?php echo wp_json_encode( $nonce ); ?>;
			function post(action,data){ data=data||{}; data.action=action; data.nonce=NONCE; var fd=new FormData(); for(var k in data){fd.append(k,data[k]);} return fetch(AJAX,{method:'POST',credentials:'same-origin',body:fd}).then(function(r){return r.json();}); }
			function fields(card){ var o={platform:card.getAttribute('data-adc')}; card.querySelectorAll('[data-f]').forEach(function(el){ o[el.getAttribute('data-f')]= el.type==='checkbox'?(el.checked?'1':''):el.value; }); return o; }
			function msg(card,t,ok){ var m=card.querySelector('.adc-msg'); m.textContent=t; m.style.color=ok===false?'#b32d2e':(ok?'#1e7e34':''); }
			document.querySelectorAll('[data-adc]').forEach(function(card){
				card.querySelector('.adc-save').addEventListener('click',function(){ msg(card,'…'); post('aieo_adc_save',fields(card)).then(function(j){ if(j&&j.success){ msg(card,'Saved.',true); var s=card.querySelector('.adc-status'); s.textContent=j.data.configured?'configured':'not set'; s.style.background=j.data.configured?'#dff5e1':'#f1f1f1'; } else { msg(card,(j&&j.data&&j.data.msg)||'Save failed',false); } }); });
				card.querySelector('.adc-test').addEventListener('click',function(){ msg(card,'Testing…'); post('aieo_adc_test',{platform:card.getAttribute('data-adc')}).then(function(j){ if(j&&j.success){ msg(card,j.data.msg,true);} else { msg(card,(j&&j.data&&j.data.msg)||'Test failed',false);} }); });
				card.querySelector('.adc-sync').addEventListener('click',function(){ msg(card,'Syncing…'); post('aieo_adc_sync',{platform:card.getAttribute('data-adc'),from:card.querySelector('.adc-from').value,to:card.querySelector('.adc-to').value}).then(function(j){ if(j&&j.success){ msg(card,j.data.msg,true);} else { msg(card,(j&&j.data&&j.data.msg)||'Sync failed',false);} }); });
			});
		})();
		</script>
		<?php
	}
}
