<?php
/**
 * Posts to PDF feature bootstrap.
 *
 * @package PDFDraft
 */

namespace PDFDraft\PostsToPdf;

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

use PDFDraft\PostsToPdf\Settings as PostsToPdfSettings;

/**
 * Bootstraps all Posts to PDF hooks, scripts, and REST routes.
 */
class PostsToPdf {

	/**
	 * @var PostsToPdfSettings
	 */
	private PostsToPdfSettings $settings;

	/**
	 * @var ButtonInjector
	 */
	private ButtonInjector $button_injector;

	/**
	 * @var PostMetaFields
	 */
	private PostMetaFields $meta_fields;

	/**
	 * @var RestController
	 */
	private RestController $rest_controller;

	/**
	 * Constructor.
	 *
	 * @param PostsToPdfSettings $settings         Settings service.
	 * @param ButtonInjector     $button_injector  Button injector.
	 * @param PostMetaFields     $meta_fields      Meta field registrar.
	 * @param RestController     $rest_controller  REST controller.
	 */
	public function __construct(
		PostsToPdfSettings $settings,
		ButtonInjector     $button_injector,
		PostMetaFields     $meta_fields,
		RestController     $rest_controller
	) {
		$this->settings        = $settings;
		$this->button_injector = $button_injector;
		$this->meta_fields     = $meta_fields;
		$this->rest_controller = $rest_controller;
	}

	/**
	 * Register all WordPress hooks.
	 *
	 * @return void
	 */
	public function init(): void {
		// Register post meta fields (REST-accessible)
		add_action( 'init', array( $this->meta_fields, 'register' ) );

		// REST routes
		add_action( 'rest_api_init', array( $this->rest_controller, 'register_routes' ) );

		// Frontend button injection
		$this->button_injector->init();

		// Frontend script enqueue
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );

		// Gutenberg sidebar panel
		add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_gutenberg_scripts' ) );

	}

	/**
	 * Add posts-to-pdf and pages-to-pdf to the list of contexts that allow
	 * creating a new design from scratch in the editor.
	 *
	 * @param array $data Localized editor data.
	 * @return array
	 */
	public function allow_create_for_posts_to_pdf( array $data ): array {
		if ( ! isset( $data['createFromScratchByFor'] ) || ! is_array( $data['createFromScratchByFor'] ) ) {
			$data['createFromScratchByFor'] = array();
		}

		// Map each for-value to a slug, then mark that slug active so the
		// canCreateFromScratch() check in the editor passes.
		$data['createFromScratchByFor']['posts-to-pdf'] = 'pdfdraft';
		$data['createFromScratchByFor']['pages-to-pdf'] = 'pdfdraft';

		if ( ! isset( $data['pdfdraftPluginsActive'] ) || ! is_array( $data['pdfdraftPluginsActive'] ) ) {
			$data['pdfdraftPluginsActive'] = array();
		}

		$data['pdfdraftPluginsActive']['pdfdraft'] = true;

		return $data;
	}

	// ── Frontend scripts ──────────────────────────────────────────────────────

	/**
	 * Enqueue the posts-to-pdf frontend bundle on singular post/page views.
	 * The script is already registered by ScriptStyle — we only enqueue it here
	 * when the current page actually needs it.
	 *
	 * @return void
	 */
	public function enqueue_frontend_scripts(): void {
		if ( ! is_singular( array( 'post', 'page' ) ) ) {
			return;
		}

		if ( ! $this->settings->is_enabled() ) {
			return;
		}

		if ( ! $this->should_show_button() ) {
			return;
		}

		// Script registered by ScriptStyle — just enqueue it here.
		if ( ! wp_script_is( 'pdfdraft-posts-to-pdf-frontend', 'registered' ) ) {
			return;
		}

		// The frontend bundle reuses some editor modules that reference __PDFDRAFT__.
		// Ensure a safe global exists on singular post/page views.
		wp_add_inline_script(
			'pdfdraft-posts-to-pdf-frontend',
			"window.__PDFDRAFT__ = window.__PDFDRAFT__ || { defaultFont: { family: 'Inter' } };",
			'before'
		);

		wp_enqueue_script( 'pdfdraft-posts-to-pdf-frontend' );

		$data = $this->build_frontend_data();
		if ( $data ) {
			// Use wp_add_inline_script + wp_json_encode instead of wp_localize_script to
			// preserve boolean/null types (wp_localize_script casts scalars to strings).
			wp_add_inline_script(
				'pdfdraft-posts-to-pdf-frontend',
				'window.__PDFDRAFT_POST_PDF__ = ' . wp_json_encode( $data ) . ';',
				'before'
			);
		}
	}

	/**
	 * Enqueue the Gutenberg sidebar panel on the block editor.
	 * The script is already registered by ScriptStyle.
	 *
	 * @return void
	 */
	public function enqueue_gutenberg_scripts(): void {
		global $post;

		if ( ! $post || ! in_array( $post->post_type, array( 'post', 'page' ), true ) ) {
			return;
		}

		if ( ! wp_script_is( 'pdfdraft-gutenberg-posts-to-pdf', 'registered' ) ) {
			return;
		}

		wp_enqueue_script( 'pdfdraft-gutenberg-posts-to-pdf' );
	}

	// ── Helper: auto-tag new designs created from settings ───────────────────

	// ── Private helpers ───────────────────────────────────────────────────────

	/**
	 * Determine whether the current post/page should show a download button,
	 * based on the per-post visibility override and the global post-type settings.
	 *
	 * @return bool
	 */
	private function should_show_button(): bool {
		$post_id   = get_the_ID();
		$post_type = get_post_type();
		$settings  = $this->settings->get_all();

		$visibility = get_post_meta( $post_id, '_pdfdraft_pdf_button_visibility', true ) ?: 'global';

		if ( 'hide' === $visibility ) {
			return false;
		}

		if ( 'show' === $visibility ) {
			return $this->resolve_design_id() > 0;
		}

		if ( 'post' === $post_type ) {
			return ! empty( $settings['posts']['enabled'] ) && $this->has_design_configured( $settings['posts'] );
		}

		if ( 'page' === $post_type ) {
			return ! empty( $settings['pages']['enabled'] ) && $this->has_design_configured( $settings['pages'] );
		}

		return false;
	}

	/**
	 * Check whether a post-type settings array has enough configuration to
	 * show the download button. In 'default' mode no project is required; in
	 * 'custom' mode a project_id must be set.
	 *
	 * @param array $pt_settings Post-type settings (posts or pages).
	 * @return bool
	 */
	private function has_design_configured( array $pt_settings ): bool {
		// The button should appear whenever the post type is enabled.
		// 'default' mode needs no project; 'custom' with no project selected
		// falls back to default-mode rendering on the JS side (templateData null).
		return true;
	}

	/**
	 * Resolve the effective design ID for the current post.
	 * Per-post override (template_id meta) takes precedence over global settings.
	 *
	 * @return int  0 when no design is configured.
	 */
	private function resolve_design_id(): int {
		$post_id   = get_the_ID();
		$post_type = get_post_type();
		$settings  = $this->settings->get_all();

		// Per-post override always wins.
		$override = (int) ( get_post_meta( $post_id, '_pdfdraft_pdf_template_id', true ) ?? 0 );
		if ( $override ) {
			return $override;
		}

		if ( 'post' === $post_type ) {
			if ( 'custom' !== ( $settings['posts']['pdf_style'] ?? 'default' ) ) {
				return 0;
			}
			return (int) ( $settings['posts']['project_id'] ?? 0 );
		}

		if ( 'page' === $post_type ) {
			if ( 'custom' !== ( $settings['pages']['pdf_style'] ?? 'default' ) ) {
				return 0;
			}
			return (int) ( $settings['pages']['project_id'] ?? 0 );
		}

		return 0;
	}

	/**
	 * Build the `window.__PDFDRAFT_POST_PDF__` data object.
	 *
	 * @return array
	 */
	private function build_frontend_data(): array {
		$post_id     = get_the_ID();
		$settings    = $this->settings->get_all();
		$template_id = $this->resolve_design_id();
		$template_data = null;

		if ( $template_id ) {
			$design_post = get_post( $template_id );
			if ( $design_post && 'pdfdraft-design' === $design_post->post_type ) {
				$decoded = json_decode( $design_post->post_content, true );
				if ( is_array( $decoded ) ) {
					$template_data = $decoded;
				}
			}
		}

		return array(
			'postId'          => $post_id,
			'templateData'    => $template_data,
			'filenamePattern' => $settings['filename_pattern'] ?? '{post_title}.pdf',
			'includeImages'   => isset( $settings['include_images'] ) ? (bool) $settings['include_images'] : true,
			'restUrl'         => rest_url(),
			'nonce'           => wp_create_nonce( 'wp_rest' ),
		);
	}
}
