<?php
declare(strict_types=1);
namespace ConfManager\Payment;

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


use ConfManager\Traits\Singleton;

/**
 * PDF レンダラー
 *
 * mPDF を使用して HTML テンプレートから PDF を生成する。
 * IPAex フォントを使用して日本語を正しく表示。
 *
 * @since 1.0.0
 */
class PdfRenderer {

	use Singleton;

	protected function init(): void {}

	/**
	 * HTML から PDF を生成してブラウザに出力する
	 *
	 * @param string $html     HTML コンテンツ
	 * @param string $filename ダウンロードファイル名
	 * @param string $css_file assets/css/pdf/ 配下の CSS ファイル名（任意）
	 */
	public function render_to_browser( string $html, string $filename, string $css_file = '' ): void {
		$mpdf = $this->create_mpdf();
		$this->apply_css( $mpdf, $css_file );
		$mpdf->WriteHTML( $html );
		$mpdf->Output( $filename, \Mpdf\Output\Destination::INLINE );
	}

	/**
	 * HTML から PDF バイナリを取得する
	 *
	 * @param string $html     HTML コンテンツ
	 * @param string $css_file assets/css/pdf/ 配下の CSS ファイル名（任意）
	 * @return string PDF バイナリ
	 */
	public function render_to_string( string $html, string $css_file = '' ): string {
		$mpdf = $this->create_mpdf();
		$this->apply_css( $mpdf, $css_file );
		$mpdf->WriteHTML( $html );
		return $mpdf->Output( '', \Mpdf\Output\Destination::STRING_RETURN );
	}

	/**
	 * assets/css/pdf/ 配下の CSS を mPDF に HEADER_CSS として注入する
	 */
	private function apply_css( \Mpdf\Mpdf $mpdf, string $css_file ): void {
		if ( '' === $css_file ) {
			return;
		}
		$css_path = CONF_MANAGER_PLUGIN_DIR . 'assets/css/pdf/' . $css_file;
		if ( ! file_exists( $css_path ) ) {
			return;
		}
		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Local plugin asset read; WP_Filesystem is overkill here.
		$css = file_get_contents( $css_path );
		if ( false !== $css && '' !== $css ) {
			$mpdf->WriteHTML( $css, \Mpdf\HTMLParserMode::HEADER_CSS );
		}
	}

	/**
	 * テンプレートファイルからHTMLを生成する
	 *
	 * @param string $template テンプレートファイル名（templates/ 配下）
	 * @param array  $data     テンプレート変数
	 * @return string HTML
	 */
	public function load_template( string $template, array $__vars = [] ): string {
		$template_path = CONF_MANAGER_PLUGIN_DIR . 'templates/' . $template;

		if ( ! file_exists( $template_path ) ) {
			throw new \RuntimeException( esc_html( sprintf( 'Template not found: %s', $template ) ) );
		}

		extract( $__vars, EXTR_SKIP );
		ob_start();
		include $template_path;
		return ob_get_clean();
	}

	/**
	 * mPDF インスタンスを作成する
	 */
	private function create_mpdf(): \Mpdf\Mpdf {
		$font_dir = \ConfManager\Fonts\FontManager::get_font_dir();

		// フォント未配置チェック
		$has_any_font = file_exists( $font_dir . '/ipaexg.ttf' )
			|| file_exists( $font_dir . '/ipaexm.ttf' )
			|| file_exists( $font_dir . '/NotoSansJP.ttf' );

		if ( ! $has_any_font ) {
			throw new \RuntimeException(
				esc_html__( 'Japanese fonts required for PDF generation are not installed. Please download them from the admin Dashboard.', 'conferencemanager' )
			);
		}

		$config = [
			'mode'            => 'utf-8',
			'format'          => 'A4',
			'margin_left'     => 15,
			'margin_right'    => 15,
			'margin_top'      => 15,
			'margin_bottom'   => 15,
			'default_font'    => 'ipag',
			'tempDir'         => sys_get_temp_dir() . '/mpdf',
		];

		// カスタムフォント設定
		$custom_fonts = [];
		$has_custom   = false;

		if ( file_exists( $font_dir . '/ipaexg.ttf' ) ) {
			$custom_fonts['ipag'] = [ 'R' => 'ipaexg.ttf' ];
			$has_custom = true;
		}
		if ( file_exists( $font_dir . '/ipaexm.ttf' ) ) {
			$custom_fonts['ipam'] = [ 'R' => 'ipaexm.ttf' ];
			$has_custom = true;
		}
		if ( file_exists( $font_dir . '/NotoSansJP.ttf' ) ) {
			$custom_fonts['notosansjp'] = [ 'R' => 'NotoSansJP.ttf' ];
			$has_custom = true;
		}

		if ( $has_custom ) {
			$config['fontDir']  = [ $font_dir ];
			$config['fontdata'] = $custom_fonts;

			// 利用可能なフォントで default_font を設定（優先順: IPAexゴシック → Noto Sans JP）
			if ( isset( $custom_fonts['ipag'] ) ) {
				$config['default_font'] = 'ipag';
			} elseif ( isset( $custom_fonts['notosansjp'] ) ) {
				$config['default_font'] = 'notosansjp';
			}
		}

		return new \Mpdf\Mpdf( $config );
	}

}
