<?php
/**
 * Code Snippet Revisions Display - diff rendering.
 *
 * @package CodeSnippet
 * @since 1.0.0
 */

namespace CodeSnippet;

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

/**
 * Class Wpps_Revisions_Display.
 */
class Wpps_Revisions_Display {

	/**
	 * Render revision header with avatar, author, date, restore button.
	 *
	 * @param object $revision       Revision row from DB.
	 * @param bool   $is_current     Whether this is the current/latest revision.
	 */
	public static function render_header( $revision, bool $is_current = false ): void {
		$datef   = _x( 'F j, Y @ H:i:s', 'revision date format', 'wppowersuite-lite' );
		$modified = strtotime( $revision->created );
		$updated  = sprintf(
			/* translators: %s: human time diff */
			__( 'Updated %s ago', 'wppowersuite-lite' ),
			human_time_diff( $modified )
		);
		if ( time() - $modified > 15 * DAY_IN_SECONDS ) {
			$updated = sprintf(
				/* translators: %s: date */
				__( 'Updated on %s', 'wppowersuite-lite' ),
				wp_date( $datef, $modified )
			);
		}
		$restore_url = $is_current ? '' : wp_nonce_url(
			add_query_arg(
				[ 'restore' => $revision->revision_id ],
				admin_url( 'admin.php?page=powersuite-code-snippet&view=revisions&revision=' . $revision->revision_id )
			),
			'wpps-restore-revision'
		);
		?>
		<div class="wpps-cs-revision-header">
			<?php echo get_avatar( $revision->author_id, 30 ); ?>
			<span class="wpps-cs-revision-author"><?php echo esc_html( get_the_author_meta( 'display_name', $revision->author_id ) ); ?></span>
			<span class="wpps-cs-revision-date"><?php echo esc_html( $updated ); ?></span>
			<?php if ( ! $is_current && $restore_url ) : ?>
				<div class="wpps-cs-revision-header-right">
					<a href="<?php echo esc_url( $restore_url ); ?>" class="wpps-cs-btn wpps-cs-btn-primary wpps-cs-btn-sm"><?php esc_html_e( 'Restore this revision', 'wppowersuite-lite' ); ?></a>
				</div>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * Render diff content between previous and revision data.
	 *
	 * @param array $previous_data Data before this revision.
	 * @param array $revision_data This revision's data.
	 */
	public static function render_compare_content( array $previous_data, array $revision_data ): void {
		$labels = \CodeSnippet\Module::getLocations();
		$code_types = [
			'html' => __( 'HTML Snippet', 'wppowersuite-lite' ),
			'css'  => __( 'CSS Snippet', 'wppowersuite-lite' ),
			'js'   => __( 'JavaScript Snippet', 'wppowersuite-lite' ),
			'php'  => __( 'PHP Snippet', 'wppowersuite-lite' ),
		];
		?>
		<div class="wpps-cs-revision-content">
			<div class="wpps-cs-revision-diff-section">
				<h4><?php esc_html_e( 'Title', 'wppowersuite-lite' ); ?></h4>
				<?php echo wp_kses_post( self::text_diff( $previous_data['title'] ?? '', $revision_data['title'] ?? '', [ 'show_no_diff' => true ] ) ); ?>
			</div>
			<?php if ( ( $previous_data['code_type'] ?? '' ) !== ( $revision_data['code_type'] ?? '' ) ) : ?>
				<div class="wpps-cs-revision-diff-section">
					<h4><?php esc_html_e( 'Code Type', 'wppowersuite-lite' ); ?></h4>
					<?php
					$prev_type = $code_types[ $previous_data['code_type'] ?? '' ] ?? ( $previous_data['code_type'] ?? '' );
					$curr_type = $code_types[ $revision_data['code_type'] ?? '' ] ?? ( $revision_data['code_type'] ?? '' );
					echo wp_kses_post( self::text_diff( $prev_type, $curr_type ) );
					?>
				</div>
			<?php endif; ?>
			<?php if ( ( $previous_data['code'] ?? '' ) !== ( $revision_data['code'] ?? '' ) ) : ?>
				<div class="wpps-cs-revision-diff-section wpps-cs-revision-diff-code">
					<h4><?php esc_html_e( 'Code', 'wppowersuite-lite' ); ?></h4>
					<?php echo wp_kses_post( self::text_diff( $previous_data['code'] ?? '', $revision_data['code'] ?? '' ) ); ?>
				</div>
			<?php endif; ?>
			<?php if ( ( $previous_data['location_label'] ?? $previous_data['location'] ?? '' ) !== ( $revision_data['location_label'] ?? $revision_data['location'] ?? '' ) ) : ?>
				<div class="wpps-cs-revision-diff-section">
					<h4><?php esc_html_e( 'Location', 'wppowersuite-lite' ); ?></h4>
					<?php
					$prev_loc = $previous_data['location_label'] ?? $labels[ $previous_data['location'] ?? '' ] ?? ( $previous_data['location'] ?? '' );
					$curr_loc = $revision_data['location_label'] ?? $labels[ $revision_data['location'] ?? '' ] ?? ( $revision_data['location'] ?? '' );
					echo wp_kses_post( self::text_diff( $prev_loc, $curr_loc ) );
					?>
				</div>
			<?php endif; ?>
			<?php if ( ( $previous_data['auto_insert'] ?? '' ) !== ( $revision_data['auto_insert'] ?? '' ) ) : ?>
				<div class="wpps-cs-revision-diff-section">
					<h4><?php esc_html_e( 'Auto Insert', 'wppowersuite-lite' ); ?></h4>
					<?php
					$prev_auto = ( $previous_data['auto_insert'] ?? false ) ? __( 'Enabled', 'wppowersuite-lite' ) : __( 'Disabled', 'wppowersuite-lite' );
					$curr_auto = ( $revision_data['auto_insert'] ?? false ) ? __( 'Enabled', 'wppowersuite-lite' ) : __( 'Disabled', 'wppowersuite-lite' );
					echo wp_kses_post( self::text_diff( $prev_auto, $curr_auto ) );
					?>
				</div>
			<?php endif; ?>
			<?php if ( ( $previous_data['priority'] ?? '' ) !== ( $revision_data['priority'] ?? '' ) ) : ?>
				<div class="wpps-cs-revision-diff-section">
					<h4><?php esc_html_e( 'Priority', 'wppowersuite-lite' ); ?></h4>
					<?php echo wp_kses_post( self::text_diff( (string) ( $previous_data['priority'] ?? '' ), (string) ( $revision_data['priority'] ?? '' ) ) ); ?>
				</div>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * Render compare content for "compare any two revisions" (left = older, right = newer).
	 *
	 * @param array $left_data  Older revision data.
	 * @param array $right_data Newer revision data.
	 * @return string HTML.
	 */
	public static function render_compare_any_two( array $left_data, array $right_data ): string {
		ob_start();
		self::render_compare_content( $left_data, $right_data );
		return ob_get_clean();
	}

	/**
	 * Text diff (shows content even when unchanged).
	 *
	 * @param string $left  Left string.
	 * @param string $right Right string.
	 * @param array  $args  Extra args (show_no_diff, title_left, title_right).
	 * @return string HTML.
	 */
	public static function text_diff( string $left, string $right, array $args = [] ): string {
		$args = wp_parse_args( $args, [
			'title_left'      => __( 'Removed', 'wppowersuite-lite' ),
			'title_right'     => __( 'Added', 'wppowersuite-lite' ),
			'show_split_view' => true,
			'show_no_diff'    => false,
		] );
		if ( ! class_exists( 'WP_Text_Diff_Renderer_Table', false ) ) {
			require ABSPATH . WPINC . '/wp-diff.php';
		}
		$left         = normalize_whitespace( $left );
		$right        = normalize_whitespace( $right );
		$left_lines   = explode( "\n", $left );
		$right_lines  = explode( "\n", $right );
		$text_diff    = new \Text_Diff( $left_lines, $right_lines );
		$renderer     = new \WP_Text_Diff_Renderer_Table();
		$diff         = $renderer->render( $text_diff );
		if ( ! $diff ) {
			if ( ! $args['show_no_diff'] ) {
				return '';
			}
			$diff = '';
			$max  = max( count( $left_lines ), count( $right_lines ) );
			for ( $i = 0; $i < $max; $i++ ) {
				$l = isset( $left_lines[ $i ] ) ? esc_html( $left_lines[ $i ] ) : '';
				$r = isset( $right_lines[ $i ] ) ? esc_html( $right_lines[ $i ] ) : '';
				$diff .= '<tr><td class="diff-context">' . $l . '</td><td class="diff-context">' . $r . '</td></tr>';
			}
		}
		$split_class = $args['show_split_view'] ? ' is-split-view' : '';
		$out = "<table class='diff wpps-cs-diff-table$split_class'>\n<tbody>\n$diff\n</tbody>\n</table>";
		return $out;
	}
}
