<?php
/**
 * Public Handler
 *
 * @package PCChangelogManager
 */

// Prevent direct access to the file.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Handles all public-facing functionality for the changelog manager.
 */
class PC_CLM_Public {

	/**
	 * Instance of the post type class.
	 *
	 * @var PC_CLM_Post_Type
	 */
	private $post_type;

	/**
	 * Constructor.
	 *
	 * @param PC_CLM_Post_Type $post_type Post type instance.
	 */
	public function __construct( $post_type ) {
		$this->post_type = $post_type;
		$this->init_hooks();
	}

	/**
	 * Initialize public hooks.
	 */
	private function init_hooks() {
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
		add_filter( 'template_include', array( $this, 'template_loader' ) );
		add_shortcode( 'changelog', array( $this, 'shortcode_changelog' ) );
		add_action( 'widgets_init', array( $this, 'register_widgets' ) );
		add_action( 'wp_ajax_pc_clm_upvote', array( $this, 'handle_upvote' ) );
		add_action( 'wp_ajax_nopriv_pc_clm_upvote', array( $this, 'handle_upvote' ) );
	}

	/**
	 * Enqueue public styles.
	 */
	public function enqueue_styles() {
		// Check if we're on the changelog page or if shortcode is used.
		if ( ! $this->is_changelog_page() && ! $this->is_changelog_single() && ! $this->has_shortcode() ) {
			return;
		}

		$min_suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';

		if ( file_exists( PC_CLM_PLUGIN_DIR . 'public/css/public-style.css' ) ) {
			// Enqueue main stylesheet.
			if ( ! wp_style_is( 'pc-clm-public-style', 'enqueued' ) ) {
				wp_enqueue_style(
					'pc-clm-public-style',
					PC_CLM_PLUGIN_URL . 'public/css/public-style.css',
					array(),
					PC_CLM_VERSION
				);
			}
		}
	}

	/**
	 * Check if we're on the changelog page.
	 *
	 * @return bool
	 */
	private function is_changelog_page() {
		return is_post_type_archive( $this->post_type->get_post_type_slug() );
	}

	private function is_changelog_single() {
		return is_singular( $this->post_type->get_post_type_slug() );
	}

	/**
	 * Check if the page has the changelog shortcode.
	 *
	 * @return bool
	 */
	private function has_shortcode() {
		if ( ! is_singular() ) {
			return false;
		}

		$post = get_post();
		if ( ! $post ) {
			return false;
		}

		return has_shortcode( $post->post_content, 'changelog' );
	}

	public function template_loader( $template ) {
		if ( is_singular( $this->post_type->get_post_type_slug() ) ) {
			$custom_template = PC_CLM_PLUGIN_DIR . 'public/templates/single-pc_changelog.php';
			if ( file_exists( $custom_template ) ) {
				return $custom_template;
			}
		}

		return $template;
	}

	/**
	 * Changelog shortcode.
	 *
	 * @param array $atts Shortcode attributes.
	 * @return string
	 */
	public function shortcode_changelog( $atts ) {
		$atts = shortcode_atts(
			array(
				'limit'      => 10,
				'category'   => '',
				'show_date'  => 'yes',
				'show_title' => 'yes',
				'order'      => 'DESC',
			),
			$atts,
			'changelog'
		);

		// Enqueue styles for the shortcode output.
		if ( file_exists( PC_CLM_PLUGIN_DIR . 'public/css/public-style.css' ) ) {
			wp_enqueue_style( 'pc-clm-public-style', PC_CLM_PLUGIN_URL . 'public/css/public-style.css', array(), PC_CLM_VERSION );
		}

		// Build query args.
		$query_args = array(
			'post_type'      => $this->post_type->get_post_type_slug(),
			'post_status'    => 'publish',
			'posts_per_page' => intval( $atts['limit'] ),
			'orderby'        => 'date',
			'order'          => 'DESC' === $atts['order'] ? 'DESC' : 'ASC',
		);

		// Filter by category if specified.
		if ( ! empty( $atts['category'] ) ) {
			$query_args['meta_query'] = array(
				array(
					'key'   => '_pc_clm_category',
					'value' => sanitize_text_field( $atts['category'] ),
				),
			);
		}

		$query = new WP_Query( $query_args );

		ob_start();

		if ( $query->have_posts() ) {
			?>
			<div class="pc-clm-shortcode-wrapper">
				<?php if ( 'yes' === $atts['show_title'] ) : ?>
					<h2 class="pc-clm-shortcode-title"><?php esc_html_e( 'Changelog', 'pc-changelog-manager-abc123' ); ?></h2>
				<?php endif; ?>

				<div class="pc-clm-entries-list">
					<?php
					while ( $query->have_posts() ) :
						$query->the_post();
						$this->render_entry( get_the_ID(), $atts );
					endwhile;
					?>
				</div>
			</div>
			<?php
			wp_reset_postdata();
		} else {
			?>
			<div class="pc-clm-no-entries">
				<p><?php esc_html_e( 'No changelog entries found.', 'pc-changelog-manager-abc123' ); ?></p>
			</div>
			<?php
		}

		return ob_get_clean();
	}

	/**
	 * Render a single changelog entry.
	 *
	 * @param int   $post_id Post ID.
	 * @param array $atts    Shortcode attributes.
	 */
	private function render_entry( $post_id, $atts ) {
		$version   = $this->post_type->get_meta( $post_id, 'version_number' );
		$release_date = $this->post_type->get_meta( $post_id, 'release_date' );
		$category  = $this->post_type->get_meta( $post_id, 'category' );
		$categories = $this->post_type->get_categories();
		$category_name = isset( $categories[ $category ] ) ? $categories[ $category ] : $category;
		$upvote_count = $this->get_upvote_count( $post_id );
		$has_voted = $this->has_user_voted( $post_id );

		$entry_classes = array( 'pc-clm-entry' );
		if ( $category ) {
			$entry_classes[] = 'pc-clm-category-' . $category;
		}

		?>
		<article class="<?php echo esc_attr( implode( ' ', $entry_classes ) ); ?>" id="pc-clm-entry-<?php echo esc_attr( $post_id ); ?>">
			<div class="pc-clm-entry-inner">
				<div class="pc-clm-entry-header">
					<div class="pc-clm-entry-meta">
						<?php if ( $version ) : ?>
							<span class="pc-clm-version-badge"><?php echo esc_html( $version ); ?></span>
						<?php endif; ?>

						<?php if ( 'yes' === $atts['show_date'] && $release_date ) : ?>
							<span class="pc-clm-release-date"><?php echo esc_html( date_i18n( get_option( 'date_format' ), strtotime( $release_date ) ) ); ?></span>
						<?php endif; ?>

						<?php if ( $category ) : ?>
							<span class="pc-clm-category-badge pc-clm-category-<?php echo esc_attr( $category ); ?>"><?php echo esc_html( $category_name ); ?></span>
						<?php endif; ?>
					</div>

					<div class="pc-clm-upvote-section">
						<button class="pc-clm-upvote-btn <?php echo $has_voted ? 'voted' : ''; ?>" 
						        data-post-id="<?php echo esc_attr( $post_id ); ?>"
						        <?php echo $has_voted ? 'disabled' : ''; ?>>
							<span class="pc-clm-upvote-icon">
								<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
									<path d="M12 2l2.4 7.4h7.6l-6 4.6 2.3 7.4-6.3-4.6-6.3 4.6 2.3-7.4-6-4.6h7.6z"/>
								</svg>
							</span>
							<span class="pc-clm-upvote-count"><?php echo esc_html( $upvote_count ); ?></span>
						</button>
						<span class="pc-clm-upvote-label"><?php echo esc_html( _n( 'upvote', 'upvotes', $upvote_count, 'pc-changelog-manager-abc123' ) ); ?></span>
					</div>
				</div>

				<h3 class="pc-clm-entry-title">
					<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
				</h3>

				<div class="pc-clm-entry-content">
					<?php the_excerpt(); ?>
				</div>
			</div>
		</article>
		<?php
	}

	/**
	 * Enqueue public scripts.
	 */
	public function enqueue_scripts() {
		// Check if we're on the changelog page or if shortcode is used.
		if ( ! $this->is_changelog_page() && ! $this->is_changelog_single() && ! $this->has_shortcode() ) {
			return;
		}

		$min_suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';

		if ( file_exists( PC_CLM_PLUGIN_DIR . 'public/js/public-script.js' ) ) {
			wp_enqueue_script(
				'pc-clm-public-script',
				PC_CLM_PLUGIN_URL . 'public/js/public-script.js',
				array( 'jquery' ),
				PC_CLM_VERSION,
				true
			);

			wp_localize_script(
				'pc-clm-public-script',
				'pc_clm_ajax',
				array(
					'ajax_url' => admin_url( 'admin-ajax.php' ),
					'nonce'    => wp_create_nonce( 'pc_clm_upvote_nonce' ),
				)
			);
		}
	}



	/**
	 * Handle upvote AJAX request.
	 */
	public function handle_upvote() {
		check_ajax_referer( 'pc_clm_upvote_nonce', 'nonce' );

		if ( ! isset( $_POST['post_id'] ) ) {
			wp_die( 'Invalid request' );
		}

		$post_id = intval( $_POST['post_id'] );
		$ip_address = $_SERVER['REMOTE_ADDR'];
		$user_id = get_current_user_id();

		// Check if user has already voted (by IP or user ID if logged in)
		$voted_key = $user_id ? "pc_clm_voted_user_{$user_id}" : "pc_clm_voted_ip_{$ip_address}";
		$voted_posts = get_transient( $voted_key );
		
		if ( ! $voted_posts ) {
			$voted_posts = array();
		}

		if ( in_array( $post_id, $voted_posts ) ) {
			wp_send_json_error( array( 'message' => __( 'You have already voted for this entry.', 'pc-changelog-manager-abc123' ) ) );
			return;
		}

		// Get current vote count
		$vote_count = get_post_meta( $post_id, '_pc_clm_upvotes', true ) ?: 0;
		$new_vote_count = intval( $vote_count ) + 1;

		// Update vote count
		update_post_meta( $post_id, '_pc_clm_upvotes', $new_vote_count );

		// Mark as voted (expires after 30 days)
		$voted_posts[] = $post_id;
		set_transient( $voted_key, $voted_posts, 30 * DAY_IN_SECONDS );

		wp_send_json_success( array(
			'vote_count' => $new_vote_count,
			'message'    => __( 'Thank you for voting!', 'pc-changelog-manager-abc123' ),
		) );
	}

	/**
	 * Get upvote count for a post.
	 *
	 * @param int $post_id Post ID.
	 * @return int
	 */
	public function get_upvote_count( $post_id ) {
		$vote_count = get_post_meta( $post_id, '_pc_clm_upvotes', true );
		return intval( $vote_count );
	}

	/**
	 * Check if current user has voted for a post.
	 *
	 * @param int $post_id Post ID.
	 * @return bool
	 */
	public function has_user_voted( $post_id ) {
		$ip_address = $_SERVER['REMOTE_ADDR'];
		$user_id = get_current_user_id();

		$voted_key = $user_id ? "pc_clm_voted_user_{$user_id}" : "pc_clm_voted_ip_{$ip_address}";
		$voted_posts = get_transient( $voted_key );
		
		if ( ! $voted_posts ) {
			return false;
		}

		return in_array( $post_id, $voted_posts );
	}

	/**
	 * Register widgets.
	 */
	public function register_widgets() {
		require_once PC_CLM_PLUGIN_DIR . 'public/widgets/class-changelog-widget.php';
		register_widget( 'PC_CLM_Widget' );
	}
}

/**
 * Template function to display changelog entries.
 *
 * @param array $args Query arguments.
 */
function pc_clm_display_changelog( $args = array() ) {
	$post_type = new PC_CLM_Post_Type();
	$query     = $post_type->get_entries( $args );

	if ( $query->have_posts() ) {
		?>
		<div class="pc-clm-entries-list">
			<?php
			while ( $query->have_posts() ) :
				$query->the_post();
				$post_id      = get_the_ID();
				$version      = $post_type->get_meta( $post_id, 'version_number' );
				$release_date = $post_type->get_meta( $post_id, 'release_date' );
				$category     = $post_type->get_meta( $post_id, 'category' );
				$categories   = $post_type->get_categories();
				$category_name = isset( $categories[ $category ] ) ? $categories[ $category ] : $category;

				$entry_classes = array( 'pc-clm-entry' );
				if ( $category ) {
					$entry_classes[] = 'pc-clm-category-' . $category;
				}
				?>
				<article id="post-<?php the_ID(); ?>" <?php post_class( $entry_classes ); ?>>
					<div class="pc-clm-entry-inner">
						<div class="pc-clm-entry-meta">
							<?php if ( $version ) : ?>
								<span class="pc-clm-version-badge"><?php echo esc_html( $version ); ?></span>
							<?php endif; ?>

							<?php if ( $release_date ) : ?>
								<span class="pc-clm-release-date"><?php echo esc_html( date_i18n( get_option( 'date_format' ), strtotime( $release_date ) ) ); ?></span>
							<?php endif; ?>

							<?php if ( $category ) : ?>
								<span class="pc-clm-category-badge pc-clm-category-<?php echo esc_attr( $category ); ?>"><?php echo esc_html( $category_name ); ?></span>
							<?php endif; ?>
						</div>

						<h3 class="pc-clm-entry-title">
							<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
						</h3>

						<div class="pc-clm-entry-content">
							<?php the_excerpt(); ?>
						</div>
					</div>
				</article>
				<?php
			endwhile;
			?>
		</div>
		<?php
	} else {
		?>
		<div class="pc-clm-no-entries">
			<p><?php esc_html_e( 'No changelog entries found.', 'pc-changelog-manager-abc123' ); ?></p>
		</div>
		<?php
	}

	wp_reset_postdata();
}
