<?php

defined( 'ABSPATH' ) || exit;

/**
 * Sidebars module.
 *
 * Lets the site owner manage widget areas without editing the theme:
 *  - Register any number of custom sidebars with a chosen slug, display name,
 *    and description. New sidebars appear in Appearance → Widgets and can be
 *    rendered anywhere via the `[bw_dev_sidebar slug="..."]` shortcode (works
 *    inside any block, Kadence header/footer builder, template parts, etc.).
 *  - Unregister theme- or plugin-provided sidebars that aren't wanted. Widgets
 *    attached to an unregistered sidebar move to "Inactive widgets" in
 *    Appearance → Widgets — they aren't deleted, so re-registering brings
 *    them back automatically.
 *
 * Hook timing:
 *  - register_sidebar() runs on widgets_init priority 11 (default theme
 *    registrations are at priority 10).
 *  - unregister_sidebar() runs on widgets_init priority 99 so it sees every
 *    registration first (theme + plugins + our own).
 *  - The output shortcode is registered on init.
 *
 * @package BW_Dev
 */

class BW_Dev_Module_Sidebars implements BW_Dev_Module_Interface {

	const SHORTCODE = 'bw_dev_sidebar';

	public function slug(): string {
		return 'sidebars';
	}

	public function label(): string {
		return __( 'Sidebars', 'bw-dev' );
	}

	public function group(): string {
		return 'frontend';
	}

	public function default_settings(): array {
		return array(
			'custom'     => array(),
			'unregister' => array(),
		);
	}

	public function sanitize( array $data ): array {
		$custom_raw = isset( $data['custom'] ) && is_array( $data['custom'] ) ? $data['custom'] : array();
		$custom     = array();
		$seen       = array();

		foreach ( $custom_raw as $row ) {
			if ( ! is_array( $row ) ) {
				continue;
			}
			$slug        = isset( $row['slug'] ) ? sanitize_title( (string) $row['slug'] ) : '';
			$name        = isset( $row['name'] ) ? sanitize_text_field( wp_unslash( (string) $row['name'] ) ) : '';
			$description = isset( $row['description'] ) ? sanitize_text_field( wp_unslash( (string) $row['description'] ) ) : '';

			// Skip empty rows and duplicates.
			if ( '' === $slug || '' === $name ) {
				continue;
			}
			if ( isset( $seen[ $slug ] ) ) {
				continue;
			}
			$seen[ $slug ] = true;

			$custom[] = array(
				'slug'        => $slug,
				'name'        => $name,
				'description' => $description,
			);
		}

		$unreg_raw = isset( $data['unregister'] ) && is_array( $data['unregister'] ) ? $data['unregister'] : array();
		$unreg     = array();
		foreach ( $unreg_raw as $id ) {
			$id = sanitize_title( (string) $id );
			if ( '' === $id ) {
				continue;
			}
			$unreg[] = $id;
		}

		return array(
			'custom'     => $custom,
			'unregister' => array_values( array_unique( $unreg ) ),
		);
	}

	public function register(): void {
		add_action( 'widgets_init', array( $this, 'register_custom_sidebars' ), 11 );
		add_action( 'widgets_init', array( $this, 'unregister_sidebars' ),     99 );
		add_action( 'init',         array( $this, 'register_shortcode' ) );
	}

	public function register_custom_sidebars(): void {
		$customs = bw_dev()->settings()->get( $this->slug(), 'custom', array() );
		if ( ! is_array( $customs ) ) {
			return;
		}
		foreach ( $customs as $row ) {
			if ( ! is_array( $row ) || empty( $row['slug'] ) || empty( $row['name'] ) ) {
				continue;
			}
			register_sidebar(
				array(
					'id'            => (string) $row['slug'],
					'name'          => (string) $row['name'],
					'description'   => isset( $row['description'] ) ? (string) $row['description'] : '',
					'before_widget' => '<section id="%1$s" class="widget %2$s">',
					'after_widget'  => '</section>',
					'before_title'  => '<h2 class="widget-title">',
					'after_title'   => '</h2>',
				)
			);
		}
	}

	public function unregister_sidebars(): void {
		$ids = bw_dev()->settings()->get( $this->slug(), 'unregister', array() );
		if ( ! is_array( $ids ) ) {
			return;
		}

		// Never unregister our own customs — guard in case a slug ended up in both lists.
		$customs       = bw_dev()->settings()->get( $this->slug(), 'custom', array() );
		$custom_slugs  = array();
		if ( is_array( $customs ) ) {
			foreach ( $customs as $row ) {
				if ( is_array( $row ) && ! empty( $row['slug'] ) ) {
					$custom_slugs[ (string) $row['slug'] ] = true;
				}
			}
		}

		foreach ( $ids as $id ) {
			$id = (string) $id;
			if ( '' === $id || isset( $custom_slugs[ $id ] ) ) {
				continue;
			}
			unregister_sidebar( $id );
		}
	}

	public function register_shortcode(): void {
		add_shortcode( self::SHORTCODE, array( $this, 'render_shortcode' ) );
	}

	public function render_shortcode( $atts ): string {
		$atts = shortcode_atts(
			array(
				'slug' => '',
			),
			(array) $atts,
			self::SHORTCODE
		);
		$slug = sanitize_title( (string) $atts['slug'] );
		if ( '' === $slug || ! is_registered_sidebar( $slug ) ) {
			return '';
		}
		if ( ! is_active_sidebar( $slug ) ) {
			return '';
		}
		ob_start();
		dynamic_sidebar( $slug );
		return (string) ob_get_clean();
	}

	/* ---------------------------------------------------------------------
	 * Settings tab
	 * ------------------------------------------------------------------- */

	public function render_tab(): void {
		$customs = bw_dev()->settings()->get( $this->slug(), 'custom', array() );
		$unreg   = bw_dev()->settings()->get( $this->slug(), 'unregister', array() );
		if ( ! is_array( $customs ) ) {
			$customs = array();
		}
		if ( ! is_array( $unreg ) ) {
			$unreg = array();
		}
		$unreg_map = array_flip( $unreg );

		$registered    = isset( $GLOBALS['wp_registered_sidebars'] ) && is_array( $GLOBALS['wp_registered_sidebars'] )
			? $GLOBALS['wp_registered_sidebars']
			: array();
		$custom_slugs  = array();
		foreach ( $customs as $row ) {
			if ( is_array( $row ) && ! empty( $row['slug'] ) ) {
				$custom_slugs[ (string) $row['slug'] ] = true;
			}
		}

		$base = BW_Dev_Settings::OPTION . '[' . $this->slug() . ']';
		?>
		<p class="description">
			<?php esc_html_e( 'Register your own widget areas (sidebars) and unregister ones you don\'t need. Render any sidebar anywhere with the shortcode below.', 'bw-dev' ); ?>
		</p>

		<h3><?php esc_html_e( 'Custom sidebars', 'bw-dev' ); ?></h3>
		<p class="description"><?php esc_html_e( 'Each row registers one sidebar. Slug is the internal ID used by the shortcode; Name shows in Appearance → Widgets.', 'bw-dev' ); ?></p>

		<table class="widefat striped" id="bw-dev-sidebars-table" style="max-width:960px;margin-top:8px;">
			<thead>
				<tr>
					<th style="width:24%;"><?php esc_html_e( 'Slug', 'bw-dev' ); ?></th>
					<th style="width:26%;"><?php esc_html_e( 'Name', 'bw-dev' ); ?></th>
					<th style="width:40%;"><?php esc_html_e( 'Description', 'bw-dev' ); ?></th>
					<th style="width:10%;"></th>
				</tr>
			</thead>
			<tbody id="bw-dev-sidebars-tbody">
				<?php
				$rows = $customs;
				if ( empty( $rows ) ) {
					$rows = array( array( 'slug' => '', 'name' => '', 'description' => '' ) );
				}
				foreach ( $rows as $idx => $row ) :
					$slug = isset( $row['slug'] ) ? (string) $row['slug'] : '';
					$name = isset( $row['name'] ) ? (string) $row['name'] : '';
					$desc = isset( $row['description'] ) ? (string) $row['description'] : '';
					?>
					<tr class="bw-dev-sidebar-row">
						<td><input type="text" name="<?php echo esc_attr( $base . '[custom][' . $idx . '][slug]' ); ?>" value="<?php echo esc_attr( $slug ); ?>" class="regular-text code" placeholder="footer-cta" style="width:100%;" /></td>
						<td><input type="text" name="<?php echo esc_attr( $base . '[custom][' . $idx . '][name]' ); ?>" value="<?php echo esc_attr( $name ); ?>" class="regular-text" placeholder="<?php esc_attr_e( 'Footer CTA', 'bw-dev' ); ?>" style="width:100%;" /></td>
						<td><input type="text" name="<?php echo esc_attr( $base . '[custom][' . $idx . '][description]' ); ?>" value="<?php echo esc_attr( $desc ); ?>" class="regular-text" placeholder="<?php esc_attr_e( 'Where this sidebar is used (optional).', 'bw-dev' ); ?>" style="width:100%;" /></td>
						<td><button type="button" class="button button-link-delete bw-dev-sidebar-delete"><?php esc_html_e( 'Remove', 'bw-dev' ); ?></button></td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
		<p style="margin-top:8px;">
			<button type="button" class="button button-secondary" id="bw-dev-sidebars-add"><?php esc_html_e( '+ Add sidebar', 'bw-dev' ); ?></button>
		</p>

		<h3><?php esc_html_e( 'Unregister existing sidebars', 'bw-dev' ); ?></h3>
		<p class="description">
			<?php esc_html_e( 'Tick a sidebar to unregister it. Widgets attached to it move to "Inactive widgets" — they\'re not deleted, untick to bring them back.', 'bw-dev' ); ?>
		</p>

		<?php if ( empty( $registered ) ) : ?>
			<p><?php esc_html_e( 'No sidebars currently registered.', 'bw-dev' ); ?></p>
		<?php else : ?>
			<fieldset style="border:1px solid #c3c4c7;background:#fff;padding:12px 18px;max-width:960px;">
				<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:6px 18px;">
					<?php foreach ( $registered as $sid => $sidebar ) :
						$sid = (string) $sid;
						if ( isset( $custom_slugs[ $sid ] ) ) {
							// Don't show our own registered sidebars in the unregister list.
							continue;
						}
						$name       = isset( $sidebar['name'] ) ? (string) $sidebar['name'] : $sid;
						$is_checked = isset( $unreg_map[ $sid ] );
						$field_name = $base . '[unregister][]';
						?>
						<label style="display:flex;align-items:flex-start;gap:6px;">
							<input type="checkbox" name="<?php echo esc_attr( $field_name ); ?>" value="<?php echo esc_attr( $sid ); ?>" <?php checked( $is_checked ); ?> />
							<span>
								<?php echo esc_html( $name ); ?>
								<br /><code style="color:#646970;font-size:11px;"><?php echo esc_html( $sid ); ?></code>
							</span>
						</label>
					<?php endforeach; ?>
				</div>
			</fieldset>
		<?php endif; ?>

		<h3><?php esc_html_e( 'Output a sidebar', 'bw-dev' ); ?></h3>
		<p><?php esc_html_e( 'Drop this shortcode anywhere — block content, Kadence header/footer builder, template parts:', 'bw-dev' ); ?></p>
		<pre style="background:#f6f7f7;padding:10px 14px;max-width:720px;border-left:4px solid #2271b1;"><code>[<?php echo esc_html( self::SHORTCODE ); ?> slug="footer-cta"]</code></pre>
		<p class="description"><?php esc_html_e( 'The shortcode returns empty if the sidebar isn\'t registered or has no active widgets — safe to leave in place even before you\'ve added widgets to it.', 'bw-dev' ); ?></p>

		<script>
		(function () {
			var tbody = document.getElementById('bw-dev-sidebars-tbody');
			var addBtn = document.getElementById('bw-dev-sidebars-add');
			if (!tbody || !addBtn) return;

			function nextIndex() {
				var rows = tbody.querySelectorAll('tr.bw-dev-sidebar-row');
				return rows.length;
			}

			function bindDelete(row) {
				var btn = row.querySelector('.bw-dev-sidebar-delete');
				if (!btn) return;
				btn.addEventListener('click', function (e) {
					e.preventDefault();
					row.parentNode.removeChild(row);
				});
			}

			tbody.querySelectorAll('tr.bw-dev-sidebar-row').forEach(bindDelete);

			addBtn.addEventListener('click', function (e) {
				e.preventDefault();
				var idx = nextIndex();
				var base = <?php echo wp_json_encode( $base . '[custom]' ); ?>;
				var tr = document.createElement('tr');
				tr.className = 'bw-dev-sidebar-row';
				tr.innerHTML =
					'<td><input type="text" name="' + base + '[' + idx + '][slug]" value="" class="regular-text code" placeholder="footer-cta" style="width:100%;" /></td>' +
					'<td><input type="text" name="' + base + '[' + idx + '][name]" value="" class="regular-text" placeholder="" style="width:100%;" /></td>' +
					'<td><input type="text" name="' + base + '[' + idx + '][description]" value="" class="regular-text" placeholder="" style="width:100%;" /></td>' +
					'<td><button type="button" class="button button-link-delete bw-dev-sidebar-delete">' + <?php echo wp_json_encode( __( 'Remove', 'bw-dev' ) ); ?> + '</button></td>';
				tbody.appendChild(tr);
				bindDelete(tr);
			});
		})();
		</script>
		<?php
	}

	public function uninstall(): void {
		// Settings live under bw_dev_settings — root option drop covers them.
		// Widget assignments stay in the sidebars_widgets option as "Inactive"
		// after the sidebars stop being registered.
	}
}
