<?php
/**
 * NeccoSpeak — Agent UI: セキュリティ タブ（本番 ai-agent-embed v1.5.1.1 の
 * 「セキュリティ」タブと同じ見た目・同じ画面構成で描画する）。
 *
 * 本番のセキュリティタブは includes/admin-agent-settings.php
 * ai_agent_embed_render_advanced_wrapper( 'security' ) が
 *   1. （旧）フィードバック評価 — 2026-08 に無料版から機能ごと撤去（下記参照）
 *   2. セキュリティ・制限設定 / PII保護 / 禁止ワード
 *                                          （ai_agent_embed_render_section_security）
 * の順で描画する。本番の「セキュリティ・制限設定」セクション内はさらに
 *   2-1. セキュリティ・制限設定（1ユーザーあたりの送信回数制限・連投制限）
 *   2-2. PII（個人情報）保護（メール／電話／クレジットカードの3行）
 *   2-3. 禁止ワード（禁止ワードフィルタ・1行のみ）
 * の順（admin-agent-settings.php:2049-2120）。このタブの本編（下記 3〜4）は
 * この本番の見出し・行順・文言をそのまま再現する。
 *
 * 2026-08 撤去記録: 本編先頭にあった「フィードバック評価」セクション
 * （feedback_enabled / feedback_comment_enabled の2チェックボックスを
 * 'logs' スロットのフォームで保存していた）は、AI応答評価機能を無料版から
 * 提供しない製品判断により、オプション・REST・DB・フロント実装ごと削除した。
 * このセクション専用の <form> だったためフォームごと削除している。
 *
 * 統一レイアウト方針（プロジェクト全体で確定）に基づき、本番の同タブに存在しない
 * NeccoSpeak 独自項目は本編から全て外し、タブ末尾の
 * neccospeak_agent_ui_render_security_ns_only_section() へ隔離した
 * （機能・バインド・保存経路は変更していない。位置のみ移動）。
 *   - 送信回数・音声トークン制限（IP単位／サイト全体） … rate_limit_per_min /
 *     rate_limit_global_hourly / rate_limit_global_daily / realtime_limit_per_min /
 *     realtime_global_daily（'rate-limits' スロット）。本番の「1ユーザーあたりの
 *     送信回数制限」「連投制限」に相当する NS キーは存在しないため、本編側は
 *     本番と同じ2行を灰色の有料版プレースホルダーとして残す。
 *   - PII保護の追加オプション … pii_client_warning / pii_warning_text（ブラウザ上の
 *     警告）、pii_mask_server（サーバー側マスキングの親スイッチ。本番には無いが、
 *     REST 側（includes/rest.php）がこのフラグをマスキング適用のゲートとして
 *     参照しているため意味を変えずに残している）。本編側の PII セクションは
 *     本番と同じ3行（メール／電話／クレジットカードのマスキング。pii_types[] に
 *     バインド）のみで、本番にある説明文は無いためそのまま。
 *   - 禁止ワードの追加オプション … banned_block_input（該当メッセージをブロック）・
 *     banned_mask_output（応答内でもマスクする）・banned_reply_text（定型返信文）。
 *     本編側の禁止ワードセクションは本番と同じ1行（禁止ワードフィルタ・banned_words）
 *     のみ。ただし説明文末尾にあったバイト数上限注記（neccospeak_field_max_bytes_note）
 *     は本番の説明文に無いため2026-08に追加で非表示化（textarea本体・name/valueは不変）。
 *
 * フォームは元と同じ neccospeak_agent_ui_form_open('旧タブslug') / _close() を
 * 経由する。'safety' スロットは本編（PII 3行 + 禁止ワードフィルタ）と末尾
 * （PII追加オプション + 禁止ワード追加オプション）の2箇所で別々のフォームとして
 * 開閉するが、これは同一ページに同一 slug のフォームを複数置く既存の設計
 * （includes/agent-ui.php の docblock 参照）通りで問題ない。各キーの入力欄は
 * どちらも1箇所のみで、二重描画にはなっていない。
 *
 * @package NeccoSpeak
 */

defined( 'ABSPATH' ) || exit;

/**
 * セキュリティ タブ本体。
 *
 * @param array $opts neccospeak_editing_options() 相当。
 * @return void
 */
function neccospeak_agent_ui_tab_security( $opts ) {
	$opts = is_array( $opts ) ? $opts : array();
	?>
	<div class="ai-agent-section" id="ai-agent-advanced-security">
		<div class="ai-agent-section-header">
			<h2><?php echo esc_html__( 'Security & privacy', 'neccospeak' ); ?></h2>
		</div>
		<p class="description">
			<?php
			printf(
				/* translators: %1$s: 「即時反映」(強調), %2$s: 「ドラフト保存」(強調) */
				esc_html__( 'Advanced model and LLM settings. Model selection is %1$s, while advanced LLM parameters such as temperature are %2$s and must be published from the Dashboard tab.', 'neccospeak' ),
				'<strong>' . esc_html__( 'Applied immediately', 'neccospeak' ) . '</strong>',
				'<strong>' . esc_html__( 'Saved as a draft', 'neccospeak' ) . '</strong>'
			);
			?>
		</p>

		<?php
		$pii_types_selected = ( isset( $opts['pii_types'] ) && is_array( $opts['pii_types'] ) ) ? $opts['pii_types'] : array();
		?>
		<?php /* ── 3. PII（個人情報）保護（本番と同順・同内容の3行のみ） ── */ ?>
		<h3><?php echo esc_html__( 'PII (personal information) protection', 'neccospeak' ); ?></h3>
		<?php if ( function_exists( 'neccospeak_agent_ui_form_open' ) ) : ?>
			<?php neccospeak_agent_ui_form_open( 'safety' ); ?>
			<table class="form-table ai-agent-form-table">
				<tr>
					<th scope="row"><?php echo esc_html__( 'Email address masking', 'neccospeak' ); ?></th>
					<td>
						<label>
							<input type="checkbox" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[pii_types][]" value="email" <?php checked( in_array( 'email', $pii_types_selected, true ) ); ?> />
							<?php echo esc_html__( 'Mask users\' email addresses', 'neccospeak' ); ?>
						</label>
					</td>
				</tr>
				<tr>
					<th scope="row"><?php echo esc_html__( 'Phone number masking', 'neccospeak' ); ?></th>
					<td>
						<label>
							<input type="checkbox" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[pii_types][]" value="phone" <?php checked( in_array( 'phone', $pii_types_selected, true ) ); ?> />
							<?php echo esc_html__( 'Mask users\' phone numbers', 'neccospeak' ); ?>
						</label>
					</td>
				</tr>
				<tr>
					<th scope="row"><?php echo esc_html__( 'Credit card masking', 'neccospeak' ); ?></th>
					<td>
						<label>
							<input type="checkbox" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[pii_types][]" value="card" <?php checked( in_array( 'card', $pii_types_selected, true ) ); ?> />
							<?php echo esc_html__( 'Mask users\' credit card numbers', 'neccospeak' ); ?>
						</label>
					</td>
				</tr>
			</table>

			<?php /* ── 4. 禁止ワード（本番と同順・同内容の1行のみ。同じ 'safety' フォーム内で継続） ── */ ?>
			<h3><?php echo esc_html__( 'Blocked words', 'neccospeak' ); ?></h3>
			<table class="form-table ai-agent-form-table">
				<tr>
					<th scope="row"><?php echo esc_html__( 'Blocked words filter', 'neccospeak' ); ?></th>
					<td>
						<textarea class="large-text" rows="4" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[banned_words]" placeholder="<?php echo esc_attr__( 'One word per line', 'neccospeak' ); ?>"><?php echo esc_textarea( $opts['banned_words'] ); ?></textarea>
						<p class="description">
							<?php echo esc_html__( 'Enter words you do not want in the agent\'s replies, one per line (note: this is a WordPress-side filter only; it is not applied to the backend AI response)', 'neccospeak' ); ?>
							<?php
							$safety_specs = function_exists( 'neccospeak_field_specs' ) ? neccospeak_field_specs() : array();
							if ( isset( $safety_specs['banned_words']['max'] ) ) :
								/* 2026-08 本番の禁止ワード説明文にはバイト数上限の注記が無いため非表示化。
								出力テキストのみでPOST対象の値ではないが、他ブロックと同じDOM保持規約
								（削除せず display:none で包む）を踏襲する。 */
								?>
								<span style="display:none" aria-hidden="true" data-neccospeak-extras-hidden="1"><?php echo esc_html( neccospeak_field_max_bytes_note( $safety_specs['banned_words']['max'] ) ); ?></span>
							<?php endif; ?>
						</p>
					</td>
				</tr>
			</table>
			<?php neccospeak_agent_ui_form_close( __( 'Save', 'neccospeak' ) ); ?>
		<?php endif; ?>

		<?php /* 2026-08 ユーザー決定: 「NeccoSpeak独自の設定」セクションを一旦非表示にする。
		DOMからは削除しない — hidden化した項目のinputはそのままPOSTされ続けるため、保存時に
		チェックボックスが未チェック扱いになって機能が意図せずOFFになる事故を防ぐ。フィールドの
		name/値・保存経路は変更しない。 */ ?>
		<div style="display:none" aria-hidden="true" data-neccospeak-extras-hidden="1">
		<?php neccospeak_agent_ui_render_security_ns_only_section( $opts ); ?>
		</div>
	</div>
	<?php
}

/**
 * 「NeccoSpeak独自の設定」— 本番の同タブには存在しない NeccoSpeak 独自項目を
 * タブ末尾へ隔離するセクション（統一レイアウト方針・項目4）。
 *
 * 内訳（いずれも本編から場所を移しただけで、機能・バインド・保存経路は変更なし）:
 *   - 送信回数・音声トークン制限（IPアドレス単位／サイト全体） … 'rate-limits' スロット。
 *   - PII保護の追加オプション（ブラウザ上の警告・サーバー側マスキング） … 'safety' スロット。
 *   - 禁止ワードの追加オプション（入力ブロック・応答内マスク・定型返信文） … 'safety' スロット
 *     （PII追加オプションと同じフォーム内で続けて保存する。元の実装と同じ構成）。
 *
 * @param array $opts neccospeak_editing_options() 相当。
 * @return void
 */
function neccospeak_agent_ui_render_security_ns_only_section( $opts ) {
	?>
	<h3 class="title"><?php echo esc_html__( 'NeccoSpeak-specific settings', 'neccospeak' ); ?></h3>
	<p class="description"><?php echo esc_html__( 'NeccoSpeak-specific items that do not exist in the production (paid) version\'s screens.', 'neccospeak' ); ?></p>

	<h4><?php echo esc_html__( 'Message and voice token limits (per IP address / site-wide)', 'neccospeak' ); ?></h4>
	<?php if ( function_exists( 'neccospeak_agent_ui_form_open' ) ) : ?>
		<?php neccospeak_agent_ui_form_open( 'rate-limits' ); ?>
		<table class="form-table ai-agent-form-table">
			<tr>
				<th scope="row"><?php echo esc_html__( 'Message limit (per minute)', 'neccospeak' ); ?></th>
				<td>
					<input type="number" min="1" step="1" class="small-text" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[rate_limit_per_min]" value="<?php echo esc_attr( (string) $opts['rate_limit_per_min'] ); ?>" />
					<span class="description"><?php echo esc_html__( 'messages / minute (per IP address)', 'neccospeak' ); ?></span>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php echo esc_html__( 'Site-wide message limit (per hour)', 'neccospeak' ); ?></th>
				<td>
					<input type="number" min="1" step="1" class="small-text" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[rate_limit_global_hourly]" value="<?php echo esc_attr( (string) $opts['rate_limit_global_hourly'] ); ?>" />
					<span class="description"><?php echo esc_html__( 'messages / hour (site-wide, all visitors combined)', 'neccospeak' ); ?></span>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php echo esc_html__( 'Site-wide message limit (per day)', 'neccospeak' ); ?></th>
				<td>
					<input type="number" min="1" step="1" class="small-text" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[rate_limit_global_daily]" value="<?php echo esc_attr( (string) $opts['rate_limit_global_daily'] ); ?>" />
					<span class="description"><?php echo esc_html__( 'messages / day (site-wide, all visitors combined)', 'neccospeak' ); ?></span>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php echo esc_html__( 'Voice token issuance limit (per minute)', 'neccospeak' ); ?></th>
				<td>
					<input type="number" min="1" step="1" class="small-text" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[realtime_limit_per_min]" value="<?php echo esc_attr( (string) $opts['realtime_limit_per_min'] ); ?>" />
					<span class="description"><?php echo esc_html__( 'times / minute (per IP address; set strictly because of the high cost)', 'neccospeak' ); ?></span>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php echo esc_html__( 'Voice token issuance limit (per day, site-wide)', 'neccospeak' ); ?></th>
				<td>
					<input type="number" min="1" step="1" class="small-text" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[realtime_global_daily]" value="<?php echo esc_attr( (string) $opts['realtime_global_daily'] ); ?>" />
					<span class="description"><?php echo esc_html__( 'times / day (site-wide)', 'neccospeak' ); ?></span>
				</td>
			</tr>
		</table>
		<?php
		if ( function_exists( 'neccospeak_admin_tab_slot' ) ) {
			neccospeak_admin_tab_slot( 'rate_limits_bottom', $opts );
		}
		?>
		<?php neccospeak_agent_ui_form_close( __( 'Save', 'neccospeak' ) ); ?>
	<?php endif; ?>

	<h4><?php echo esc_html__( 'Additional options for PII protection and blocked words', 'neccospeak' ); ?></h4>
	<?php if ( function_exists( 'neccospeak_agent_ui_form_open' ) ) : ?>
		<?php neccospeak_agent_ui_form_open( 'safety' ); ?>
		<table class="form-table ai-agent-form-table">
			<tr>
				<th scope="row"><?php echo esc_html__( 'In-browser warning', 'neccospeak' ); ?></th>
				<td>
					<label>
						<input type="checkbox" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[pii_client_warning]" value="1" <?php checked( ! empty( $opts['pii_client_warning'] ) ); ?> />
						<?php echo esc_html__( 'While a visitor is typing what looks like personal information, show a warning below the input field (it does not block sending)', 'neccospeak' ); ?>
					</label>
					<p>
						<textarea class="large-text" rows="2" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[pii_warning_text]"><?php echo esc_textarea( $opts['pii_warning_text'] ); ?></textarea>
					</p>
					<p class="description"><?php echo esc_html__( 'This field is optional. If left blank, the built-in text is used.', 'neccospeak' ); ?></p>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php echo esc_html__( 'Server-side masking', 'neccospeak' ); ?></th>
				<td>
					<label>
						<input type="checkbox" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[pii_mask_server]" value="1" <?php checked( ! empty( $opts['pii_mask_server'] ) ); ?> />
						<?php echo esc_html__( 'Replace personal information in visitor input before sending it to OpenAI (applies to the types selected under "PII (personal information) protection" above)', 'neccospeak' ); ?>
					</label>
				</td>
			</tr>
		</table>
		<p class="description"><?php echo esc_html__( 'The in-browser warning and server-side masking both apply to text chat only. Voice (realtime) audio is sent directly from the visitor\'s browser to OpenAI, so neither can be applied.', 'neccospeak' ); ?></p>
		<p class="description"><?php echo esc_html__( 'Server-side masking applies only to what visitors type; it does not apply to the assistant\'s own earlier replies or to anything configured on the Prompt tab — so the assistant can still quote, for example, a phone number entered in the company information or FAQ fields.', 'neccospeak' ); ?></p>
		<p class="description"><?php echo esc_html__( 'Detection is pattern-based. Card numbers are additionally validated with a Luhn checksum to reduce false positives, but no pattern covers everything, and legitimate numbers may sometimes be masked. Because masking can remove information the assistant needs to answer, it is disabled by default.', 'neccospeak' ); ?></p>

		<table class="form-table ai-agent-form-table">
			<tr>
				<th scope="row"><?php echo esc_html__( 'Block matching messages', 'neccospeak' ); ?></th>
				<td>
					<label>
						<input type="checkbox" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[banned_block_input]" value="1" <?php checked( ! empty( $opts['banned_block_input'] ) ); ?> />
						<?php echo esc_html__( 'When a visitor\'s message contains a blocked word, reply with the canned response instead of sending it to OpenAI', 'neccospeak' ); ?>
					</label>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php echo esc_html__( 'Also mask in replies', 'neccospeak' ); ?></th>
				<td>
					<label>
						<input type="checkbox" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[banned_mask_output]" value="1" <?php checked( ! empty( $opts['banned_mask_output'] ) ); ?> />
						<?php echo esc_html__( 'Replace blocked words with ●● when they appear in the AI\'s own reply', 'neccospeak' ); ?>
					</label>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php echo esc_html__( 'Canned reply text', 'neccospeak' ); ?></th>
				<td>
					<textarea class="large-text" rows="2" name="<?php echo esc_attr( NECCOSPEAK_OPTION ); ?>[banned_reply_text]"><?php echo esc_textarea( $opts['banned_reply_text'] ); ?></textarea>
					<p class="description"><?php echo esc_html__( 'This field is optional. If left blank, the built-in text is used.', 'neccospeak' ); ?></p>
				</td>
			</tr>
		</table>
		<p class="description"><?php echo esc_html__( 'Blocked words are applied server-side to text chat only. Voice (realtime) audio travels directly from the visitor\'s browser to OpenAI without passing through the server, so this filter cannot be applied to voice conversations.', 'neccospeak' ); ?></p>
		<p class="description"><?php echo esc_html__( 'Matching ignores differences in Latin letter case and between full-width and half-width characters. Hiragana and katakana do not match each other, so register both forms if you need both. Entries shorter than 2 characters are ignored.', 'neccospeak' ); ?></p>
		<p class="description"><?php echo esc_html__( 'Entries written only in Latin letters, digits, and ASCII symbols match whole words (e.g. "ai" does not block "explain" or "mail"). Entries containing Japanese (or any non-ASCII characters) have no word boundaries and also match inside words — short Japanese entries can block more messages than you expect. Test your list against real incoming messages before enabling input blocking.', 'neccospeak' ); ?></p>
		<p class="description"><?php echo esc_html__( 'Reply masking replaces matches in the assistant\'s replies with ●●. Legitimate words that merely contain a blocked word may be masked by mistake.', 'neccospeak' ); ?></p>
		<p class="description"><?php echo esc_html__( 'Blocked messages are not sent to OpenAI so they cost nothing, but they still count toward the site-wide hourly and daily limits on the Rate Limits tab.', 'neccospeak' ); ?></p>

		<?php
		if ( function_exists( 'neccospeak_admin_tab_slot' ) ) {
			neccospeak_admin_tab_slot( 'safety_bottom', $opts );
		}
		?>
		<?php neccospeak_agent_ui_form_close( __( 'Save', 'neccospeak' ) ); ?>
	<?php endif; ?>
	<?php
}
