<?php
/**
 * Scroll Down module. Renders a scroll-down indicator (animated SVG) that
 * smooth-scrolls to the next section or a configured anchor. Two ways to place
 * it: the [bw_dev_scroll_down] shortcode, or by adding a trigger CSS class to
 * any Kadence row (the indicator is injected + wired automatically).
 *
 * Ported from the standalone `bw-scroll-down` plugin (v4.0.0). Re-prefixed:
 *   - Option:    bw_scroll_down_settings → bw_dev_settings[scroll_down]
 *   - JS config: window.bwScrollDownSettings → bwDevScrollDownConfig
 *   - CSS:       .bw-scroll-down* → .bw-dev-scroll-down*, @keyframes bw-float → bw-dev-float
 *   - Shortcode: [bw_scroll_down] → [bw_dev_scroll_down] (legacy tag kept as a
 *                back-compat alias only when nothing else registers it)
 *
 * The frontend logic is ported from the plugin's (clean) inlined footer script,
 * NOT the stale debug copy that shipped in its assets/js/ directory.
 *
 * @package BW_Dev
 */

defined( 'ABSPATH' ) || exit;

class BW_Dev_Module_Scroll_Down implements BW_Dev_Module_Interface {

	private const DEFAULTS = array(
		'icon_type'     => 'chevron',
		'icon_size'     => 40,
		'icon_color'    => '#ffffff',
		'label_text'    => '',
		'bottom_offset' => '5',
		'anchor_target' => '#start',
		'trigger_class' => 'has-scroll-down',
		'auto_target'   => 1,
		'animate'       => 1,
	);

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

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

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

	public function default_settings(): array {
		return self::DEFAULTS;
	}

	/**
	 * Available indicator icons. Each value is a stroke-based SVG with no
	 * width/height/color — those are injected by icon_svg().
	 */
	private static function icons(): array {
		return array(
			'chevron'        => array(
				'label' => __( 'Chevron', 'bw-dev' ),
				'svg'   => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>',
			),
			'chevron-double' => array(
				'label' => __( 'Double Chevron', 'bw-dev' ),
				'svg'   => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 6 12 12 18 6"></polyline><polyline points="6 12 12 18 18 12"></polyline></svg>',
			),
			'arrow'          => array(
				'label' => __( 'Arrow', 'bw-dev' ),
				'svg'   => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><polyline points="19 12 12 19 5 12"></polyline></svg>',
			),
			'arrow-circle'   => array(
				'label' => __( 'Circle Arrow', 'bw-dev' ),
				'svg'   => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polyline points="8 12 12 16 16 12"></polyline><line x1="12" y1="8" x2="12" y2="16"></line></svg>',
			),
			'mouse'          => array(
				'label' => __( 'Mouse', 'bw-dev' ),
				'svg'   => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="3" width="12" height="18" rx="6"></rect><line x1="12" y1="7" x2="12" y2="11"></line></svg>',
			),
			'angle'          => array(
				'label' => __( 'Angle', 'bw-dev' ),
				'svg'   => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="5 10 12 17 19 10"></polyline></svg>',
			),
		);
	}

	public function sanitize( array $data ): array {
		$icons = self::icons();

		$icon_type = isset( $data['icon_type'] ) ? sanitize_text_field( wp_unslash( (string) $data['icon_type'] ) ) : self::DEFAULTS['icon_type'];
		$icon_type = isset( $icons[ $icon_type ] ) ? $icon_type : self::DEFAULTS['icon_type'];

		$icon_size = isset( $data['icon_size'] ) ? max( 20, min( 100, absint( $data['icon_size'] ) ) ) : self::DEFAULTS['icon_size'];

		$icon_color = isset( $data['icon_color'] ) ? sanitize_hex_color( wp_unslash( (string) $data['icon_color'] ) ) : '';
		$icon_color = $icon_color ? $icon_color : self::DEFAULTS['icon_color'];

		$label_text = isset( $data['label_text'] ) ? sanitize_text_field( wp_unslash( (string) $data['label_text'] ) ) : '';

		$bottom_offset = isset( $data['bottom_offset'] ) ? sanitize_text_field( wp_unslash( (string) $data['bottom_offset'] ) ) : self::DEFAULTS['bottom_offset'];
		$bottom_offset = preg_match( '/^[0-9]+(px|%)?$/', $bottom_offset ) ? $bottom_offset : self::DEFAULTS['bottom_offset'];

		$anchor = isset( $data['anchor_target'] ) ? sanitize_text_field( wp_unslash( (string) $data['anchor_target'] ) ) : self::DEFAULTS['anchor_target'];
		if ( '' !== $anchor && 0 !== strpos( $anchor, '#' ) ) {
			$anchor = '#' . $anchor;
		}
		$anchor = '' !== $anchor ? $anchor : self::DEFAULTS['anchor_target'];

		$trigger_class = isset( $data['trigger_class'] ) ? sanitize_html_class( wp_unslash( (string) $data['trigger_class'] ) ) : '';
		$trigger_class = $trigger_class ? $trigger_class : self::DEFAULTS['trigger_class'];

		return array(
			'icon_type'     => $icon_type,
			'icon_size'     => $icon_size,
			'icon_color'    => $icon_color,
			'label_text'    => $label_text,
			'bottom_offset' => $bottom_offset,
			'anchor_target' => $anchor,
			'trigger_class' => $trigger_class,
			'auto_target'   => ! empty( $data['auto_target'] ) ? 1 : 0,
			'animate'       => ! empty( $data['animate'] ) ? 1 : 0,
		);
	}

	private function settings(): array {
		$saved = bw_dev()->settings()->get( $this->slug(), null, array() );
		return wp_parse_args( is_array( $saved ) ? $saved : array(), self::DEFAULTS );
	}

	private function get( string $key ) {
		$s = $this->settings();
		return $s[ $key ] ?? ( self::DEFAULTS[ $key ] ?? null );
	}

	/**
	 * Build an icon SVG with width/height/color injected. The icon key is
	 * validated against the known set; $color is escaped for the style attr,
	 * $size is cast to int.
	 */
	private function icon_svg( string $icon_type, int $size = 40, string $color = '#ffffff' ): string {
		$icons = self::icons();
		$icon  = $icons[ $icon_type ] ?? $icons['chevron'];
		return str_replace(
			'<svg ',
			'<svg width="' . (int) $size . '" height="' . (int) $size . '" style="color:' . esc_attr( $color ) . ';" ',
			$icon['svg']
		);
	}

	/**
	 * A bare numeric offset means percent; an explicit px value passes through.
	 */
	private function parse_offset( string $offset ): string {
		return is_numeric( $offset ) ? $offset . '%' : $offset;
	}

	public function register(): void {
		add_action( 'wp_head', array( $this, 'output_css' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue' ) );

		add_shortcode( 'bw_dev_scroll_down', array( $this, 'shortcode_output' ) );
		if ( ! shortcode_exists( 'bw_scroll_down' ) ) {
			add_shortcode( 'bw_scroll_down', array( $this, 'shortcode_output' ) );
		}
	}

	public function admin_enqueue( $hook ): void {
		if ( 'settings_page_' . BW_Dev_Admin_Page::MENU_SLUG !== $hook ) {
			return;
		}
		$query = wp_unslash( $_GET ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$tab   = isset( $query['tab'] ) ? sanitize_key( (string) $query['tab'] ) : 'modules';
		if ( $this->slug() !== $tab ) {
			return;
		}
		wp_enqueue_style( 'wp-color-picker' );
		wp_enqueue_script( 'wp-color-picker' );
	}

	public function output_css(): void {
		$trigger = sanitize_html_class( (string) $this->get( 'trigger_class' ) );
		$bottom  = $this->parse_offset( (string) $this->get( 'bottom_offset' ) );
		?>
		<style id="bw-dev-scroll-down-css">
			.bw-dev-scroll-down { display: inline-block !important; text-align: center; visibility: visible !important; opacity: 1 !important; }
			.bw-dev-scroll-down__text { display: block; font-size: 11px; font-weight: 500; letter-spacing: 3px; text-transform: uppercase; margin-bottom: 12px; }
			.bw-dev-scroll-down__link { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; transition: opacity 0.3s ease; }
			.bw-dev-scroll-down__link:hover { opacity: 0.7; }
			.bw-dev-scroll-down__icon { display: inline-flex; align-items: center; justify-content: center; }
			.bw-dev-scroll-down__icon svg { display: block; }
			.bw-dev-scroll-down--auto { position: absolute; bottom: <?php echo esc_attr( $bottom ); ?>; left: 50%; transform: translateX(-50%); z-index: 100; }
			<?php if ( '' !== $trigger ) : ?>
			.<?php echo esc_attr( $trigger ); ?> { position: relative !important; }
			<?php endif; ?>
			@keyframes bw-dev-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(8px); } }
			.bw-dev-scroll-down--animated .bw-dev-scroll-down__icon { animation: bw-dev-float 2.5s ease-in-out infinite; }
			.bw-dev-scroll-down--animated:hover .bw-dev-scroll-down__icon { animation-play-state: paused; }
		</style>
		<?php
	}

	public function enqueue_assets(): void {
		wp_enqueue_script(
			'bw-dev-scroll-down',
			BW_DEV_URL . 'assets/js/scroll-down.js',
			array(),
			BW_DEV_VERSION,
			true
		);

		$color = (string) $this->get( 'icon_color' );
		$color = $color ? $color : '#ffffff';
		$size  = (int) $this->get( 'icon_size' );

		wp_localize_script(
			'bw-dev-scroll-down',
			'bwDevScrollDownConfig',
			array(
				'anchorTarget' => (string) $this->get( 'anchor_target' ),
				'labelText'    => (string) $this->get( 'label_text' ),
				'iconSvg'      => $this->icon_svg( (string) $this->get( 'icon_type' ), $size, $color ),
				'iconColor'    => $color,
				'triggerClass' => sanitize_html_class( (string) $this->get( 'trigger_class' ) ),
				'autoTarget'   => (bool) $this->get( 'auto_target' ),
				'animateClass' => $this->get( 'animate' ) ? ' bw-dev-scroll-down--animated' : '',
			)
		);
	}

	/**
	 * Shortcode: [bw_dev_scroll_down anchor="" label="" icon="" size="" color=""]
	 */
	public function shortcode_output( $atts = array() ): string {
		$atts = shortcode_atts(
			array(
				'anchor' => (string) $this->get( 'anchor_target' ),
				'label'  => (string) $this->get( 'label_text' ),
				'icon'   => (string) $this->get( 'icon_type' ),
				'size'   => (int) $this->get( 'icon_size' ),
				'color'  => (string) $this->get( 'icon_color' ),
			),
			$atts,
			'bw_dev_scroll_down'
		);

		$anchor        = esc_attr( (string) $atts['anchor'] );
		$label         = esc_html( (string) $atts['label'] );
		$size          = absint( $atts['size'] );
		$color         = esc_attr( (string) $atts['color'] );
		$color         = $color ? $color : '#ffffff';
		$animate_class = $this->get( 'animate' ) ? ' bw-dev-scroll-down--animated' : '';

		$label_html = '' !== $label ? '<span class="bw-dev-scroll-down__text" style="color:' . $color . ';">' . $label . '</span>' : '';
		$icon_svg   = $this->icon_svg( isset( self::icons()[ $atts['icon'] ] ) ? (string) $atts['icon'] : 'chevron', $size, $color );

		$out  = '<div class="bw-dev-scroll-down bw-dev-scroll-down--shortcode' . $animate_class . '">';
		$out .= $label_html;
		$out .= '<a href="' . $anchor . '" class="bw-dev-scroll-down__link" style="color:' . $color . ';">';
		$out .= '<span class="bw-dev-scroll-down__icon">' . $icon_svg . '</span>';
		$out .= '</a>';
		$out .= '</div>';

		return $out;
	}

	public function render_tab(): void {
		$settings = $this->settings();
		$icons    = self::icons();
		$pfx      = BW_Dev_Settings::OPTION . '[' . $this->slug() . ']';
		?>
		<p class="description">
			<?php esc_html_e( 'A scroll-down indicator for hero sections. Place it with the shortcode, or add the trigger class to any Kadence row to inject it automatically. Clicking it smooth-scrolls to the next section (or a fixed anchor).', 'bw-dev' ); ?>
		</p>

		<h3><?php esc_html_e( 'Icon', 'bw-dev' ); ?></h3>
		<div style="display:flex; flex-wrap:wrap; gap:12px;">
			<?php foreach ( $icons as $key => $icon ) :
				$is_sel = ( $settings['icon_type'] === $key );
				?>
				<label class="bw-dev-scroll-icon-option" style="display:flex; flex-direction:column; align-items:center; padding:15px 20px; border:2px solid <?php echo $is_sel ? '#2271b1' : '#ddd'; ?>; border-radius:8px; cursor:pointer; background:#1a1a2e; min-width:90px;">
					<input type="radio" name="<?php echo esc_attr( $pfx ); ?>[icon_type]" value="<?php echo esc_attr( $key ); ?>" <?php checked( $settings['icon_type'], $key ); ?> class="bw-dev-scroll-icon-radio" style="display:none;">
					<span style="color:#fff; width:36px; height:36px;"><?php echo $icon['svg']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static SVG markup. ?></span>
					<span style="margin-top:8px; font-size:11px; color:#aaa;"><?php echo esc_html( $icon['label'] ); ?></span>
				</label>
			<?php endforeach; ?>
		</div>

		<h3><?php esc_html_e( 'Appearance', 'bw-dev' ); ?></h3>
		<table class="form-table" role="presentation">
			<tbody>
				<tr>
					<th scope="row"><label for="bw-dev-scroll-size"><?php esc_html_e( 'Icon size', 'bw-dev' ); ?></label></th>
					<td><input type="number" id="bw-dev-scroll-size" name="<?php echo esc_attr( $pfx ); ?>[icon_size]" value="<?php echo esc_attr( (string) $settings['icon_size'] ); ?>" class="small-text" min="20" max="100"> px</td>
				</tr>
				<tr>
					<th scope="row"><label for="bw-dev-scroll-color"><?php esc_html_e( 'Icon color', 'bw-dev' ); ?></label></th>
					<td><input type="text" id="bw-dev-scroll-color" name="<?php echo esc_attr( $pfx ); ?>[icon_color]" value="<?php echo esc_attr( (string) $settings['icon_color'] ); ?>" class="bw-dev-scroll-color-picker"></td>
				</tr>
				<tr>
					<th scope="row"><label for="bw-dev-scroll-label"><?php esc_html_e( 'Label text', 'bw-dev' ); ?></label></th>
					<td>
						<input type="text" id="bw-dev-scroll-label" name="<?php echo esc_attr( $pfx ); ?>[label_text]" value="<?php echo esc_attr( (string) $settings['label_text'] ); ?>" class="regular-text" placeholder="SCROLL">
						<p class="description"><?php esc_html_e( 'Optional text above the icon.', 'bw-dev' ); ?></p>
					</td>
				</tr>
				<tr>
					<th scope="row"><label for="bw-dev-scroll-offset"><?php esc_html_e( 'Bottom offset', 'bw-dev' ); ?></label></th>
					<td>
						<input type="text" id="bw-dev-scroll-offset" name="<?php echo esc_attr( $pfx ); ?>[bottom_offset]" value="<?php echo esc_attr( (string) $settings['bottom_offset'] ); ?>" class="small-text" placeholder="5">
						<p class="description"><?php esc_html_e( 'Distance from the bottom (a number means %, or use "px").', 'bw-dev' ); ?></p>
					</td>
				</tr>
				<tr>
					<th scope="row"><?php esc_html_e( 'Animation', 'bw-dev' ); ?></th>
					<td>
						<label>
							<input type="checkbox" name="<?php echo esc_attr( $pfx ); ?>[animate]" value="1" <?php checked( $settings['animate'], 1 ); ?>>
							<?php esc_html_e( 'Enable the smooth floating animation', 'bw-dev' ); ?>
						</label>
					</td>
				</tr>
			</tbody>
		</table>

		<h3><?php esc_html_e( 'Behavior', 'bw-dev' ); ?></h3>
		<table class="form-table" role="presentation">
			<tbody>
				<tr>
					<th scope="row"><label for="bw-dev-scroll-anchor"><?php esc_html_e( 'Anchor target', 'bw-dev' ); ?></label></th>
					<td><input type="text" id="bw-dev-scroll-anchor" name="<?php echo esc_attr( $pfx ); ?>[anchor_target]" value="<?php echo esc_attr( (string) $settings['anchor_target'] ); ?>" class="regular-text" placeholder="#start"></td>
				</tr>
				<tr>
					<th scope="row"><label for="bw-dev-scroll-trigger"><?php esc_html_e( 'Trigger class', 'bw-dev' ); ?></label></th>
					<td>
						<input type="text" id="bw-dev-scroll-trigger" name="<?php echo esc_attr( $pfx ); ?>[trigger_class]" value="<?php echo esc_attr( (string) $settings['trigger_class'] ); ?>" class="regular-text">
						<p class="description"><?php esc_html_e( 'Add this class to any Kadence Row to auto-inject the indicator.', 'bw-dev' ); ?></p>
					</td>
				</tr>
				<tr>
					<th scope="row"><?php esc_html_e( 'Auto-target', 'bw-dev' ); ?></th>
					<td>
						<label>
							<input type="checkbox" name="<?php echo esc_attr( $pfx ); ?>[auto_target]" value="1" <?php checked( $settings['auto_target'], 1 ); ?>>
							<?php esc_html_e( 'Scroll to the next section instead of the anchor target', 'bw-dev' ); ?>
						</label>
					</td>
				</tr>
			</tbody>
		</table>

		<h3><?php esc_html_e( 'Preview', 'bw-dev' ); ?></h3>
		<div style="padding:80px 40px; background:linear-gradient(135deg,#1a1a2e 0%,#16213e 100%); text-align:center; margin-bottom:20px; position:relative; min-height:200px; border-radius:8px;">
			<p style="color:rgba(255,255,255,0.4); margin:0 0 60px;"><?php esc_html_e( 'Hero Section Preview', 'bw-dev' ); ?></p>
			<div style="position:absolute; bottom:<?php echo esc_attr( $this->parse_offset( (string) $settings['bottom_offset'] ) ); ?>; left:50%; transform:translateX(-50%);">
				<?php echo $this->shortcode_output(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped at source. ?>
			</div>
		</div>

		<h3><?php esc_html_e( 'Usage', 'bw-dev' ); ?></h3>
		<p><strong><?php esc_html_e( 'Shortcode:', 'bw-dev' ); ?></strong> <code>[bw_dev_scroll_down]</code></p>
		<p>
			<strong><?php esc_html_e( 'CSS class:', 'bw-dev' ); ?></strong>
			<?php
			printf(
				/* translators: %s: the trigger CSS class */
				esc_html__( 'Add %s to any Kadence Row.', 'bw-dev' ),
				'<code>' . esc_html( (string) $settings['trigger_class'] ) . '</code>'
			);
			?>
		</p>

		<script>
		jQuery(function ($) {
			$('.bw-dev-scroll-icon-radio').on('change', function () {
				$('.bw-dev-scroll-icon-radio').closest('label').css('border-color', '#ddd');
				$(this).closest('label').css('border-color', '#2271b1');
			});
			if ($.fn.wpColorPicker) {
				$('.bw-dev-scroll-color-picker').wpColorPicker();
			}
		});
		</script>
		<?php
	}

	public function uninstall(): void {
		// No-op. Root option drop handles persisted state.
	}
}
