<?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 $filepath  保存先パス（wp-content/uploads/conf-manager/ 配下）
	 * @param string $title     PDF タイトル
	 * @param string $css_file  assets/css/pdf/ 配下の CSS ファイル名（任意）
	 * @return string 保存先のフルパス
	 * @throws \RuntimeException 生成に失敗した場合
	 */
	public function render_to_file( string $html, string $filepath, string $title = '', string $css_file = '' ): string {
		$upload_dir = wp_upload_dir();
		$base_dir   = $upload_dir['basedir'] . '/conf-manager';
		$full_path  = $base_dir . '/' . ltrim( $filepath, '/' );

		// ディレクトリ作成
		$dir = dirname( $full_path );
		if ( ! file_exists( $dir ) ) {
			wp_mkdir_p( $dir );
		}

		$mpdf = $this->create_mpdf();

		if ( '' !== $title ) {
			$mpdf->SetTitle( $title );
		}

		$this->apply_css( $mpdf, $css_file );
		$mpdf->WriteHTML( $html );
		$mpdf->Output( $full_path, \Mpdf\Output\Destination::FILE );

		return $full_path;
	}

	/**
	 * 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 );
	}

	/**
	 * PDF ファイルの URL を取得する
	 *
	 * @param string $filepath conf-manager/ 配下の相対パス
	 * @return string URL
	 */
	public static function get_pdf_url( string $filepath ): string {
		$upload_dir = wp_upload_dir();
		return $upload_dir['baseurl'] . '/conf-manager/' . ltrim( $filepath, '/' );
	}
}
