/* Let's Code Cookie Banner – Admin JS (color pickers + live preview + reset) */
( function ( $ ) {
	'use strict';

	$( '.lccb-color-picker' ).wpColorPicker( {
		change: debounce( updatePreview, 150 ),
		clear:  debounce( updatePreview, 150 ),
	} );

	$( '.lccb-number-field' ).on( 'input change', debounce( updatePreview, 200 ) );
	$( '.lccb-text-field' ).on( 'input change', debounce( updatePreview, 300 ) );

	function updatePreview() {
		var bg               = val( 'bg_color' );
		var text             = val( 'text_color' );
		var btnBg            = val( 'btn_bg' );
		var btnTxt           = val( 'btn_text' );
		var border           = val( 'btn_border_color' );
		var overlayBg        = val( 'overlay_bg' );
		var alwaysActiveColor = val( 'always_active_color' );
		var fabBg            = val( 'fab_bg' );
		var fabIconColor     = val( 'fab_icon_color' );
		var fabBorderColor   = val( 'fab_border_color' );
		var fabBorderWidth   = intVal( 'fab_border_width', 0 );
		var fabBoxShadow     = val( 'fab_box_shadow' );
		var btnRadius        = intVal( 'btn_border_radius', 8 );
		var btnBorderWidth   = intVal( 'btn_border_width', 2 );
		var bannerRadius     = intVal( 'banner_radius', 8 );
		var fontSize         = intVal( 'font_size', 14 );
		var fabIconSize      = intVal( 'fab_icon_size', 22 );

		// Banner preview.
		$( '.lccb-preview-banner' ).css( {
			backgroundColor: bg   || '#ffffff',
			color:           text || '#333333',
			borderRadius:    bannerRadius + 'px',
			fontSize:        fontSize + 'px',
		} );
		$( '.lccb-preview-btn' ).css( {
			backgroundColor: btnBg  || '#1a73e8',
			color:           btnTxt || '#ffffff',
			borderColor:     border || '#1a73e8',
			borderWidth:     btnBorderWidth + 'px',
			borderStyle:     'solid',
			borderRadius:    btnRadius + 'px',
		} );

		// FAB button preview.
		$( '.lccb-preview-fab-btn' ).css( {
			backgroundColor: fabBg       || '#1a73e8',
			color:           fabIconColor || '#ffffff',
			borderRadius:    btnRadius + 'px',
			border:          fabBorderWidth + 'px solid ' + ( fabBorderColor || '#1a73e8' ),
			boxShadow:       fabBoxShadow || '0 2px 10px rgba(0,0,0,.25)',
		} );
		$( '.lccb-preview-fab-btn svg' ).css( {
			width:  fabIconSize + 'px',
			height: fabIconSize + 'px',
		} );

		// Preferences panel preview.
		$( '.lccb-preview-panel' ).css( {
			backgroundColor: overlayBg || '#f8f8f8',
			color:           text      || '#333333',
			fontSize:        fontSize  + 'px',
		} );
		$( '.lccb-preview-slider-on' ).css( {
			backgroundColor: btnBg || '#1a73e8',
		} );
		$( '.lccb-preview-always-on' ).css( {
			color: alwaysActiveColor || '#2e7d32',
		} );

		// Cookie policy table preview.
		var tableHeaderBg   = val( 'table_header_bg' );
		var tableHeaderText = val( 'table_header_text' );
		var tableOddBg      = val( 'table_odd_bg' );
		var tableOddText    = val( 'table_odd_text' );
		var tableEvenBg     = val( 'table_even_bg' );
		var tableEvenText   = val( 'table_even_text' );
		$( '.lccb-preview-policy-tbl thead th' ).css( {
			backgroundColor: tableHeaderBg   || '#f5f5f5',
			color:           tableHeaderText || '#333333',
		} );
		// jQuery :even = index 0 (first row) = CSS nth-child(odd).
		$( '.lccb-preview-policy-tbl tbody tr:even td' ).css( {
			backgroundColor: tableOddBg   || '#ffffff',
			color:           tableOddText || '#000000',
		} );
		// jQuery :odd = index 1 (second row) = CSS nth-child(even).
		$( '.lccb-preview-policy-tbl tbody tr:odd td' ).css( {
			backgroundColor: tableEvenBg   || '#ffffff',
			color:           tableEvenText || '#000000',
		} );
	}

	function val( field ) {
		return $( '[name="lccb_settings[' + field + ']"]' ).val();
	}

	function intVal( field, fallback ) {
		var v = parseInt( val( field ), 10 );
		return isNaN( v ) ? fallback : v;
	}

	function debounce( fn, ms ) {
		var t;
		return function () {
			clearTimeout( t );
			t = setTimeout( fn, ms );
		};
	}

	// Initial preview on page load.
	$( function () { updatePreview(); } );

	// Reset design fields to defaults.
	$( document ).on( 'click', '#lccb-reset-defaults', function () {
		if ( typeof lccbAdmin === 'undefined' || ! lccbAdmin.designDefaults ) { return; }
		if ( ! window.confirm( lccbAdmin.confirmReset ) ) { return; }

		var d = lccbAdmin.designDefaults;

		// Reset color pickers.
		var colorFields = [ 'bg_color', 'text_color', 'btn_bg', 'btn_text', 'btn_border_color', 'overlay_bg', 'always_active_color',
			'fab_bg', 'fab_icon_color', 'fab_border_color',
			'table_header_bg', 'table_header_text', 'table_odd_bg', 'table_odd_text', 'table_even_bg', 'table_even_text' ];
		$.each( colorFields, function ( i, field ) {
			var $input = $( '[name="lccb_settings[' + field + ']"]' );
			$input.val( d[ field ] );
			// Update the Iris color picker UI if initialised.
			if ( $input.data( 'a8cIris' ) ) {
				$input.iris( 'color', d[ field ] );
			}
		} );

		// Reset number fields.
		var numFields = [
			'btn_border_radius', 'btn_padding_v', 'btn_padding_h', 'fab_icon_size',
			'banner_left', 'banner_right', 'banner_bottom', 'banner_radius', 'font_size',
			'fab_bottom', 'fab_left', 'fab_right', 'fab_border_width', 'btn_border_width',
		];
		$.each( numFields, function ( i, field ) {
			$( '[name="lccb_settings[' + field + ']"]' ).val( d[ field ] );
		} );

		// Reset fab position select.
		$( '[name="lccb_settings[fab_position]"]' ).val( d.fab_position || 'bottom-left' );

		// Reset text fields.
		$( '[name="lccb_settings[fab_box_shadow]"]' ).val( d.fab_box_shadow || '0 2px 10px rgba(0,0,0,.25)' );

		updatePreview();
	} );

	// Scan launcher — open target URL in new tab with scan params.
	$( document ).on( 'click', '#lccb-scan-start', function () {
		var raw = ( $( '#lccb-scan-url' ).val() || '' ).trim();
		var $msg = $( '#lccb-scan-msg' );
		$msg.text( '' ).removeClass( 'success error' );

		if ( ! raw ) {
			$msg.text( lccbAdmin.msgEnterUrl ).addClass( 'error' );
			$( '#lccb-scan-url' ).focus();
			return;
		}

		var force = $( '#lccb-scan-force' ).is( ':checked' ) ? '1' : '0';
		var scanUrl;
		try {
			var parsed = new URL( raw );
			parsed.searchParams.set( 'lccb_scan', '1' );
			parsed.searchParams.set( 'lccb_force_consent', force );
			scanUrl = parsed.toString();
		} catch ( e ) {
			$msg.text( lccbAdmin.msgInvalidUrl ).addClass( 'error' );
			return;
		}

		var win = window.open( scanUrl, '_blank' );
		if ( ! win || win.closed || typeof win.closed === 'undefined' ) {
			// Popup blocked — show a clickable fallback link.
			$msg.html(
				lccbAdmin.msgPopupBlocked + ' ' +
				'<a href="' + scanUrl + '" target="_blank" rel="noopener">' + lccbAdmin.msgPopupBlockedLink + '</a>.'
			).addClass( 'error' );
		} else {
			$msg.text( lccbAdmin.msgScanStarted ).addClass( 'success' );
		}
	} );

	// Server-side scan — PHP fetches the URL and parses Set-Cookie headers (including HttpOnly).
	$( document ).on( 'click', '#lccb-server-scan-start', function () {
		if ( typeof lccbAdmin === 'undefined' ) { return; }

		var raw  = ( $( '#lccb-server-scan-url' ).val() || '' ).trim();
		var $msg    = $( '#lccb-server-scan-msg' );
		var $btn    = $( this );
		var $loader = $( '#lccb-server-scan-loader' );

		$msg.text( '' ).removeClass( 'success error' );

		if ( ! raw ) {
			$msg.text( lccbAdmin.msgEnterUrl ).addClass( 'error' );
			$( '#lccb-server-scan-url' ).focus();
			return;
		}

		$btn.prop( 'disabled', true );
		$loader.css( 'display', 'flex' );

		$.post( lccbAdmin.ajax_url, {
			action : 'lccb_server_scan',
			nonce  : lccbAdmin.server_scan_nonce,
			url    : raw,
		} )
		.done( function ( res ) {
			if ( res && res.success ) {
				if ( res.data.count > 0 ) {
					$msg.text( lccbAdmin.msgServerScanFound.replace( '%d', res.data.count ) ).addClass( 'success' );
				} else {
					$msg.text( lccbAdmin.msgServerScanNone ).addClass( 'success' );
				}
			} else {
				var errMsg = ( res && res.data && res.data.message ) ? res.data.message : lccbAdmin.errorMsg;
				$msg.text( lccbAdmin.msgErrorPrefix + ' ' + errMsg ).addClass( 'error' );
			}
		} )
		.fail( function ( xhr ) {
			var errMsg = lccbAdmin.msgNetworkErrorScan;
			if ( xhr.status ) {
				errMsg += ' (HTTP ' + xhr.status + ')';
			}
			$msg.text( errMsg ).addClass( 'error' );
		} )
		.always( function () {
			$btn.prop( 'disabled', false );
			$loader.hide();
		} );
	} );

	// Clear the list of detected third-party domains.
	$( document ).on( 'click', '#lccb-clear-third-party-domains', function () {
		if ( typeof lccbAdmin === 'undefined' ) { return; }

		var $btn = $( this );
		$btn.prop( 'disabled', true );

		$.post( lccbAdmin.ajax_url, {
			action : 'lccb_clear_third_party_domains',
			nonce  : lccbAdmin.server_scan_nonce,
		} )
		.done( function ( res ) {
			if ( res && res.success ) {
				window.location.reload();
			} else {
				$btn.prop( 'disabled', false );
			}
		} )
		.fail( function () {
			$btn.prop( 'disabled', false );
		} );
	} );

	// Cleanup / delete old logs.
	$( document ).on( 'click', '#lccb-delete-btn', function () {
		if ( typeof lccbAdmin === 'undefined' ) { return; }

		var $btn   = $( this );
		var years  = parseInt( $( '#lccb-delete-period' ).val(), 10 );
		var label  = $( '#lccb-delete-period option:selected' ).text();
		var $msg   = $( '#lccb-delete-msg' );

		var confirmMsg = years === 0
			? lccbAdmin.confirmAll
			: lccbAdmin.confirmOld.replace( '{period}', label );

		if ( ! window.confirm( confirmMsg ) ) { return; }

		$btn.prop( 'disabled', true );
		$msg.text( '' ).removeClass( 'success error' );

		$.post(
			lccbAdmin.ajax_url,
			{
				action: 'lccb_delete_old_logs',
				nonce:  lccbAdmin.delete_nonce,
				years:  years,
			},
			function ( response ) {
				$btn.prop( 'disabled', false );
				if ( response.success ) {
					$msg.text( lccbAdmin.msgLogsDeleted.replace( '%d', response.data.deleted ) ).addClass( 'success' );
					setTimeout( function () { location.reload(); }, 1500 );
				} else {
					var errMsg = ( response.data && response.data.message ) ? response.data.message : lccbAdmin.errorMsg;
					$msg.text( errMsg ).addClass( 'error' );
				}
			}
		);
	} );

} )( jQuery );

/* ---- Cookie Registry tab ---- */
( function ( $ ) {
	'use strict';

	if ( typeof lccbAdmin === 'undefined' || ( ! $( '#lccb-registry-table' ).length && ! $( '#lccb-edit-detected-overlay' ).length ) ) {
		return;
	}

	var nonce = lccbAdmin.cookie_nonce;

	// Add a new cookie — open modal in "new" mode.
	$( document ).on( 'click', '#lccb-cookie-add-new', function () {
		openEditModal( 'new', { id: '', name: '', category: 'necessary', vendor: '', duration: '', description: '' } );
	} );

	// Delete a cookie.
	$( document ).on( 'click', '.lccb-cookie-delete', function () {
		if ( ! window.confirm( lccbAdmin.confirmCookieDelete ) ) { return; }
		var id = $( this ).data( 'id' );
		$.post( lccbAdmin.ajax_url, {
			action:    'lccb_cookie_delete',
			nonce:     nonce,
			cookie_id: id,
		}, function () { location.reload(); } );
	} );

	// Edit a cookie from the registry — open modal in "edit" mode.
	$( document ).on( 'click', '.lccb-cookie-edit', function () {
		var $row = $( this ).closest( 'tr' );
		openEditModal( 'edit', {
			id:          $row.data( 'id' ),
			name:        $row.data( 'name' ),
			category:    $row.data( 'category' ),
			vendor:      $row.data( 'vendor' ),
			duration:    $row.data( 'duration' ),
			description: $row.data( 'description' ),
		} );
	} );

	// Reset to defaults.
	$( document ).on( 'click', '#lccb-cookie-reset', function () {
		if ( ! window.confirm( lccbAdmin.confirmCookieReset ) ) { return; }
		$.post( lccbAdmin.ajax_url, {
			action: 'lccb_cookie_reset',
			nonce:  nonce,
		}, function () { location.reload(); } );
	} );

	// Add a detected cookie to the registry (single row button).
	$( document ).on( 'click', '.lccb-add-detected', function () {
		var $btn = $( this );
		$btn.prop( 'disabled', true );
		$.post( lccbAdmin.ajax_url, {
			action:      'lccb_cookie_add_detected',
			nonce:       nonce,
			name:        $btn.data( 'name' ),
			category:    $btn.data( 'category' ) || 'necessary',
			vendor:      $btn.data( 'vendor' ),
			duration:    $btn.data( 'duration' ),
			description: $btn.data( 'description' ),
		}, function ( resp ) {
			if ( resp.success ) {
				location.reload();
			} else {
				$btn.prop( 'disabled', false );
			}
		} );
	} );

	// Clear all detected cookies.
	$( document ).on( 'click', '#lccb-clear-detected', function () {
		if ( ! window.confirm( lccbAdmin.confirmClearDetected ) ) { return; }
		$.post( lccbAdmin.ajax_url, {
			action: 'lccb_clear_detected',
			nonce:  nonce,
		}, function () { location.reload(); } );
	} );

	// ---- Edit modal (shared for detected cookies and registry edits) ----------

	var $editOverlay = $( '#lccb-edit-detected-overlay' );

	/**
	 * Opens the modal.
	 * mode: 'add'  – add a detected cookie to registry (name is read-only)
	 * mode: 'edit' – edit an existing registry cookie (name is editable)
	 * mode: 'new'  – add a brand-new cookie (name is editable, blank)
	 */
	function openEditModal( mode, data ) {
		$editOverlay.find( '#lccb-edit-modal-mode' ).val( mode );
		$editOverlay.find( '#lccb-edit-modal-id' ).val( data.id || '' );

		if ( mode === 'edit' ) {
			$editOverlay.find( '#lccb-edit-modal-title' ).text( lccbAdmin.modalTitleEdit );
			$editOverlay.find( '#lccb-edit-detected-name-display' ).hide();
			$editOverlay.find( '#lccb-edit-detected-name-input' ).show().val( data.name || '' );
			$editOverlay.find( '#lccb-edit-detected-save' ).text( lccbAdmin.modalSaveEdit );
		} else if ( mode === 'new' ) {
			$editOverlay.find( '#lccb-edit-modal-title' ).text( lccbAdmin.modalTitleAdd );
			$editOverlay.find( '#lccb-edit-detected-name-display' ).hide();
			$editOverlay.find( '#lccb-edit-detected-name-input' ).show().val( '' );
			$editOverlay.find( '#lccb-edit-detected-save' ).text( lccbAdmin.modalSaveNew );
		} else if ( mode === 'detected' ) {
			// Detected cookie: name is editable so the user can correct it before adding.
			$editOverlay.find( '#lccb-edit-modal-title' ).text( lccbAdmin.modalTitleDetected );
			$editOverlay.find( '#lccb-edit-detected-name-display' ).hide();
			$editOverlay.find( '#lccb-edit-detected-name-input' ).show().val( data.name || '' );
			$editOverlay.find( '#lccb-edit-detected-save' ).text( lccbAdmin.modalSaveDetected );
		} else {
			$editOverlay.find( '#lccb-edit-modal-title' ).text( lccbAdmin.modalTitleDetected );
			$editOverlay.find( '#lccb-edit-detected-name-display' ).text( data.name || '' ).show();
			$editOverlay.find( '#lccb-edit-detected-name-input' ).hide();
			$editOverlay.find( '#lccb-edit-detected-save' ).text( lccbAdmin.modalSaveDetected );
		}

		$editOverlay.find( '#lccb-edit-detected-name' ).val( data.name || '' );
		$editOverlay.find( '#lccb-edit-detected-category' ).val( data.category || 'necessary' );
		$editOverlay.find( '#lccb-edit-detected-vendor' ).val( data.vendor || '' );
		$editOverlay.find( '#lccb-edit-detected-duration' ).val( data.duration || '' );
		$editOverlay.find( '#lccb-edit-detected-desc' ).val( data.description || '' );
		$editOverlay.find( '#lccb-edit-detected-msg' ).text( '' ).removeClass( 'success error' );
		$editOverlay.find( '#lccb-edit-detected-save' ).prop( 'disabled', false );
		$editOverlay.css( 'display', 'flex' );
	}

	function openEditDetectedModal( data ) {
		openEditModal( 'detected', data );
	}

	function closeEditDetectedModal() {
		$editOverlay.hide();
	}

	// Open modal when clicking "Edit" on a detected cookie row.
	$( document ).on( 'click', '.lccb-edit-detected', function () {
		var $btn = $( this );
		openEditDetectedModal( {
			name:        $btn.data( 'name' ),
			category:    $btn.data( 'category' ),
			vendor:      $btn.data( 'vendor' ),
			duration:    $btn.data( 'duration' ),
			description: $btn.data( 'description' ),
		} );
	} );

	// Close modal on X, Cancel, or overlay background click.
	$( document ).on( 'click', '#lccb-edit-detected-close, #lccb-edit-detected-cancel', closeEditDetectedModal );
	$( document ).on( 'click', '#lccb-edit-detected-overlay', function ( e ) {
		if ( $( e.target ).is( '#lccb-edit-detected-overlay' ) ) {
			closeEditDetectedModal();
		}
	} );

	// Save from modal: behaviour depends on mode.
	$( document ).on( 'click', '#lccb-edit-detected-save', function () {
		var $saveBtn = $( this );
		var $msg     = $editOverlay.find( '#lccb-edit-detected-msg' );
		var mode     = $editOverlay.find( '#lccb-edit-modal-mode' ).val();

		var name = ( mode === 'edit' || mode === 'new' || mode === 'detected' )
			? $editOverlay.find( '#lccb-edit-detected-name-input' ).val().trim()
			: $editOverlay.find( '#lccb-edit-detected-name' ).val().trim();

		if ( ! name ) {
			$msg.text( lccbAdmin.msgCookieNameRequired ).addClass( 'error' );
			return;
		}

		// Prevent adding a detected cookie whose name already exists in the registry.
		if ( mode === 'detected' ) {
			var registryNames = lccbAdmin.registryNames || [];
			if ( registryNames.indexOf( name ) !== -1 ) {
				$msg.text( lccbAdmin.msgNameInRegistry ).addClass( 'error' );
				return;
			}
		}

		$saveBtn.prop( 'disabled', true );
		$msg.text( '' ).removeClass( 'success error' );

		var postData = {
			nonce:       nonce,
			category:    $editOverlay.find( '#lccb-edit-detected-category' ).val() || 'necessary',
			vendor:      $editOverlay.find( '#lccb-edit-detected-vendor' ).val(),
			duration:    $editOverlay.find( '#lccb-edit-detected-duration' ).val(),
			description: $editOverlay.find( '#lccb-edit-detected-desc' ).val(),
		};

		if ( mode === 'edit' || mode === 'new' ) {
			postData.action    = 'lccb_cookie_save';
			postData.cookie_id = mode === 'edit' ? $editOverlay.find( '#lccb-edit-modal-id' ).val() : '';
			postData.name      = name;
		} else {
			postData.action = 'lccb_cookie_add_detected';
			postData.name   = name;
		}

		$.post( lccbAdmin.ajax_url, postData )
		.done( function ( resp ) {
			if ( resp && resp.success ) {
				$msg.text( lccbAdmin.msgCookieAdded ).addClass( 'success' );
				setTimeout( function () {
					closeEditDetectedModal();
					location.reload();
				}, 700 );
			} else {
				var errMsg = ( resp && resp.data && resp.data.message ) ? resp.data.message : lccbAdmin.errorMsg;
				$msg.text( errMsg ).addClass( 'error' );
				$saveBtn.prop( 'disabled', false );
			}
		} )
		.fail( function () {
			$msg.text( lccbAdmin.msgNetworkError ).addClass( 'error' );
			$saveBtn.prop( 'disabled', false );
		} );
	} );

} )( jQuery );

/* ---- API backoffice: reconnect / lookup / contribute ---- */
( function ( $ ) {
	'use strict';

	if ( typeof lccbAdmin === 'undefined' ) { return; }

	var apiNonce = lccbAdmin.api_nonce;

	// Reconnect — re-register with the backoffice to get/refresh the API key.
	$( document ).on( 'click', '#lccb-api-reconnect', function () {
		var $btn = $( this );
		var $msg = $( '#lccb-api-reconnect-msg' ).text( '' ).removeClass( 'success error' );
		$btn.prop( 'disabled', true );

		$.post( lccbAdmin.ajax_url, {
			action: 'lccb_api_reconnect',
			nonce:  apiNonce,
		} )
		.done( function ( res ) {
			if ( res && res.success ) {
				$msg.text( res.data.message + ( res.data.key_hint ? ' (' + res.data.key_hint + ')' : '' ) ).addClass( 'success' );
				setTimeout( function () { location.reload(); }, 1500 );
			} else {
				var errMsg = ( res && res.data && res.data.message ) ? res.data.message : lccbAdmin.apiOfflineMsg;
				$msg.text( errMsg ).addClass( 'error' );
				$btn.prop( 'disabled', false );
			}
		} )
		.fail( function () {
			$msg.text( lccbAdmin.apiOfflineMsg ).addClass( 'error' );
			$btn.prop( 'disabled', false );
		} );
	} );

	// Lookup — update incomplete registry cookies from the global database.
	$( document ).on( 'click', '#lccb-api-lookup', function () {
		var $btn = $( this );
		var $msg = $( '#lccb-api-lookup-msg' ).text( '' ).removeClass( 'success error' );
		var origText = $btn.text();
		$btn.prop( 'disabled', true ).text( lccbAdmin.msgLookupUpdating );

		$.post( lccbAdmin.ajax_url, {
			action: 'lccb_api_lookup',
			nonce:  apiNonce,
		} )
		.done( function ( res ) {
			if ( res && res.success ) {
				if ( res.data.ts_formatted ) {
					var $ts = $( '#lccb-api-lookup-ts' );
					$ts.text( lccbAdmin.msgLookupLastUpdate.replace( '%s', res.data.ts_formatted ) ).show();
				}
				if ( res.data.updated > 0 ) {
					// At least one cookie was matched and saved server-side (source: 'global_db').
					// Reload regardless of `remaining` so its "Checked" badge — rendered server-side
					// from the saved value — actually shows up instead of staying stale until a
					// manual refresh.
					if ( res.data.remaining > 0 ) {
						$msg.text(
							lccbAdmin.msgLookupPartial
								.replace( '%1$d', res.data.updated )
								.replace( '%2$d', res.data.remaining )
						).addClass( 'error' );
					} else {
						$msg.text( lccbAdmin.msgLookupUpdated.replace( '%d', res.data.updated ) ).addClass( 'success' );
					}
					setTimeout( function () { location.reload(); }, 1500 );
				} else if ( res.data.remaining > 0 ) {
					$btn.prop( 'disabled', false ).text( origText );
					$msg.text( lccbAdmin.msgLookupNoResults ).addClass( 'error' );
					$( '#lccb-bulk-contribute' ).show();
				} else {
					$btn.prop( 'disabled', false ).text( origText );
				}
			} else {
				$btn.prop( 'disabled', false ).text( origText );
				var errMsg = ( res && res.data && res.data.message ) ? res.data.message : lccbAdmin.apiOfflineMsg;
				$msg.text( errMsg ).addClass( 'error' );
			}
		} )
		.fail( function () {
			$btn.prop( 'disabled', false ).text( origText );
			$msg.text( lccbAdmin.apiOfflineMsg ).addClass( 'error' );
		} );
	} );

	// Bulk contribute — send all unknown cookies for review in one shot per session.
	$( document ).on( 'click', '#lccb-bulk-contribute', function () {
		if ( ! window.confirm( lccbAdmin.confirmBulkContribute ) ) { return; }

		var $btn = $( this );
		var $msg = $( '#lccb-api-lookup-msg' ).text( '' ).removeClass( 'success error' );
		$btn.prop( 'disabled', true );

		$.post( lccbAdmin.ajax_url, {
			action: 'lccb_api_contribute_all',
			nonce:  apiNonce,
		} )
		.done( function ( res ) {
			if ( res && res.success ) {
				$msg.text( lccbAdmin.msgBulkContributeSuccess ).addClass( 'success' );
				// button remains disabled for the rest of this page session
			} else {
				var errMsg = ( res && res.data && res.data.message ) ? res.data.message : lccbAdmin.apiOfflineMsg;
				if ( res && res.data && res.data.message === 'No unknown cookies to send.' ) {
					$msg.text( lccbAdmin.msgBulkContributeNone ).addClass( 'success' );
				} else {
					$btn.prop( 'disabled', false );
					$msg.text( errMsg ).addClass( 'error' );
				}
			}
		} )
		.fail( function () {
			$btn.prop( 'disabled', false );
			$msg.text( lccbAdmin.apiOfflineMsg ).addClass( 'error' );
		} );
	} );

} )( jQuery );

/* ---- Suggest Scripts to Community ---- */
( function ( $ ) {
	'use strict';

	if ( typeof lccbAdmin === 'undefined' ) { return; }
	if ( ! $( '#lccb-suggest-scripts-table' ).length && ! $( '#lccb-suggest-scripts-btn' ).length ) { return; }

	var apiNonce = lccbAdmin.api_nonce;

	$( document ).on( 'click', '#lccb-suggest-scripts-btn', function () {
		var $btn    = $( this );
		var $loader = $( '#lccb-suggest-scripts-loader' );
		var $msg    = $( '#lccb-suggest-scripts-msg' ).text( '' ).removeClass( 'success error' );

		$btn.prop( 'disabled', true );
		$loader.css( 'display', 'flex' );

		$.post( lccbAdmin.ajax_url, {
			action: 'lccb_suggest_scripts',
			nonce:  apiNonce,
		} )
		.done( function ( res ) {
			if ( res && res.success ) {
				var d = res.data;

				// Mark synced rows without reloading the page.
				( d.synced_urls || [] ).forEach( function ( url ) {
					$( '#lccb-suggest-scripts-table tbody tr' ).each( function () {
						if ( $( this ).attr( 'data-url' ) === url ) {
							$( this ).attr( 'data-synced', '1' );
							$( this ).find( '.lccb-synced-check' )
								.css( 'color', '#2e7d32' )
								.attr( 'title', 'Synced' )
								.html( '&#10003;' );
						}
					} );
				} );

				// Re-sort rows: unsynced first.
				var $tbody = $( '#lccb-suggest-scripts-table tbody' );
				var rows   = $tbody.find( 'tr' ).get();
				rows.sort( function ( a, b ) {
					return parseInt( $( a ).attr( 'data-synced' ) || '0', 10 ) - parseInt( $( b ).attr( 'data-synced' ) || '0', 10 );
				} );
				$.each( rows, function ( i, row ) { $tbody.append( row ); } );

				// Update last sync timestamp.
				if ( d.ts_formatted ) {
					var tpl = lccbAdmin.suggestScriptsLastSync || 'Last sync: %s';
					$( '#lccb-suggest-scripts-last-sync' ).text( tpl.replace( '%s', d.ts_formatted ) );
				}

				var sentMsg = ( lccbAdmin.msgSuggestScriptsSent || '%d script(s) sent successfully. Thank you!' )
					.replace( '%d', d.synced );
				$msg.text( sentMsg ).addClass( 'success' );
			} else {
				var errMsg = ( res && res.data && res.data.message ) ? res.data.message : lccbAdmin.apiOfflineMsg;
				$msg.text( errMsg ).addClass( 'error' );
				$btn.prop( 'disabled', false );
			}
		} )
		.fail( function () {
			$msg.text( lccbAdmin.apiOfflineMsg ).addClass( 'error' );
			$btn.prop( 'disabled', false );
		} )
		.always( function () {
			$loader.hide();
		} );
	} );

	$( document ).on( 'click', '#lccb-clear-detected-scripts', function () {
		var confirmMsg = lccbAdmin.confirmClearScripts || 'Clear the list of detected scripts? This cannot be undone.';
		if ( ! window.confirm( confirmMsg ) ) { return; }

		var $btn = $( this );
		$btn.prop( 'disabled', true );

		$.post( lccbAdmin.ajax_url, {
			action: 'lccb_clear_detected_scripts',
			nonce:  apiNonce,
		} )
		.done( function ( res ) {
			if ( res && res.success ) {
				window.location.reload();
			} else {
				$btn.prop( 'disabled', false );
			}
		} )
		.fail( function () {
			$btn.prop( 'disabled', false );
		} );
	} );

} )( jQuery );


/* ---- Full Website Scan, Add All, Bulk Third-Party Scan ---- */
( function ( $ ) {
	'use strict';

	if ( typeof lccbAdmin === 'undefined' ) { return; }

	$( document ).on( 'click', '.lccb-scan-page-btn', function () {
		var $btn  = $( this );
		var raw   = $btn.attr( 'data-url' ) || '';
		var force = $( '#lccb-scan-page-force' ).is( ':checked' ) ? '1' : '0';
		var $cell = $btn.closest( 'tr' ).find( '.lccb-last-scan' );
		var $msg  = $( '#lccb-scan-page-msg' );
		var scanUrl;

		$msg.text( '' ).removeClass( 'success error' );

		try {
			var parsed = new URL( raw );
			parsed.searchParams.set( 'lccb_scan', '1' );
			parsed.searchParams.set( 'lccb_force_consent', force );
			scanUrl = parsed.toString();
		} catch ( e ) {
			$msg.text( lccbAdmin.msgInvalidUrl ).addClass( 'error' );
			return;
		}

		var win = window.open( scanUrl, '_blank' );
		if ( ! win || win.closed || typeof win.closed === 'undefined' ) {
			$msg.html(
				lccbAdmin.msgPopupBlocked + ' ' +
				'<a href="' + scanUrl + '" target="_blank" rel="noopener">' + lccbAdmin.msgPopupBlockedLink + '</a>.'
			).addClass( 'error' );
		} else {
			$msg.text( lccbAdmin.msgScanStarted ).addClass( 'success' );
			$.post( lccbAdmin.ajax_url, {
				action: 'lccb_record_page_scan',
				nonce:  lccbAdmin.scan_page_nonce,
				url:    raw,
			}, function ( res ) {
				if ( res.success && res.data && res.data.timestamp ) {
					$cell.text( res.data.timestamp );
				}
			} );
		}
	} );

	$( document ).on( 'click', '#lccb-add-all-detected', function () {
		if ( ! window.confirm( lccbAdmin.confirmAddAll ) ) { return; }
		var $btn = $( this );
		var $msg = $( '#lccb-add-all-detected-msg' ).text( '' ).removeClass( 'success error' );
		$btn.prop( 'disabled', true );

		$.post(
			lccbAdmin.ajax_url,
			{ action: 'lccb_cookie_add_all_detected', nonce: lccbAdmin.cookie_nonce }
		).done( function ( res ) {
			if ( res && res.success ) {
				if ( res.data.added > 0 ) {
					$msg.text( lccbAdmin.msgAddAllDone.replace( '%d', res.data.added ) ).addClass( 'success' );
					setTimeout( function () { location.reload(); }, 1200 );
				} else {
					$msg.text( lccbAdmin.msgAddAllNone ).addClass( 'success' );
					$btn.prop( 'disabled', false );
				}
			} else {
				var errMsg = ( res && res.data && res.data.message ) ? res.data.message : lccbAdmin.errorMsg;
				$msg.text( errMsg ).addClass( 'error' );
				$btn.prop( 'disabled', false );
			}
		} ).fail( function () {
			$msg.text( lccbAdmin.msgNetworkError ).addClass( 'error' );
			$btn.prop( 'disabled', false );
		} );
	} );

	$( document ).on( 'click', '#lccb-scan-third-party-start', function () {
		var $btn    = $( this );
		var $loader = $( '#lccb-third-party-loader' );
		var $msg    = $( '#lccb-third-party-msg' );

		$msg.text( '' ).removeClass( 'success error' );
		$btn.prop( 'disabled', true );
		$( '#lccb-clear-third-party-domains' ).prop( 'disabled', true );
		$loader.css( 'display', 'flex' );

		$.post( lccbAdmin.ajax_url, {
			action: 'lccb_scan_third_party',
			nonce:  lccbAdmin.server_scan_nonce,
		} ).done( function ( res ) {
			if ( res && res.success ) {
				var d    = res.data;
				var text = lccbAdmin.msgThirdPartyScanDone
					.replace( '%1$s', d.scanned )
					.replace( '%2$s', d.cookies );
				if ( d.failed && d.failed.length ) {
					text += ' ' + lccbAdmin.msgThirdPartyScanFail + ' ' + d.failed.join( ', ' ) + '.';
				}
				if ( d.cookies > 0 ) {
					text += ' ' + lccbAdmin.msgThirdPartyScanMore;
				}
				$msg.text( text ).addClass( 'success' );
			} else {
				var errMsg = ( res && res.data && res.data.message ) ? res.data.message : lccbAdmin.errorMsg;
				$msg.text( lccbAdmin.msgErrorPrefix + ' ' + errMsg ).addClass( 'error' );
			}
		} ).fail( function ( xhr ) {
			$msg.text( lccbAdmin.msgNetworkError + ' (HTTP ' + ( xhr.status || '?' ) + ')' ).addClass( 'error' );
		} ).always( function () {
			$btn.prop( 'disabled', false );
			$( '#lccb-clear-third-party-domains' ).prop( 'disabled', false );
			$loader.hide();
		} );
	} );

} )( jQuery );


/* ---- Cookie Registry filters ---- */
( function ( $ ) {
	'use strict';

	var $table = $( '#lccb-registry-table' );
	var $count = $( '#lccb-filter-count' );

	if ( ! $table.length ) { return; }

	function applyFilters() {
		var cat = $( '#lccb-filter-category' ).val();
		var q   = ( $( '#lccb-filter-search' ).val() || '' ).toLowerCase().trim();
		var visible = 0;

		$table.find( 'tbody tr' ).each( function () {
			var $row    = $( this );
			var rowCat  = ( $row.data( 'category' ) || '' ).toString();
			var rowName = ( $row.data( 'name' )        || '' ).toString().toLowerCase();
			var rowVend = ( $row.data( 'vendor' )      || '' ).toString().toLowerCase();
			var rowDesc = ( $row.data( 'description' ) || '' ).toString().toLowerCase();

			var matchCat = ! cat || rowCat === cat;
			var matchQ   = ! q   || rowName.indexOf( q ) !== -1 || rowVend.indexOf( q ) !== -1 || rowDesc.indexOf( q ) !== -1;

			if ( matchCat && matchQ ) {
				$row.show();
				visible++;
			} else {
				$row.hide();
			}
		} );

		var total = $table.find( 'tbody tr' ).length;
		$count.text( visible < total ? ( visible + ' / ' + total ) : '' );
	}

	$( document ).on( 'change input', '#lccb-filter-category, #lccb-filter-search', applyFilters );

	$( document ).on( 'click', '#lccb-filter-reset', function () {
		$( '#lccb-filter-category' ).val( '' );
		$( '#lccb-filter-search' ).val( '' );
		applyFilters();
	} );

} )( jQuery );
