<?php
/**
 * PufferGo Site Profile (Site Info) – 站点信息 / 商业资料
 *
 * 职责：
 * 1. 存储/读取站点商业资料（WordPress Option puffergo_site_profile）
 * 2. 提供 REST API 供前端 GET / PUT / POST（与 Design System 等模块一致）
 * 3. 注册后台「站点信息」子菜单并加载 React 应用
 * 4. 与 AI 建站 Step1 共用此数据（Step1 预填与回写）
 *
 * Option 结构（puffergo_site_profile）：
 * audience, identity, contact, business, advantage, assets（logo_attachment_id + logo_url 由保存逻辑同步）, seo
 * 详见 default_structure()。
 *
 * @package PufferGo
 */

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

/**
 * Class PufferGo_Site_Profile
 */
class PufferGo_Site_Profile {

	const OPTION_KEY = 'puffergo_site_profile';

	/**
	 * Default profile structure (all keys, empty values).
	 *
	 * @return array
	 */
	/**
	 * 与前端 siteProfileSchema.js DEFAULT_PROFILE 严格一致（Step1 / 站点信息唯一数据源）。
	 */
	public static function default_structure() {
		return array(
			'audience'  => array(
				'role'       => '',
				'priorities' => '',
				'use_cases'  => '',
				'regions'    => '',
			),
			'identity'  => array(
				'brand_name' => '',
				'slogan'     => '',
				'founded'    => '',
				'story'      => '',
			),
			'contact'   => array(
				'email'    => '',
				'phone'    => '',
				'address'  => '',
				'channels' => array(),
			),
			'business'  => array(
				'industry' => '',
				'products' => array(),
			),
			'advantage'  => array(
				'certs'       => '',
				'pillars'     => array(),
				'pain_points' => '',
				'tone'        => 'Professional',
			),
			'assets'    => array(
				'logo_attachment_id' => 0,
				'logo_url'           => '',
			),
			'seo'       => array(
				'keywords' => array(),
			),
			'special_instructions' => '',
		);
	}

	public function __construct() {
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
		add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
	}

	/**
	 * Render admin page (React root). Menu registered in PufferGo_Admin_Menu.
	 */
	public static function render_page() {
		?>
		<div class="wrap">
			<div id="puffergo-site-profile-root"></div>
		</div>
		<?php
	}

	/**
	 * Enqueue script and style only on site profile page.
	 *
	 * @param string $hook Current admin page hook.
	 */
	public function enqueue_scripts( $hook ) {
		if ( strpos( $hook, 'puffergo-site-profile' ) === false ) {
			return;
		}

		$plugin_dir  = plugin_dir_path( dirname( __FILE__ ) );
		$plugin_url  = plugin_dir_url( dirname( __FILE__ ) );
		$asset_file  = $plugin_dir . 'build/blocks/site-profile-app/index.asset.php';
		$script_path = 'build/blocks/site-profile-app/index.js';
		$style_path  = 'build/blocks/site-profile-app/style-index.css';

		if ( file_exists( $asset_file ) ) {
			$asset   = include $asset_file;
			$deps    = $asset['dependencies'];
			$version = $asset['version'];
		} else {
			$deps    = array( 'wp-element', 'wp-components', 'wp-api-fetch', 'wp-i18n' );
			$version = (string) time();
		}

		wp_enqueue_script(
			'puffergo-site-profile',
			$plugin_url . $script_path,
			$deps,
			$version,
			true
		);

		$global_tailwind = $plugin_dir . 'build/blocks/ai-admin-app/index.css';
		if ( file_exists( $global_tailwind ) ) {
			wp_enqueue_style(
				'puffergo-admin-tailwind',
				$plugin_url . 'build/blocks/ai-admin-app/index.css',
				array(),
				(string) filemtime( $global_tailwind )
			);
		}

		$index_css = $plugin_dir . 'build/blocks/site-profile-app/index.css';
		if ( file_exists( $index_css ) ) {
			wp_enqueue_style(
				'puffergo-site-profile-app',
				$plugin_url . 'build/blocks/site-profile-app/index.css',
				array(),
				(string) filemtime( $index_css )
			);
		}

		if ( file_exists( $plugin_dir . $style_path ) ) {
			wp_enqueue_style(
				'puffergo-site-profile-styles',
				$plugin_url . $style_path,
				array( 'puffergo-site-profile-app' ),
				$version
			);
		}

		wp_localize_script(
			'puffergo-site-profile',
			'puffergoSiteProfile',
			array(
				'restUrl'           => rest_url(),
				'nonce'             => wp_create_nonce( 'wp_rest' ),
				'aiSiteBuilderUrl'  => admin_url( 'admin.php?page=puffergo-ai-site-builder' ),
			)
		);

		PufferGo_Workflow_Jobs_REST::add_poll_config_inline_script( 'puffergo-site-profile' );

		wp_enqueue_style( 'wp-components' );
		wp_enqueue_media();
	}

	/**
	 * 注册 REST 路由（风格与 class-design-system 一致：GET 读，PUT/POST 写）
	 */
	public function register_rest_routes() {
		register_rest_route(
			'puffergo/v1',
			'/site-profile',
			array(
				array(
					'methods'             => 'GET',
					'callback'            => array( $this, 'rest_get' ),
					'permission_callback' => function () {
						return current_user_can( 'manage_options' );
					},
				),
				array(
					'methods'             => array( 'PUT', 'POST' ),
					'callback'            => array( $this, 'rest_save' ),
					'permission_callback' => function () {
						return current_user_can( 'manage_options' );
					},
					'args'                => array(
						'profile' => array(
							'type'        => 'object',
							'required'    => false,
							'description' => __( 'Full site profile object.', 'puffergo' ),
						),
					),
				),
			)
		);
	}

	/**
	 * GET /puffergo/v1/site-profile
	 *
	 * 与 default_structure() 做深度合并；assets 中 logo 仅按 logo_attachment_id 派生 URL（断崖）。
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response
	 */
	public function rest_get( $request ) {
		$stored = get_option( self::OPTION_KEY, array() );
		if ( ! is_array( $stored ) ) {
			$stored = array();
		}
		$merged = array_replace_recursive( self::default_structure(), $stored );
		if ( isset( $merged['assets'] ) && is_array( $merged['assets'] ) ) {
			$merged['assets'] = self::resolve_logo_assets( $merged['assets'] );
		}
		return new WP_REST_Response( array( 'profile' => $merged ), 200 );
	}

	/**
	 * PUT / POST /puffergo/v1/site-profile
	 *
	 * 接受完整 profile 对象，经 sanitize 后覆盖保存。
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response
	 */
	public function rest_save( $request ) {
		$params    = $request->get_json_params();
		$raw       = isset( $params['profile'] ) && is_array( $params['profile'] ) ? $params['profile'] : array();
		$sanitized = $this->sanitize_profile( $raw );
		$updated   = array_merge( $sanitized, array( 'updated_at' => current_time( 'c' ) ) );
		update_option( self::OPTION_KEY, $updated, false );
		return new WP_REST_Response( array( 'success' => true, 'profile' => $updated ), 200 );
	}

	/**
	 * Sanitize full profile for save.
	 *
	 * @param array $raw Raw payload.
	 * @return array
	 */
	private function sanitize_profile( $raw ) {
		$out = array();

		$out['audience'] = array(
			'role'       => isset( $raw['audience']['role'] ) ? sanitize_text_field( wp_unslash( $raw['audience']['role'] ) ) : '',
			'priorities' => isset( $raw['audience']['priorities'] ) ? sanitize_text_field( wp_unslash( $raw['audience']['priorities'] ) ) : '',
			'use_cases'  => isset( $raw['audience']['use_cases'] ) ? sanitize_textarea_field( wp_unslash( $raw['audience']['use_cases'] ) ) : '',
			'regions'    => isset( $raw['audience']['regions'] ) ? sanitize_text_field( wp_unslash( $raw['audience']['regions'] ) ) : '',
		);

		$out['identity'] = array(
			'brand_name' => isset( $raw['identity']['brand_name'] ) ? sanitize_text_field( wp_unslash( $raw['identity']['brand_name'] ) ) : '',
			'slogan'     => isset( $raw['identity']['slogan'] ) ? sanitize_text_field( wp_unslash( $raw['identity']['slogan'] ) ) : '',
			'founded'    => isset( $raw['identity']['founded'] ) ? sanitize_text_field( wp_unslash( $raw['identity']['founded'] ) ) : '',
			'story'      => isset( $raw['identity']['story'] ) ? sanitize_textarea_field( wp_unslash( $raw['identity']['story'] ) ) : '',
		);

		$out['contact'] = array(
			'email'    => isset( $raw['contact']['email'] ) ? sanitize_email( $raw['contact']['email'] ) : '',
			// Normalize phone early so templates can build `tel:` reliably without extra regex cleanup.
			'phone'    => isset( $raw['contact']['phone'] ) ? preg_replace( '/[^0-9+]/', '', sanitize_text_field( wp_unslash( $raw['contact']['phone'] ) ) ) : '',
			'address'  => isset( $raw['contact']['address'] ) ? sanitize_textarea_field( wp_unslash( $raw['contact']['address'] ) ) : '',
			'channels' => array(),
		);
		if ( ! empty( $raw['contact']['channels'] ) && is_array( $raw['contact']['channels'] ) ) {
			foreach ( $raw['contact']['channels'] as $ch ) {
				$type  = isset( $ch['type'] ) ? sanitize_text_field( wp_unslash( $ch['type'] ) ) : '';
				$value = isset( $ch['value'] ) ? sanitize_text_field( wp_unslash( $ch['value'] ) ) : '';
				$out['contact']['channels'][] = array( 'type' => $type, 'value' => $value );
			}
		}

		$out['business'] = array(
			'industry' => isset( $raw['business']['industry'] ) ? sanitize_text_field( wp_unslash( $raw['business']['industry'] ) ) : '',
			'products' => array(),
		);
		if ( ! empty( $raw['business']['products'] ) && is_array( $raw['business']['products'] ) ) {
			foreach ( array_slice( $raw['business']['products'], 0, 3 ) as $p ) {
				$out['business']['products'][] = array(
					'name' => isset( $p['name'] ) ? sanitize_text_field( wp_unslash( $p['name'] ) ) : ( is_string( $p ) ? sanitize_text_field( wp_unslash( $p ) ) : '' ),
				);
			}
		}

		$pillars = array();
		if ( ! empty( $raw['advantage']['pillars'] ) && is_array( $raw['advantage']['pillars'] ) ) {
			foreach ( $raw['advantage']['pillars'] as $v ) {
				$pillars[] = is_string( $v ) ? sanitize_text_field( wp_unslash( $v ) ) : '';
			}
		}
		$out['advantage'] = array(
			'certs'       => isset( $raw['advantage']['certs'] ) ? sanitize_text_field( wp_unslash( $raw['advantage']['certs'] ) ) : '',
			'pillars'     => $pillars,
			'pain_points' => isset( $raw['advantage']['pain_points'] ) ? sanitize_textarea_field( wp_unslash( $raw['advantage']['pain_points'] ) ) : '',
			'tone'        => isset( $raw['advantage']['tone'] ) ? sanitize_text_field( wp_unslash( $raw['advantage']['tone'] ) ) : 'Professional',
		);
		$allowed_tone = array( 'Professional', 'Innovative', 'Caring' );
		if ( ! in_array( $out['advantage']['tone'], $allowed_tone, true ) ) {
			$out['advantage']['tone'] = 'Professional';
		}

		$out['assets'] = self::sanitize_assets_for_save( isset( $raw['assets'] ) && is_array( $raw['assets'] ) ? $raw['assets'] : array() );

		$keywords_arr = array();
		if ( ! empty( $raw['seo']['keywords'] ) && is_array( $raw['seo']['keywords'] ) ) {
			foreach ( array_slice( $raw['seo']['keywords'], 0, 30 ) as $k ) {
				$keywords_arr[] = is_string( $k ) ? sanitize_text_field( wp_unslash( $k ) ) : '';
			}
			$keywords_arr = array_values( array_filter( $keywords_arr ) );
		} elseif ( isset( $raw['seo']['keywords'] ) && is_string( $raw['seo']['keywords'] ) ) {
			$keywords_arr = array_values( array_filter( array_map( 'trim', preg_split( '/[\n,]+/', $raw['seo']['keywords'] ) ) ) );
			$keywords_arr = array_slice( array_map( 'sanitize_text_field', $keywords_arr ), 0, 30 );
		}
		$out['seo'] = array( 'keywords' => $keywords_arr );

		$out['special_instructions'] = isset( $raw['special_instructions'] ) && is_string( $raw['special_instructions'] )
			? sanitize_textarea_field( wp_unslash( $raw['special_instructions'] ) ) : '';

		return $out;
	}

	/**
	 * 从原始 assets 数组安全解析 logo：仅信任附件 ID，URL 实时由 WP 派生。
	 * 适用于任意读取场景（REST 响应、前台渲染、SEO 输出）。
	 *
	 * @param array $assets Raw assets block（来自 puffergo_site_profile option 或 REST 请求体）。
	 * @return array{logo_attachment_id:int,logo_url:string}
	 */
	public static function resolve_logo_assets( array $assets ) {
		$id = isset( $assets['logo_attachment_id'] ) ? absint( $assets['logo_attachment_id'] ) : 0;
		if ( $id > 0 && wp_attachment_is_image( $id ) ) {
			$url = wp_get_attachment_image_url( $id, 'full' );
			return array(
				'logo_attachment_id' => $id,
				'logo_url'           => $url ? esc_url_raw( $url ) : '',
			);
		}
		return array(
			'logo_attachment_id' => 0,
			'logo_url'           => '',
		);
	}

	/**
	 * 保存时根据附件 ID 同步 logo_url；忽略请求里的 logo_url。
	 *
	 * @param array $raw_assets Raw assets from client.
	 * @return array{logo_attachment_id:int,logo_url:string}
	 */
	public static function sanitize_assets_for_save( array $raw_assets ) {
		$id = isset( $raw_assets['logo_attachment_id'] ) ? absint( $raw_assets['logo_attachment_id'] ) : 0;
		if ( $id <= 0 ) {
			return array(
				'logo_attachment_id' => 0,
				'logo_url'           => '',
			);
		}
		$post = get_post( $id );
		if ( ! $post || 'attachment' !== $post->post_type || ! wp_attachment_is_image( $id ) || ! current_user_can( 'edit_post', $id ) ) {
			return array(
				'logo_attachment_id' => 0,
				'logo_url'           => '',
			);
		}
		$url = wp_get_attachment_image_url( $id, 'full' );
		return array(
			'logo_attachment_id' => $id,
			'logo_url'           => $url ? esc_url_raw( $url ) : '',
		);
	}
}

/**
 * 全站唯一品牌标识读取入口（Header、Footer 共用）。
 *
 * 职责：
 * - 从 puffergo_site_profile 读取品牌名与 Logo 附件。
 * - 通过 resolve_logo_assets() 确保 URL 实时由附件 ID 派生，永远有效。
 * - 读取附件的 Alt 文本，优先使用附件自身设置，回退为品牌名。
 * - 每次请求静态缓存，避免多处调用导致重复 DB 读取。
 *
 * @return array{
 *   brand_name: string,
 *   logo_url:   string,
 *   logo_alt:   string,
 *   logo_id:    int,
 *   contact:    array{email:string,phone:string,address:string,channels:array},
 * }
 */
function puffergo_get_site_brand_identity() {
	static $cached = null;
	if ( null !== $cached ) {
		return $cached;
	}

	$profile    = get_option( PufferGo_Site_Profile::OPTION_KEY, array() );
	$raw_assets = ( isset( $profile['assets'] ) && is_array( $profile['assets'] ) ) ? $profile['assets'] : array();
	$assets     = PufferGo_Site_Profile::resolve_logo_assets( $raw_assets );

	$site_name  = get_bloginfo( 'name' );
	$brand_name = ! empty( $profile['identity']['brand_name'] ) ? $profile['identity']['brand_name'] : $site_name;

	// Logo alt：优先读附件自身设置，回退为品牌名。
	$logo_id  = (int) $assets['logo_attachment_id'];
	$logo_alt = $brand_name;
	if ( $logo_id > 0 ) {
		$att_alt = get_post_meta( $logo_id, '_wp_attachment_image_alt', true );
		if ( ! empty( $att_alt ) ) {
			$logo_alt = $att_alt;
		}
	}

	// 联系信息（Footer 共用）。
	$raw_contact = ( isset( $profile['contact'] ) && is_array( $profile['contact'] ) ) ? $profile['contact'] : array();
	$contact     = array(
		'email'    => isset( $raw_contact['email'] ) ? sanitize_email( $raw_contact['email'] ) : '',
		'phone'    => isset( $raw_contact['phone'] ) ? sanitize_text_field( $raw_contact['phone'] ) : '',
		'address'  => isset( $raw_contact['address'] ) ? sanitize_textarea_field( $raw_contact['address'] ) : '',
		'channels' => isset( $raw_contact['channels'] ) && is_array( $raw_contact['channels'] ) ? $raw_contact['channels'] : array(),
	);

	$cached = array(
		'brand_name' => $brand_name,
		'logo_url'   => $assets['logo_url'],
		'logo_alt'   => $logo_alt,
		'logo_id'    => $logo_id,
		'contact'    => $contact,
	);
	return $cached;
}

/**
 * 输出站点 Logo 图片。
 *
 * 内部读取 puffergo_get_site_brand_identity()，模板只需传 class 和加载策略。
 * 有 logo 时输出并返回 true；无 logo 时不输出、返回 false（供模板渲染品牌名回退）。
 *
 * 当附件 ID 有效时使用 wp_get_attachment_image()（自动 srcset、WP 核心转义）；
 * 仅有 URL 时退回手动 <img>（兼容旧数据）。
 *
 * @param string $class       CSS class 字符串。
 * @param array  $extra_attrs 额外 HTML 属性，如 ['fetchpriority'=>'high','loading'=>'eager']。
 * @return bool 是否输出了 logo。
 */
function puffergo_the_logo( $class = 'h-8 w-auto max-w-[12rem] object-contain object-left', $extra_attrs = array() ) {
	$brand    = puffergo_get_site_brand_identity();
	$logo_id  = $brand['logo_id'];
	$logo_url = $brand['logo_url'];
	$logo_alt = $brand['logo_alt'];

	if ( $logo_id > 0 ) {
		$attrs = array_merge(
			array( 'class' => $class, 'alt' => $logo_alt ),
			$extra_attrs
		);
		// wp_get_attachment_image() 是 WP 核心函数，已自行转义所有输出。
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo wp_get_attachment_image( $logo_id, 'full', false, $attrs );
		return true;
	}

	if ( '' !== $logo_url ) {
		$attr_parts = array( 'class="' . esc_attr( $class ) . '"' );
		foreach ( $extra_attrs as $k => $v ) {
			$attr_parts[] = esc_attr( $k ) . '="' . esc_attr( (string) $v ) . '"';
		}
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- 每个属性片段均已转义。
		echo '<img src="' . esc_url( $logo_url ) . '" alt="' . esc_attr( $logo_alt ) . '" ' . implode( ' ', $attr_parts ) . '>';
		return true;
	}

	return false;
}
