<?php
/**
 * Auto-reply templates admin page.
 *
 * @package SubmissionInbox
 */

use SUBIN\AutoReplies\AutoReplyTemplateLibrary;
use SUBIN\AutoReplies\AutoReplyTemplateRepository;
use SUBIN\AutoReplies\AutoReplyRuleRepository;
use SUBIN\AutoReplies\AutoReplyFormProviderRegistry;
use SUBIN\Forms\FormRepository;

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

/**
 * Renders reusable auto-reply template management.
 */
class SUBIN_AutoRepliesPage {
	const PAGE_SLUG    = 'submission-inbox-auto-replies';
	const NONCE_ACTION = 'subin_save_auto_reply_template';
	const NONCE_NAME   = 'subin_auto_reply_template_nonce';
	const RULE_NONCE_ACTION = 'subin_save_auto_reply_rule';
	const RULE_NONCE_NAME   = 'subin_auto_reply_rule_nonce';

	/**
	 * Template repository.
	 *
	 * @var AutoReplyTemplateRepository
	 */
	private $templates;

	/**
	 * Starter template library.
	 *
	 * @var AutoReplyTemplateLibrary
	 */
	private $library;

	/**
	 * Form repository.
	 *
	 * @var FormRepository
	 */
	private $forms;

	/**
	 * Rule repository.
	 *
	 * @var AutoReplyRuleRepository
	 */
	private $rules;

	/**
	 * Provider registry.
	 *
	 * @var AutoReplyFormProviderRegistry
	 */
	private $providers;

	/**
	 * Cached template usage counts.
	 *
	 * @var array<int|string,mixed>|null
	 */
	private $template_usage_counts = null;

	/**
	 * Current error message.
	 *
	 * @var string
	 */
	private $error_message = '';

	/**
	 * Submitted template data after validation failure.
	 *
	 * @var array<string,mixed>|null
	 */
	private $submitted_template = null;

	/**
	 * Submitted rule data after validation failure.
	 *
	 * @var array<string,mixed>|null
	 */
	private $submitted_rule = null;

	/**
	 * Rule field that failed validation.
	 *
	 * @var string
	 */
	private $rule_error_field = '';

	/**
	 * Whether state-changing request handling has already run.
	 *
	 * @var bool
	 */
	private $request_handled = false;

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->templates           = new AutoReplyTemplateRepository();
		$this->library             = new AutoReplyTemplateLibrary();
		$this->forms               = new FormRepository();
		$this->rules               = new AutoReplyRuleRepository();
		$this->providers           = new AutoReplyFormProviderRegistry();
	}

	/**
	 * Render page.
	 *
	 * @return void
	 */
	public function render() {
		if ( ! current_user_can( SUBIN_AdminMenu::CAPABILITY ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'submission-inbox' ) );
		}

		$this->handle_request();

		$view        = SUBIN_Request::get_key( 'view' );
		$rule_view   = SUBIN_Request::get_key( 'rule_view' );
		$template_id = SUBIN_Request::get_absint( 'id' );
		$tab         = $this->current_tab( $view );

		$this->render_page_header( $view, $tab );

		$this->render_notices();

		if ( 'new' === $rule_view || ( 'edit' === $rule_view && SUBIN_Request::get_absint( 'id' ) > 0 ) ) {
			$this->render_rule_editor();
		} elseif ( 'new' === $view ) {
			$this->render_gallery();
		} elseif ( 'preview' === $view ) {
			$this->render_starter_preview();
		} elseif ( 'editor' === $view ) {
			$this->render_editor( $this->editor_template_from_request() );
		} elseif ( 'edit' === $view && $template_id > 0 ) {
			$template = $this->submitted_template ? $this->submitted_template : $this->templates->get( $template_id );
			if ( $template ) {
				$this->render_editor( $template );
			} else {
				$this->render_list( __( 'Auto-reply template not found.', 'submission-inbox' ) );
			}
		} elseif ( 'templates' === $tab ) {
			$this->render_list();
		} else {
			$this->render_rules_tab();
		}

		SUBIN_View::page_footer();
	}

	/**
	 * Handle redirects and state changes before admin HTML is sent.
	 *
	 * @return void
	 */
	public function handle_request() {
		if ( $this->request_handled ) {
			return;
		}

		$this->request_handled = true;

		if ( ! current_user_can( SUBIN_AdminMenu::CAPABILITY ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'submission-inbox' ) );
		}

		$this->maybe_save_rule();
		$this->maybe_handle_rule_action();
		$this->maybe_handle_row_action();
		$this->maybe_save_template();
	}

	/**
	 * Render the contextual page header.
	 *
	 * @param string $view Current view.
	 * @return void
	 */
	private function render_page_header( $view, $tab ) {
		if ( 'new' === $view ) {
			SUBIN_View::page_header(
				__( 'Choose an Auto-reply Template', 'submission-inbox' ),
				__( 'Start with a ready-made email layout and customize it for your form replies.', 'submission-inbox' ),
				array(
					'wrapper_class' => 'subin-auto-replies-page subin-form-templates-page',
				)
			);
			return;
		}

		if ( 'preview' === $view ) {
			SUBIN_View::page_header(
				__( 'Preview Auto-reply Template', 'submission-inbox' ),
				__( 'Review the starter email before creating it.', 'submission-inbox' ),
				array(
					'wrapper_class' => 'subin-auto-replies-page subin-form-templates-page',
				)
			);
			return;
		}

		SUBIN_View::page_header(
			__( 'Auto-replies', 'submission-inbox' ),
			__( 'Create reusable visitor confirmation emails and choose which forms should send them.', 'submission-inbox' ),
			array(
				'wrapper_class'  => 'subin-auto-replies-page',
				'primary_action' => array(
					'label' => 'templates' === $tab ? __( 'Create template', 'submission-inbox' ) : __( 'Create auto-reply rule', 'submission-inbox' ),
					'url'   => 'templates' === $tab ? $this->new_url() : $this->rule_edit_url( 0 ),
				),
			)
		);
		$this->render_management_tabs( $tab );
	}

	/**
	 * Render Forms product navigation.
	 *
	 * @return void
	 */
	private function render_management_tabs( $active = 'rules' ) {
		SUBIN_View::admin_tabs(
			array(
				array(
					'key'   => 'rules',
					'label' => __( 'Rules', 'submission-inbox' ),
					'url'   => $this->rules_url(),
				),
				array(
					'key'   => 'templates',
					'label' => __( 'Templates', 'submission-inbox' ),
					'url'   => $this->templates_url(),
				),
			),
			in_array( $active, array( 'rules', 'templates' ), true ) ? $active : 'rules'
		);
	}

	/**
	 * Render rules tab.
	 *
	 * @return void
	 */
	private function render_rules_tab() {
		$rules = $this->rules->list_rules(
			array(
				'per_page' => 200,
				'offset'   => 0,
			)
		);
		?>
		<div class="subin-forms-section subin-auto-reply-rules-section">
			<div class="subin-section-heading">
				<h2><?php esc_html_e( 'Auto-reply Rules', 'submission-inbox' ); ?></h2>
				<p><?php esc_html_e( 'Rules connect a form, a visitor email field, and an auto-reply template.', 'submission-inbox' ); ?></p>
			</div>
			<p class="subin-help"><?php esc_html_e( 'Auto-replies are sent only when the selected form field contains a valid email address.', 'submission-inbox' ); ?></p>

			<?php if ( empty( $rules ) ) : ?>
				<div class="subin-forms-empty-state subin-empty-state">
					<h2><?php esc_html_e( 'No auto-reply rules yet.', 'submission-inbox' ); ?></h2>
					<p><?php esc_html_e( 'Create a rule to send a visitor confirmation email after a supported form is submitted.', 'submission-inbox' ); ?></p>
					<div class="subin-forms-empty-state__actions">
						<a class="button button-primary subin-btn subin-btn-primary" href="<?php echo esc_url( $this->rule_edit_url( 0 ) ); ?>"><?php esc_html_e( 'Create auto-reply rule', 'submission-inbox' ); ?></a>
					</div>
				</div>
				<?php return; ?>
			<?php endif; ?>

			<table class="widefat striped subin-auto-reply-rules-table">
				<thead>
					<tr>
						<th><?php esc_html_e( 'Rule name', 'submission-inbox' ); ?></th>
						<th><?php esc_html_e( 'Provider', 'submission-inbox' ); ?></th>
						<th><?php esc_html_e( 'Form', 'submission-inbox' ); ?></th>
						<th><?php esc_html_e( 'Visitor email field', 'submission-inbox' ); ?></th>
						<th><?php esc_html_e( 'Template', 'submission-inbox' ); ?></th>
						<th><?php esc_html_e( 'Status', 'submission-inbox' ); ?></th>
						<th><?php esc_html_e( 'Last edited', 'submission-inbox' ); ?></th>
						<th><?php esc_html_e( 'Actions', 'submission-inbox' ); ?></th>
					</tr>
				</thead>
				<tbody>
					<?php foreach ( $rules as $rule ) : ?>
						<?php $this->render_rule_row( $rule ); ?>
					<?php endforeach; ?>
				</tbody>
			</table>
		</div>
		<?php
	}

	/**
	 * Render one rule row.
	 *
	 * @param array<string,mixed> $rule Rule.
	 * @return void
	 */
	private function render_rule_row( array $rule ) {
		$rule_id  = absint( $rule['id'] ?? 0 );
		$template = $this->templates->get( absint( $rule['template_id'] ?? 0 ) );
		$status   = $this->rule_status_details( $rule, $template );
		?>
		<tr>
			<td><strong><?php echo esc_html( (string) ( $rule['name'] ?? __( 'Untitled rule', 'submission-inbox' ) ) ); ?></strong></td>
			<td><?php echo esc_html( $this->providers->provider_label( (string) ( $rule['provider'] ?? '' ) ) ); ?></td>
			<td><?php echo esc_html( (string) ( $rule['form_name'] ?: $rule['form_id'] ) ); ?></td>
			<td><?php echo esc_html( (string) ( $rule['visitor_email_field_label'] ?: $rule['visitor_email_field'] ) ); ?></td>
			<td>
				<?php if ( $template ) : ?>
					<a href="<?php echo esc_url( $this->edit_url( absint( $template['id'] ?? 0 ) ) ); ?>"><?php echo esc_html( (string) ( $template['name'] ?? '' ) ); ?></a>
				<?php else : ?>
					<?php esc_html_e( 'Missing template', 'submission-inbox' ); ?>
				<?php endif; ?>
			</td>
			<td><?php SUBIN_View::badge( $status['label'], $status['type'] ); ?></td>
			<td><?php echo esc_html( $this->format_date( (string) ( $rule['updated_at'] ?? '' ) ) ); ?></td>
			<td>
				<div class="subin-row-actions">
					<a href="<?php echo esc_url( $this->rule_edit_url( $rule_id ) ); ?>"><?php esc_html_e( 'Edit', 'submission-inbox' ); ?></a>
					<a href="<?php echo esc_url( $this->rule_action_url( 'duplicate', $rule_id ) ); ?>"><?php esc_html_e( 'Duplicate', 'submission-inbox' ); ?></a>
					<a href="<?php echo esc_url( $this->rule_action_url( ! empty( $rule['enabled'] ) ? 'disable' : 'enable', $rule_id ) ); ?>"><?php echo esc_html( ! empty( $rule['enabled'] ) ? __( 'Disable', 'submission-inbox' ) : __( 'Enable', 'submission-inbox' ) ); ?></a>
					<a class="subin-action-chip-danger" href="<?php echo esc_url( $this->rule_action_url( 'delete', $rule_id ) ); ?>" onclick="return window.confirm('<?php echo esc_js( __( 'Delete this auto-reply rule?', 'submission-inbox' ) ); ?>');"><?php esc_html_e( 'Delete', 'submission-inbox' ); ?></a>
				</div>
			</td>
		</tr>
		<?php
	}

	/**
	 * Render Add/Edit rule screen.
	 *
	 * @return void
	 */
	private function render_rule_editor() {
			$rule_id = SUBIN_Request::get_absint( 'id' );
			$rule    = $rule_id > 0 ? $this->rules->find( $rule_id ) : null;
			$rule    = $rule ? $rule : $this->empty_rule();
			if ( is_array( $this->submitted_rule ) ) {
				$rule = array_merge( $rule, $this->submitted_rule );
			}
			if ( $rule_id <= 0 ) {
				$rule['provider'] = SUBIN_Request::get_key( 'provider' ) ?: AutoReplyRuleRepository::PROVIDER_SUBMISSION_INBOX_FORM;
				$rule['form_id']  = sanitize_text_field( SUBIN_Request::get_text( 'form_id' ) );
			}
			if ( is_array( $this->submitted_rule ) ) {
				$rule['provider'] = $this->submitted_rule['provider'];
				$rule['form_id']  = $this->submitted_rule['form_id'];
			}

		$provider     = $this->rules->sanitize_provider( (string) ( $rule['provider'] ?? '' ) ) ?: AutoReplyRuleRepository::PROVIDER_SUBMISSION_INBOX_FORM;
		$forms        = $this->providers->list_forms( $provider );
		$form_id      = sanitize_text_field( (string) ( $rule['form_id'] ?? '' ) );
		$form_choice  = $this->providers->get_form( $provider, $form_id );
		$email_fields = $this->providers->list_email_fields( $provider, $form_id );
		$all_forms    = $this->all_provider_form_choices();
		$all_email_fields = $this->all_provider_email_field_choices();
		$templates    = $this->templates->get_paginated( array( 'per_page' => 200, 'offset' => 0 ) );
		?>
		<a class="subin-back-link" href="<?php echo esc_url( $this->rules_url() ); ?>"><?php esc_html_e( 'Back to rules', 'submission-inbox' ); ?></a>
		<form method="post" action="" class="subin-settings-card subin-auto-reply-rule-editor">
			<?php wp_nonce_field( self::RULE_NONCE_ACTION, self::RULE_NONCE_NAME ); ?>
			<input type="hidden" name="subin_auto_reply_rule_save" value="1" />
			<input type="hidden" name="rule_id" value="<?php echo esc_attr( (string) $rule_id ); ?>" />

			<header class="subin-settings-card__header">
				<div>
					<h2><?php echo esc_html( $rule_id > 0 ? __( 'Edit auto-reply rule', 'submission-inbox' ) : __( 'Create auto-reply rule', 'submission-inbox' ) ); ?></h2>
					<p><?php esc_html_e( 'Choose which form sends a visitor confirmation email and which template it uses.', 'submission-inbox' ); ?></p>
				</div>
			</header>
			<div class="subin-settings-card__body">
				<div class="subin-settings-grid">
						<div class="<?php echo esc_attr( $this->rule_field_class( 'name' ) ); ?>">
							<label for="subin-rule-name"><?php esc_html_e( 'Rule name', 'submission-inbox' ); ?></label>
							<input id="subin-rule-name" type="text" name="name" value="<?php echo esc_attr( (string) ( $rule['name'] ?? '' ) ); ?>" required <?php echo 'name' === $this->rule_error_field ? 'aria-invalid="true"' : ''; ?> />
							<?php $this->render_rule_field_error( 'name', __( 'Enter a short internal name for this auto-reply rule.', 'submission-inbox' ) ); ?>
						</div>
						<div class="<?php echo esc_attr( $this->rule_field_class( 'provider' ) ); ?>">
							<label for="subin-rule-provider"><?php esc_html_e( 'Provider', 'submission-inbox' ); ?></label>
							<select id="subin-rule-provider" name="provider" <?php echo 'provider' === $this->rule_error_field ? 'aria-invalid="true"' : ''; ?>>
							<?php foreach ( $this->providers->providers() as $item ) : ?>
								<option value="<?php echo esc_attr( $item['key'] ); ?>" <?php selected( $provider, $item['key'] ); ?> <?php disabled( empty( $item['forms'] ) ); ?>><?php echo esc_html( empty( $item['forms'] ) ? sprintf(
									/* translators: %s: provider label. */
									__( '%s (planned)', 'submission-inbox' ),
									$item['label']
								) : $item['label'] ); ?></option>
							<?php endforeach; ?>
						</select>
						<p><?php esc_html_e( 'Choose a provider first. The form and visitor email field lists will show only matching forms for that provider.', 'submission-inbox' ); ?></p>
					</div>
				</div>
				<div class="subin-settings-grid">
						<div class="<?php echo esc_attr( $this->rule_field_class( 'form' ) ); ?>">
							<label for="subin-rule-form"><?php esc_html_e( 'Form', 'submission-inbox' ); ?></label>
							<select id="subin-rule-form" name="form_id" data-subin-rule-form-select <?php echo 'form' === $this->rule_error_field ? 'aria-invalid="true"' : ''; ?>>
							<option value=""><?php esc_html_e( 'Select form', 'submission-inbox' ); ?></option>
							<?php foreach ( $all_forms as $form ) : ?>
								<option value="<?php echo esc_attr( $form['value'] ); ?>" data-subin-provider="<?php echo esc_attr( $form['provider'] ); ?>" <?php selected( $provider . '|' . $form_id, $form['value'] ); ?> <?php echo $provider === $form['provider'] ? '' : 'hidden'; ?>><?php echo esc_html( $form['label'] ); ?></option>
							<?php endforeach; ?>
							</select>
							<?php $this->render_rule_field_error( 'form', __( 'Select the form that should send this auto-reply.', 'submission-inbox' ) ); ?>
						</div>
						<div class="<?php echo esc_attr( $this->rule_field_class( 'visitor_email_field' ) ); ?>">
							<label for="subin-rule-email-field"><?php esc_html_e( 'Visitor email field', 'submission-inbox' ); ?></label>
							<select id="subin-rule-email-field" name="visitor_email_field" data-subin-rule-email-field-select <?php disabled( empty( $all_email_fields ) ); ?> <?php echo 'visitor_email_field' === $this->rule_error_field ? 'aria-invalid="true"' : ''; ?>>
							<option value=""><?php esc_html_e( 'Select visitor email field', 'submission-inbox' ); ?></option>
							<?php foreach ( $all_email_fields as $field ) : ?>
								<?php $field_visible = $provider === $field['provider'] && ( '' === $form_id || $provider . '|' . $form_id === $field['form_value'] ); ?>
								<option value="<?php echo esc_attr( $field['value'] ); ?>" data-subin-provider="<?php echo esc_attr( $field['provider'] ); ?>" data-subin-form-value="<?php echo esc_attr( $field['form_value'] ); ?>" <?php selected( $provider . '|' . (string) $form_id . '|' . (string) ( $rule['visitor_email_field'] ?? '' ), $field['value'] ); ?> <?php echo $field_visible ? '' : 'hidden'; ?>><?php echo esc_html( $field['label'] ); ?></option>
							<?php endforeach; ?>
							</select>
							<?php $this->render_rule_field_error( 'visitor_email_field', __( 'Select the email field that contains the visitor address.', 'submission-inbox' ) ); ?>
							<?php if ( $form_choice && empty( $email_fields ) ) : ?>
								<p class="subin-settings-warning"><?php esc_html_e( 'This form does not have an Email field. Add an Email field before enabling visitor auto-reply.', 'submission-inbox' ); ?></p>
						<?php elseif ( empty( $all_email_fields ) ) : ?>
							<p class="subin-settings-warning"><?php esc_html_e( 'No supported forms have an Email field yet.', 'submission-inbox' ); ?></p>
						<?php endif; ?>
					</div>
				</div>
				<div class="subin-settings-grid">
						<div class="<?php echo esc_attr( $this->rule_field_class( 'template' ) ); ?>">
							<label for="subin-rule-template"><?php esc_html_e( 'Auto-reply template', 'submission-inbox' ); ?></label>
							<select id="subin-rule-template" name="template_id" <?php disabled( empty( $templates ) ); ?> <?php echo 'template' === $this->rule_error_field ? 'aria-invalid="true"' : ''; ?>>
							<option value="0"><?php esc_html_e( 'Select template', 'submission-inbox' ); ?></option>
							<?php foreach ( $templates as $template ) : ?>
								<option value="<?php echo esc_attr( (string) absint( $template['id'] ?? 0 ) ); ?>" <?php selected( absint( $rule['template_id'] ?? 0 ), absint( $template['id'] ?? 0 ) ); ?>><?php echo esc_html( (string) ( $template['name'] ?? '' ) ); ?></option>
							<?php endforeach; ?>
							</select>
							<?php $this->render_rule_field_error( 'template', __( 'Select the email template this rule should send.', 'submission-inbox' ) ); ?>
							<?php if ( empty( $templates ) ) : ?>
							<p class="subin-settings-warning"><?php esc_html_e( 'Create an auto-reply template before enabling this rule.', 'submission-inbox' ); ?></p>
						<?php endif; ?>
					</div>
					<div class="subin-settings-field">
						<label class="subin-settings-toggle">
							<input type="checkbox" name="enabled" value="1" <?php checked( ! empty( $rule['enabled'] ) ); ?> />
							<span></span>
							<strong><?php esc_html_e( 'Enabled', 'submission-inbox' ); ?></strong>
						</label>
					</div>
				</div>
				<div class="subin-settings-actions">
					<?php submit_button( __( 'Save rule', 'submission-inbox' ), 'primary', 'submit', false ); ?>
				</div>
			</div>
			</form>
			<?php
		}

	/**
	 * Build field wrapper class for rule editor validation.
	 *
	 * @param string $field Field key.
	 * @return string
	 */
	private function rule_field_class( $field ) {
		$classes = array( 'subin-settings-field' );
		if ( $field === $this->rule_error_field ) {
			$classes[] = 'subin-settings-field--error';
		}

		return implode( ' ', $classes );
	}

	/**
	 * Render inline rule field validation help.
	 *
	 * @param string $field Field key.
	 * @param string $message Message.
	 * @return void
	 */
	private function render_rule_field_error( $field, $message ) {
		if ( $field !== $this->rule_error_field ) {
			return;
		}
		?>
		<p class="subin-settings-field-error"><?php echo esc_html( $message ); ?></p>
		<?php
	}

	/**
	 * Store rule validation error state.
	 *
	 * @param string $field Field key.
	 * @param string $message Message.
	 * @return void
	 */
	private function set_rule_error( $field, $message ) {
		$this->rule_error_field = sanitize_key( $field );
		$this->error_message    = $message;
	}

	/**
	 * Render list view.
	 *
	 * @param string $message Optional inline message.
	 * @return void
	 */
	private function render_list( $message = '' ) {
		$templates = $this->templates->get_paginated(
			array(
				'per_page' => 50,
				'offset'   => 0,
			)
		);
		?>
		<?php if ( '' !== $message ) : ?>
			<div class="notice notice-error"><p><?php echo esc_html( $message ); ?></p></div>
		<?php endif; ?>

		<div class="subin-forms-section subin-auto-replies-section">
			<div class="subin-section-heading">
				<h2><?php esc_html_e( 'Auto-reply Templates', 'submission-inbox' ); ?></h2>
				<p><?php esc_html_e( 'Manage reusable visitor messages and attach them to forms from the form editor.', 'submission-inbox' ); ?></p>
			</div>

			<?php if ( empty( $templates ) ) : ?>
				<div class="subin-forms-empty-state subin-empty-state">
					<h2><?php esc_html_e( 'No auto-reply templates yet', 'submission-inbox' ); ?></h2>
					<p><?php esc_html_e( 'Create a reusable visitor confirmation message and attach it to a form.', 'submission-inbox' ); ?></p>
					<div class="subin-forms-empty-state__actions">
						<a class="button button-primary subin-btn subin-btn-primary" href="<?php echo esc_url( $this->new_url() ); ?>"><?php esc_html_e( 'Create auto-reply template', 'submission-inbox' ); ?></a>
					</div>
				</div>
				<?php return; ?>
			<?php endif; ?>

			<div class="subin-auto-reply-card-list">
				<?php foreach ( $templates as $template ) : ?>
					<?php $this->render_template_card( $template ); ?>
				<?php endforeach; ?>
			</div>
		</div>
		<?php
	}

	/**
	 * Render one template card.
	 *
	 * @param array<string,mixed> $template Template row.
	 * @return void
	 */
	private function render_template_card( array $template ) {
		$template_id = absint( $template['id'] ?? 0 );
		$name        = (string) ( $template['name'] ?? __( 'Untitled template', 'submission-inbox' ) );
		$subject     = (string) ( $template['subject'] ?? '' );
		$preheader   = (string) ( $template['preheader'] ?? '' );
		$used_count  = $this->get_used_by_forms_count( $template_id );
		$used_forms  = $this->get_forms_using_template( $template_id );
		$is_used     = $used_count > 0;
		?>
		<article class="subin-auto-reply-card subin-auto-reply-card--manager<?php echo $is_used ? ' subin-auto-reply-card--used' : ' subin-auto-reply-card--unused'; ?>">
			<div class="subin-auto-reply-card__preview">
				<?php $this->render_template_mini_preview( $template ); ?>
			</div>

			<div class="subin-auto-reply-card__content">
				<div class="subin-auto-reply-card__main">
					<div class="subin-auto-reply-card__title-row">
						<div class="subin-auto-reply-card__identity">
							<span class="subin-auto-reply-card__icon dashicons dashicons-email-alt2" aria-hidden="true"></span>
							<h3><a href="<?php echo esc_url( $this->edit_url( $template_id ) ); ?>"><?php echo esc_html( $name ); ?></a></h3>
						</div>
						<?php SUBIN_View::badge( $is_used ? __( 'Used', 'submission-inbox' ) : __( 'Not used', 'submission-inbox' ), $is_used ? 'success' : 'muted' ); ?>
					</div>

					<div class="subin-auto-reply-card__meta subin-meta">
						<span><?php esc_html_e( 'Last edited', 'submission-inbox' ); ?>: <?php echo esc_html( $this->format_date( (string) ( $template['updated_at'] ?? '' ) ) ); ?></span>
						<span><?php esc_html_e( 'Used by forms', 'submission-inbox' ); ?>: <?php echo esc_html( (string) $used_count ); ?></span>
					</div>

					<?php $this->render_used_by_forms( $used_forms, $used_count ); ?>

					<div class="subin-auto-reply-summary">
						<div class="subin-auto-reply-summary__item">
							<span><?php esc_html_e( 'Subject', 'submission-inbox' ); ?></span>
							<strong><?php echo esc_html( '' !== $subject ? $subject : __( 'No subject set', 'submission-inbox' ) ); ?></strong>
						</div>
						<div class="subin-auto-reply-summary__item">
							<span><?php esc_html_e( 'Preview text', 'submission-inbox' ); ?></span>
							<strong><?php echo esc_html( '' !== $preheader ? $preheader : __( 'Not set', 'submission-inbox' ) ); ?></strong>
						</div>
					</div>

				</div>

				<div class="subin-card-actions">
					<a class="button button-primary subin-btn subin-btn-primary" href="<?php echo esc_url( $this->edit_url( $template_id ) ); ?>"><?php esc_html_e( 'Edit template', 'submission-inbox' ); ?></a>
					<a class="subin-action-chip" href="<?php echo esc_url( $this->action_url( 'duplicate', $template_id ) ); ?>"><?php esc_html_e( 'Duplicate', 'submission-inbox' ); ?></a>
					<a class="subin-action-chip subin-action-chip-danger" href="<?php echo esc_url( $this->action_url( 'delete', $template_id ) ); ?>" onclick="return window.confirm('<?php echo esc_js( __( 'Delete this auto-reply template?', 'submission-inbox' ) ); ?>');"><?php esc_html_e( 'Delete', 'submission-inbox' ); ?></a>
				</div>
			</div>
		</article>
		<?php
	}

	/**
	 * Build template status display details.
	 *
	 * @param string $status Raw status.
	 * @return array{label:string,type:string}
	 */
	private function template_status_details( $status ) {
		$status = sanitize_key( $status );

		if ( AutoReplyTemplateRepository::STATUS_DRAFT === $status ) {
			return array(
				'label' => __( 'Draft', 'submission-inbox' ),
				'type'  => 'warning',
			);
		}

		if ( 'inactive' === $status ) {
			return array(
				'label' => __( 'Inactive', 'submission-inbox' ),
				'type'  => 'muted',
			);
		}

		return array(
			'label' => __( 'Active', 'submission-inbox' ),
			'type'  => 'success',
		);
	}

	/**
	 * Render compact supported variables row.
	 *
	 * @return void
	 */
	private function render_variables_row() {
		$variables = array();
		foreach ( $this->variable_groups() as $group_variables ) {
			foreach ( array_keys( $group_variables ) as $variable ) {
				$variables[] = $variable;
			}
		}
		$variables = array_slice( $variables, 0, 7 );
		?>
		<div class="subin-auto-reply-variables">
			<span class="subin-auto-reply-variables__label"><?php esc_html_e( 'Available variables', 'submission-inbox' ); ?></span>
			<div class="subin-auto-reply-variables__chips">
				<?php foreach ( $variables as $variable ) : ?>
					<code><?php echo esc_html( $variable ); ?></code>
				<?php endforeach; ?>
			</div>
		</div>
		<?php
	}

	/**
	 * Render starter template gallery.
	 *
	 * @return void
	 */
	private function render_gallery() {
		?>
		<a class="subin-back-link" href="<?php echo esc_url( $this->list_url() ); ?>"><?php esc_html_e( 'Back to templates', 'submission-inbox' ); ?></a>

		<div class="subin-template-grid subin-auto-reply-gallery">
			<?php foreach ( $this->library->all() as $template ) : ?>
				<div class="subin-template-card">
					<div class="subin-template-card__badge"><?php esc_html_e( 'Email template', 'submission-inbox' ); ?></div>
					<h2 class="subin-template-card__title"><?php echo esc_html( $template['name'] ); ?></h2>
					<p class="subin-template-card__description"><?php echo esc_html( $template['description'] ); ?></p>
					<div class="subin-template-card__count">
						<strong><?php esc_html_e( 'Subject:', 'submission-inbox' ); ?></strong>
						<?php echo esc_html( $template['subject'] ?? __( 'Auto-reply subject', 'submission-inbox' ) ); ?>
					</div>
					<p class="subin-template-card__fields">
						<strong><?php esc_html_e( 'Preheader:', 'submission-inbox' ); ?></strong>
						<?php echo esc_html( $template['preheader'] ?? __( 'Confirmation email preview text.', 'submission-inbox' ) ); ?>
					</p>
					<div class="subin-template-preview subin-auto-reply-template-preview" aria-hidden="true">
						<div class="subin-template-preview__viewport">
							<div class="subin-template-preview__scale subin-auto-reply-template-preview__scale">
								<style><?php echo esc_html( (string) ( $template['css'] ?? '' ) ); ?></style>
								<?php echo wp_kses( (string) ( $template['html'] ?? '' ), $this->email_preview_allowed_html(), array( 'http', 'https', 'mailto', 'tel' ) ); ?>
							</div>
						</div>
					</div>
					<div class="subin-template-card__actions">
						<a class="button button-primary subin-btn subin-btn-primary" href="<?php echo esc_url( $this->starter_editor_url( $template['key'] ) ); ?>"><?php esc_html_e( 'Use Template', 'submission-inbox' ); ?></a>
						<a class="button subin-btn subin-btn-secondary" href="<?php echo esc_url( $this->starter_preview_url( $template['key'] ) ); ?>"><?php esc_html_e( 'Preview', 'submission-inbox' ); ?></a>
					</div>
				</div>
			<?php endforeach; ?>
		</div>
		<?php
	}

	/**
	 * Render a larger starter template preview.
	 *
	 * @return void
	 */
	private function render_starter_preview() {
		$template_key = SUBIN_Request::get_key( 'template_key' );
		$template     = $this->library->get( $template_key );

		if ( ! $template ) {
			?>
			<a class="subin-back-link" href="<?php echo esc_url( $this->new_url() ); ?>"><?php esc_html_e( 'Back to templates', 'submission-inbox' ); ?></a>
			<div class="notice notice-error"><p><?php esc_html_e( 'Auto-reply template not found.', 'submission-inbox' ); ?></p></div>
			<?php
			return;
		}
		?>
		<div class="subin-page-actions">
			<a class="button button-primary subin-btn subin-btn-primary" href="<?php echo esc_url( $this->starter_editor_url( $template['key'] ) ); ?>"><?php esc_html_e( 'Use Template', 'submission-inbox' ); ?></a>
			<a class="button subin-btn subin-btn-secondary" href="<?php echo esc_url( $this->new_url() ); ?>"><?php esc_html_e( 'Back to Templates', 'submission-inbox' ); ?></a>
		</div>
		<div class="subin-notice-box">
			<?php esc_html_e( 'This is a template preview. Create the auto-reply template before attaching it to a form.', 'submission-inbox' ); ?>
		</div>

		<div class="subin-template-preview-screen">
			<div class="subin-template-preview-screen__content">
				<div class="subin-template-card__badge"><?php esc_html_e( 'Email template', 'submission-inbox' ); ?></div>
				<h2><?php echo esc_html( $template['name'] ); ?></h2>
				<p><?php echo esc_html( $template['description'] ); ?></p>
				<p class="subin-template-card__fields">
					<strong><?php esc_html_e( 'Subject:', 'submission-inbox' ); ?></strong>
					<?php echo esc_html( $template['subject'] ?? __( 'Auto-reply subject', 'submission-inbox' ) ); ?>
				</p>
				<dl class="subin-template-details">
					<dt><?php esc_html_e( 'Preheader', 'submission-inbox' ); ?></dt>
					<dd><?php echo esc_html( $template['preheader'] ?? __( 'Confirmation email preview text.', 'submission-inbox' ) ); ?></dd>
				</dl>
			</div>
			<div class="subin-template-preview-screen__visual">
				<div class="subin-template-preview subin-template-preview--large subin-auto-reply-template-preview" aria-hidden="true">
					<div class="subin-template-preview__viewport">
						<div class="subin-template-preview__scale subin-auto-reply-template-preview__scale">
							<style><?php echo esc_html( (string) ( $template['css'] ?? '' ) ); ?></style>
							<?php echo wp_kses( (string) ( $template['html'] ?? '' ), $this->email_preview_allowed_html(), array( 'http', 'https', 'mailto', 'tel' ) ); ?>
						</div>
					</div>
				</div>
			</div>
		</div>
		<?php
	}

	/**
	 * Render editor view.
	 *
	 * @param array<string,mixed>|null $template Template row.
	 * @return void
	 */
	private function render_editor( $template = null ) {
		$template = $template ? $template : $this->empty_template();
		$is_edit  = ! empty( $template['id'] );
		$editor_html = (string) ( $template['body'] ?? $template['rendered_html'] ?? '' );
		?>
		<form method="post" action="" class="subin-auto-reply-editor-form" data-subin-auto-reply-editor-form>
			<?php wp_nonce_field( self::NONCE_ACTION, self::NONCE_NAME ); ?>
			<input type="hidden" name="subin_auto_reply_save" value="1" />
			<input type="hidden" name="template_id" value="<?php echo esc_attr( (string) absint( $template['id'] ?? 0 ) ); ?>" />
			<input type="hidden" name="template_key" value="<?php echo esc_attr( (string) ( $template['template_key'] ?? '' ) ); ?>" />

			<div class="subin-auto-reply-editor">
				<a class="subin-back-link" href="<?php echo esc_url( $this->list_url() ); ?>"><?php esc_html_e( 'Back to templates', 'submission-inbox' ); ?></a>

				<div class="subin-email-editor-shell">
					<div class="subin-template-toolbar">
						<div class="subin-field subin-template-name-field">
							<label class="subin-field-label" for="subin-auto-reply-name"><?php esc_html_e( 'Template name', 'submission-inbox' ); ?></label>
							<input id="subin-auto-reply-name" class="subin-input subin-template-name" name="name" type="text" value="<?php echo esc_attr( (string) $template['name'] ); ?>" placeholder="<?php esc_attr_e( 'Request confirmation', 'submission-inbox' ); ?>" required />
						</div>

						<div class="subin-save-area">
							<div class="subin-save-status" data-subin-auto-reply-save-status aria-live="polite"></div>
							<button type="submit" class="subin-save-btn"><?php esc_html_e( 'Save template', 'submission-inbox' ); ?></button>
						</div>
					</div>

					<div class="subin-email-meta">
						<div class="subin-meta-card">
							<label class="subin-field-label" for="subin-auto-reply-subject"><?php esc_html_e( 'Email subject', 'submission-inbox' ); ?></label>
							<input id="subin-auto-reply-subject" class="subin-input" name="subject" type="text" value="<?php echo esc_attr( (string) $template['subject'] ); ?>" placeholder="<?php esc_attr_e( 'We received your request', 'submission-inbox' ); ?>" />
						</div>

						<div class="subin-meta-card">
							<label class="subin-field-label" for="subin-auto-reply-preheader"><?php esc_html_e( 'Preheader', 'submission-inbox' ); ?></label>
							<input id="subin-auto-reply-preheader" class="subin-input" name="preheader" type="text" value="<?php echo esc_attr( (string) $template['preheader'] ); ?>" placeholder="<?php esc_attr_e( 'Short preview text', 'submission-inbox' ); ?>" />
							<p class="subin-help"><?php esc_html_e( 'Optional preview text shown by some email clients.', 'submission-inbox' ); ?></p>
						</div>
					</div>

					<div class="subin-workspace-header">
						<div>
							<div class="subin-workspace-title"><?php esc_html_e( 'Email layout', 'submission-inbox' ); ?></div>
							<div class="subin-workspace-note"><?php echo esc_html( $is_edit ? __( 'Editing saved HTML template', 'submission-inbox' ) : __( 'Editing starter HTML template', 'submission-inbox' ) ); ?></div>
						</div>
						<div class="subin-preview-actions" aria-hidden="true"></div>
					</div>

					<div class="subin-auto-reply-workspace">
						<div class="subin-auto-reply-editor__main">
							<div class="subin-auto-reply-wp-editor-panel">
								<?php
								wp_editor(
									$editor_html,
									'subin_auto_reply_body_editor',
									array(
										'textarea_name' => 'body',
										'textarea_rows' => 24,
										'media_buttons' => true,
										'teeny'         => false,
										'quicktags'     => true,
										'tinymce'       => array(
											'wpautop'      => false,
											'toolbar1'     => 'formatselect,fontsizeselect,bold,italic,underline,forecolor,backcolor,alignleft,aligncenter,alignright,bullist,numlist,link,unlink,removeformat',
											'toolbar2'     => 'undo,redo,pastetext,charmap,hr,blockquote,code',
											'fontsize_formats' => '11px 12px 13px 14px 15px 16px 18px 20px 22px 24px 28px 32px 36px 42px 48px',
											'plugins'      => 'charmap colorpicker compat3x directionality hr lists media paste tabfocus textcolor wordpress wpautoresize wpdialogs wpeditimage wpemoji wpgallery wplink wptextpattern wpview',
										),
									)
								);
								?>
							</div>
						</div>

				<div class="subin-auto-reply-editor__side">
						<aside class="subin-auto-reply-side-panel subin-email-side-panel">
							<div class="subin-auto-reply-side-tabs subin-email-panel-tabs" role="tablist" aria-label="<?php esc_attr_e( 'Template tools', 'submission-inbox' ); ?>">
							<button type="button" class="subin-auto-reply-side-tab subin-email-panel-tab is-active subin-auto-reply-side-tab--active" data-subin-auto-reply-tab="variables" data-panel="variables"><?php esc_html_e( 'Variables', 'submission-inbox' ); ?></button>
						</div>
						<div class="subin-email-panel-body">
						<section id="subin-auto-reply-variables" class="subin-auto-reply-side-section subin-email-panel-view is-active" data-subin-auto-reply-panel="variables" data-panel-view="variables">
						<h2><?php esc_html_e( 'Variables', 'submission-inbox' ); ?></h2>
						<p class="description"><?php esc_html_e( 'Placeholders are saved with the template and can be replaced when auto-replies are attached to forms.', 'submission-inbox' ); ?></p>
						<?php foreach ( $this->variable_groups() as $group_label => $variables ) : ?>
							<h3 class="subin-variable-group-heading"><?php echo esc_html( $group_label ); ?></h3>
							<div class="subin-variable-list">
								<?php foreach ( $variables as $variable => $label ) : ?>
									<div class="subin-variable-item subin-variable-card">
										<div>
											<code><?php echo esc_html( $variable ); ?></code>
											<div class="subin-variable-label"><?php echo esc_html( $label ); ?></div>
										</div>
										<button type="button" class="subin-copy-shortcode" data-subin-copy="<?php echo esc_attr( $variable ); ?>"><?php esc_html_e( 'Insert', 'submission-inbox' ); ?></button>
										<span class="subin-copy-feedback" aria-live="polite"></span>
									</div>
								<?php endforeach; ?>
							</div>
						<?php endforeach; ?>
						</section>
					</div>
					</aside>
					</div>
				</div>
			</div>
		</form>
		<?php
	}

	/**
	 * Save submitted template.
	 *
	 * @return void
	 */
	private function maybe_save_template() {
		$request_method = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ?? '' ) );
		if ( 'POST' !== strtoupper( $request_method ) || empty( $_POST['subin_auto_reply_save'] ) ) {
			return;
		}

		if ( ! current_user_can( SUBIN_AdminMenu::CAPABILITY ) ) {
			$this->error_message = __( 'You do not have permission to perform this action.', 'submission-inbox' );
			return;
		}

		if ( ! isset( $_POST[ self::NONCE_NAME ] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST[ self::NONCE_NAME ] ) ), self::NONCE_ACTION ) ) {
			$this->error_message = __( 'Security check failed. Please try again.', 'submission-inbox' );
			return;
		}

		$template_id = isset( $_POST['template_id'] ) ? absint( wp_unslash( $_POST['template_id'] ) ) : 0;
		$data        = array(
			'template_key'  => $this->posted_string( 'template_key' ),
			'name'          => $this->posted_string( 'name' ),
			'status'        => AutoReplyTemplateRepository::STATUS_ACTIVE,
			'subject'       => $this->posted_string( 'subject' ),
			'body'          => $this->posted_string( 'body' ),
			'preheader'     => $this->posted_string( 'preheader' ),
			'project_json'  => '',
			'rendered_html' => $this->posted_string( 'body' ),
			'rendered_css'  => '',
		);
		$data['body'] = $data['rendered_html'];

		if ( '' === sanitize_text_field( is_scalar( $data['name'] ) ? (string) $data['name'] : '' ) ) {
			$this->error_message      = __( 'Template name is required.', 'submission-inbox' );
			$this->submitted_template = array_merge( $this->empty_template(), $data, array( 'id' => $template_id ) );
			return;
		}

		if ( $template_id > 0 ) {
			$saved = $this->templates->update( $template_id, $data );
			if ( $saved ) {
				$this->redirect_to_edit( $template_id, 'template_saved' );
			}
		} else {
			$template_id = $this->templates->create( $data );
			if ( $template_id > 0 ) {
				$this->redirect_to_edit( $template_id, 'template_created' );
			}
		}

		$this->error_message      = __( 'Template could not be saved.', 'submission-inbox' );
		$this->submitted_template = array_merge( $this->empty_template(), $data, array( 'id' => $template_id ) );
	}

	/**
	 * Save submitted rule.
	 *
	 * @return void
	 */
	private function maybe_save_rule() {
		$request_method = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ?? '' ) );
		if ( 'POST' !== strtoupper( $request_method ) || empty( $_POST['subin_auto_reply_rule_save'] ) ) {
			return;
		}

		if ( ! current_user_can( SUBIN_AdminMenu::CAPABILITY ) ) {
			$this->error_message = __( 'You do not have permission to perform this action.', 'submission-inbox' );
			return;
		}

		if ( ! isset( $_POST[ self::RULE_NONCE_NAME ] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST[ self::RULE_NONCE_NAME ] ) ), self::RULE_NONCE_ACTION ) ) {
			$this->error_message = __( 'Security check failed. Please try again.', 'submission-inbox' );
			return;
		}

		$rule_id  = isset( $_POST['rule_id'] ) ? absint( wp_unslash( $_POST['rule_id'] ) ) : 0;
		$provider = $this->rules->sanitize_provider( sanitize_key( wp_unslash( $_POST['provider'] ?? '' ) ) );
		$form_id  = sanitize_text_field( wp_unslash( $_POST['form_id'] ?? '' ) );
		if ( false !== strpos( $form_id, '|' ) ) {
			$form_parts = explode( '|', $form_id, 2 );
			$provider   = $this->rules->sanitize_provider( $form_parts[0] ?? $provider );
			$form_id    = sanitize_text_field( $form_parts[1] ?? '' );
		}
		$field_key = sanitize_text_field( wp_unslash( $_POST['visitor_email_field'] ?? '' ) );
		if ( false !== strpos( $field_key, '|' ) ) {
			$field_parts = explode( '|', $field_key, 3 );
			$provider    = $this->rules->sanitize_provider( $field_parts[0] ?? $provider );
			$form_id     = sanitize_text_field( $field_parts[1] ?? $form_id );
			$field_key   = sanitize_key( $field_parts[2] ?? '' );
		} else {
			$field_key = sanitize_key( $field_key );
		}
		$form     = $this->providers->get_form( $provider, $form_id );
		$field    = $this->providers->get_email_field( $provider, $form_id, $field_key );
		$template_id = absint( wp_unslash( $_POST['template_id'] ?? 0 ) );
		$template    = $template_id > 0 ? $this->templates->get( $template_id ) : null;
		$enabled     = ! empty( $_POST['enabled'] ) ? 1 : 0;
		$submitted   = array(
			'id'                          => $rule_id,
			'name'                        => sanitize_text_field( wp_unslash( $_POST['name'] ?? '' ) ),
			'provider'                    => $provider,
			'form_id'                     => $form_id,
			'form_name'                   => $form ? $form['label'] : '',
			'visitor_email_field'         => $field_key,
			'visitor_email_field_label'   => $field ? $field['label'] : '',
			'template_id'                 => $template_id,
			'enabled'                     => $enabled,
		);
		$this->submitted_rule = array_merge( $this->empty_rule(), $submitted );

		if ( '' === $provider ) {
			$this->set_rule_error( 'provider', __( 'Provider is required.', 'submission-inbox' ) );
			return;
		}
		if ( ! $form ) {
			$this->set_rule_error( 'form', __( 'Select the form that should send this auto-reply.', 'submission-inbox' ) );
			return;
		}
		if ( ! $field ) {
			$this->set_rule_error( 'visitor_email_field', __( 'Select the visitor email field for this form.', 'submission-inbox' ) );
			return;
		}
		if ( ! $template ) {
			$this->set_rule_error( 'template', __( 'Select an auto-reply template before saving this rule.', 'submission-inbox' ) );
			return;
		}
		if ( $enabled && $this->rules->exists_enabled_for_form( $provider, $form_id, $rule_id > 0 ? $rule_id : null ) ) {
			$this->set_rule_error( 'form', __( 'This form already has an enabled auto-reply rule.', 'submission-inbox' ) );
			return;
		}

		$data = array(
			'name'                      => $submitted['name'],
			'provider'                  => $provider,
			'form_id'                   => $form['id'],
			'form_name'                 => $form['label'],
			'visitor_email_field'       => $field['key'],
			'visitor_email_field_label' => $field['label'],
			'template_id'               => $template_id,
			'enabled'                   => $enabled,
		);

		if ( '' === $data['name'] ) {
			$this->set_rule_error( 'name', __( 'Rule name is required.', 'submission-inbox' ) );
			return;
		}

		if ( $rule_id > 0 ) {
			$saved = $this->rules->update( $rule_id, $data );
			$this->safe_admin_redirect( add_query_arg( array( 'subin_notice' => $saved ? 'rule_saved' : 'rule_not_saved' ), $this->rule_edit_url( $rule_id ) ) );
		}

		$new_id = $this->rules->create( $data );
		$this->safe_admin_redirect( add_query_arg( array( 'subin_notice' => $new_id > 0 ? 'rule_created' : 'rule_not_saved' ), $new_id > 0 ? $this->rule_edit_url( $new_id ) : $this->rules_url() ) );
	}

	/**
	 * Handle rule row actions.
	 *
	 * @return void
	 */
	private function maybe_handle_rule_action() {
		$action  = SUBIN_Request::action_key( 'subin_rule_action' );
		$rule_id = SUBIN_Request::action_absint( 'id' );

		if ( ! in_array( $action, array( 'duplicate', 'delete', 'enable', 'disable' ), true ) || $rule_id <= 0 ) {
			return;
		}

		if ( ! current_user_can( SUBIN_AdminMenu::CAPABILITY ) ) {
			$this->redirect_to_rules( 'permission_denied' );
		}

		$nonce = SUBIN_Request::action_text( '_wpnonce' );
		if ( ! wp_verify_nonce( $nonce, 'subin_auto_reply_rule_' . $action . '_' . $rule_id ) ) {
			$this->redirect_to_rules( 'security_check_failed' );
		}

		$notice = 'rule_not_saved';
		if ( 'duplicate' === $action ) {
			$notice = $this->rules->duplicate( $rule_id ) > 0 ? 'rule_duplicated' : 'rule_not_saved';
		} elseif ( 'delete' === $action ) {
			$notice = $this->rules->delete( $rule_id ) ? 'rule_deleted' : 'rule_not_saved';
		} else {
			$rule = $this->rules->find( $rule_id );
			if ( $rule ) {
				$rule['enabled'] = 'enable' === $action ? 1 : 0;
				if ( ! empty( $rule['enabled'] ) && $this->rules->exists_enabled_for_form( (string) $rule['provider'], (string) $rule['form_id'], $rule_id ) ) {
					$notice = 'rule_enabled_exists';
				} else {
					$notice = $this->rules->update( $rule_id, $rule ) ? ( 'enable' === $action ? 'rule_enabled' : 'rule_disabled' ) : 'rule_not_saved';
				}
			}
		}

		$this->redirect_to_rules( $notice );
	}

	/**
	 * Handle duplicate and delete row actions.
	 *
	 * @return void
	 */
	private function maybe_handle_row_action() {
		$action      = SUBIN_Request::action_key( 'subin_action' );
		$template_id = SUBIN_Request::action_absint( 'id' );

		if ( ! in_array( $action, array( 'duplicate', 'delete' ), true ) || $template_id <= 0 ) {
			return;
		}

		if ( ! current_user_can( SUBIN_AdminMenu::CAPABILITY ) ) {
			$this->redirect_to_list( 'permission_denied' );
		}

		$nonce = SUBIN_Request::action_text( '_wpnonce' );
		if ( ! wp_verify_nonce( $nonce, 'subin_auto_reply_' . $action . '_' . $template_id ) ) {
			$this->redirect_to_list( 'security_check_failed' );
		}

		if ( 'duplicate' === $action ) {
			$new_id = $this->templates->duplicate( $template_id );
			$this->redirect_to_list( $new_id > 0 ? 'template_duplicated' : 'template_not_duplicated' );
		}

		if ( $this->get_used_by_forms_count( $template_id ) > 0 ) {
			$this->redirect_to_list( 'template_in_use' );
		}

		$deleted = $this->templates->delete( $template_id );
		$this->redirect_to_list( $deleted ? 'template_deleted' : 'template_not_deleted' );
	}

	/**
	 * Render admin notices.
	 *
	 * @return void
	 */
	private function render_notices() {
		if ( '' !== $this->error_message ) {
			printf( '<div class="notice notice-error"><p>%s</p></div>', esc_html( $this->error_message ) );
		}

		$notice = SUBIN_Request::get_key( 'subin_notice' );
		if ( '' === $notice ) {
			return;
		}

		$messages = array(
			'template_created'       => __( 'Auto-reply template created.', 'submission-inbox' ),
			'template_saved'         => __( 'Auto-reply template saved.', 'submission-inbox' ),
			'template_duplicated'    => __( 'Auto-reply template duplicated.', 'submission-inbox' ),
			'template_not_duplicated' => __( 'Auto-reply template could not be duplicated.', 'submission-inbox' ),
			'template_deleted'       => __( 'Auto-reply template deleted.', 'submission-inbox' ),
			'template_not_deleted'   => __( 'Auto-reply template could not be deleted.', 'submission-inbox' ),
			'template_in_use'        => __( 'Auto-reply template is used by one or more forms and cannot be deleted.', 'submission-inbox' ),
			'rule_created'           => __( 'Auto-reply rule created.', 'submission-inbox' ),
			'rule_saved'             => __( 'Auto-reply rule saved.', 'submission-inbox' ),
			'rule_not_saved'         => __( 'Auto-reply rule could not be saved.', 'submission-inbox' ),
			'rule_duplicated'        => __( 'Auto-reply rule duplicated as disabled.', 'submission-inbox' ),
			'rule_deleted'           => __( 'Auto-reply rule deleted.', 'submission-inbox' ),
			'rule_enabled'           => __( 'Auto-reply rule enabled.', 'submission-inbox' ),
			'rule_disabled'          => __( 'Auto-reply rule disabled.', 'submission-inbox' ),
			'rule_enabled_exists'    => __( 'This form already has an enabled auto-reply rule.', 'submission-inbox' ),
			'permission_denied'      => __( 'You do not have permission to perform this action.', 'submission-inbox' ),
			'security_check_failed'  => __( 'Security check failed. Please try again.', 'submission-inbox' ),
		);

		if ( isset( $messages[ $notice ] ) ) {
			$type = in_array( $notice, array( 'template_not_duplicated', 'template_not_deleted', 'template_in_use', 'rule_not_saved', 'rule_enabled_exists', 'permission_denied', 'security_check_failed' ), true ) ? 'error' : 'success';
			printf( '<div class="notice notice-%1$s"><p>%2$s</p></div>', esc_attr( $type ), esc_html( $messages[ $notice ] ) );
		}
	}

	/**
	 * Get a scalar POST value.
	 *
	 * @param string $key POST key.
	 * @return string
	 */
	private function posted_string( $key ) {
		if ( ! isset( $_POST[ $key ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Caller verifies the auto-reply save nonce before reading submitted template fields.
			return '';
		}

		$value = wp_unslash( $_POST[ $key ] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Template HTML is sanitized by the repository according to the target field after the save nonce is verified.

		return is_scalar( $value ) ? (string) $value : '';
	}

	/**
	 * Get forms using a template.
	 *
	 * @param int $template_id Template id.
	 * @return int
	 */
	private function get_used_by_forms_count( $template_id ) {
		$template_id = absint( $template_id );

		if ( $template_id <= 0 ) {
			return 0;
		}

		if ( null === $this->template_usage_counts ) {
			$this->template_usage_counts = $this->build_template_usage_counts();
		}

		return absint( $this->template_usage_counts[ $template_id ] ?? 0 );
	}

	/**
	 * Get forms using a template.
	 *
	 * @param int $template_id Template id.
	 * @return array<int,array<string,mixed>>
	 */
	private function get_forms_using_template( $template_id ) {
		$template_id = absint( $template_id );

		if ( $template_id <= 0 ) {
			return array();
		}

		if ( null === $this->template_usage_counts ) {
			$this->template_usage_counts = $this->build_template_usage_counts();
		}

		return $this->template_usage_counts[ $template_id . '_forms' ] ?? array();
	}

	/**
	 * Render forms that use this template.
	 *
	 * @param array<int,array<string,mixed>> $forms Forms.
	 * @param int                           $used_count Total usage count.
	 * @return void
	 */
	private function render_used_by_forms( array $forms, $used_count ) {
		if ( empty( $forms ) ) {
			?>
			<div class="subin-template-used-by subin-template-used-by--empty">
				<span><?php esc_html_e( 'Not attached to any forms yet.', 'submission-inbox' ); ?></span>
			</div>
			<?php
			return;
		}

		$visible_forms = array_slice( $forms, 0, 4 );
		$remaining     = max( 0, absint( $used_count ) - count( $visible_forms ) );
		?>
		<div class="subin-template-used-by">
			<span class="subin-template-used-by__label"><?php esc_html_e( 'Used by', 'submission-inbox' ); ?></span>
			<div class="subin-template-used-by__chips">
				<?php foreach ( $visible_forms as $form ) : ?>
					<a class="subin-template-used-by__chip" href="<?php echo esc_url( $this->form_settings_url( absint( $form['id'] ?? 0 ) ) ); ?>">
						<?php echo esc_html( (string) ( $form['title'] ?? __( 'Untitled form', 'submission-inbox' ) ) ); ?>
					</a>
				<?php endforeach; ?>
				<?php if ( $remaining > 0 ) : ?>
					<span class="subin-template-used-by__more">
						<?php
						printf(
							/* translators: %d: Number of additional forms. */
							esc_html__( '+%d more', 'submission-inbox' ),
							absint( $remaining )
						);
						?>
					</span>
				<?php endif; ?>
			</div>
		</div>
		<?php
	}

	/**
	 * Count forms attached to each auto-reply template.
	 *
	 * @return array<int|string,mixed>
	 */
	private function build_template_usage_counts() {
		$counts = array();
		$rules  = $this->rules->list_rules(
			array(
				'per_page' => 1000,
				'offset'   => 0,
			)
		);

		foreach ( $rules as $rule ) {
			$template_id = absint( $rule['template_id'] ?? 0 );

			if ( $template_id <= 0 ) {
				continue;
			}

			if ( ! isset( $counts[ $template_id ] ) ) {
				$counts[ $template_id ]            = 0;
				$counts[ $template_id . '_forms' ] = array();
			}

			$counts[ $template_id ]++;
			$counts[ $template_id . '_forms' ][] = array(
				'id'    => absint( $rule['form_id'] ?? 0 ),
				'title' => sanitize_text_field( $rule['form_name'] ?? '' ),
			);
		}

		return $counts;
	}

	/**
	 * Build form settings URL.
	 *
	 * @param int $form_id Form id.
	 * @return string
	 */
	private function form_settings_url( $form_id ) {
		return add_query_arg(
			array(
				'page'    => 'submission-inbox-forms',
				'view'    => 'edit',
				'form_id' => absint( $form_id ),
				'tab'     => 'settings',
			),
			admin_url( 'admin.php' )
		);
	}

	/**
	 * Render safe compact email preview.
	 *
	 * @param array<string,mixed> $template Template row.
	 * @return void
	 */
	private function render_template_mini_preview( array $template ) {
		$srcdoc = $this->template_preview_srcdoc( $template );
		if ( '' !== $srcdoc ) {
			?>
			<div class="subin-template-mini-preview">
				<iframe
					<?php /* translators: %s: auto-reply template name. */ ?>
					title="<?php echo esc_attr( sprintf( __( 'Preview: %s', 'submission-inbox' ), $template['name'] ?? __( 'Auto-reply template', 'submission-inbox' ) ) ); ?>"
					sandbox=""
					loading="lazy"
					scrolling="no"
					srcdoc="<?php echo esc_attr( $srcdoc ); ?>"
				></iframe>
			</div>
			<?php
			return;
		}

		?>
		<div class="subin-template-mini-preview subin-template-mini-preview--placeholder" aria-hidden="true">
			<strong><?php esc_html_e( 'No preview available', 'submission-inbox' ); ?></strong>
			<span><?php esc_html_e( 'Edit template to add content.', 'submission-inbox' ); ?></span>
		</div>
		<?php
	}

	/**
	 * Build sandboxed srcdoc for a real auto-reply preview.
	 *
	 * @param array<string,mixed> $template Template row.
	 * @return string
	 */
	private function template_preview_srcdoc( array $template ) {
		$html = (string) ( $template['rendered_html'] ?? $template['body'] ?? '' );

		if ( '' === trim( $html ) ) {
			return '';
		}

		return wp_kses(
			$html,
			AutoReplyTemplateRepository::allowed_email_html(),
			array( 'http', 'https', 'mailto', 'tel' )
		);
	}

	/**
	 * Build a new editor template from selected starter.
	 *
	 * @return array<string,mixed>
	 */
	private function editor_template_from_request() {
		if ( $this->submitted_template ) {
			return $this->submitted_template;
		}

		$key     = SUBIN_Request::get_key( 'template_key' );
		$starter = $this->library->get( $key );

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

		return array_merge(
			$this->empty_template(),
			array(
				'template_key'  => $starter['key'],
				'name'          => $starter['name'],
				'subject'       => $starter['subject'],
				'preheader'     => $starter['preheader'],
				'body'          => $starter['html'],
				'rendered_html' => $starter['html'],
				'rendered_css'  => '',
				'project_json'  => '',
			)
		);
	}

	/**
	 * Get supported variables grouped by use.
	 *
	 * @return array<string,array<string,string>>
	 */
	private function variable_groups() {
		return array(
			__( 'General', 'submission-inbox' ) => array(
				'{site_name}'       => __( 'Site name', 'submission-inbox' ),
				'{form_name}'       => __( 'Form name', 'submission-inbox' ),
				'{submission_date}' => __( 'Submission date', 'submission-inbox' ),
			),
			__( 'Lead', 'submission-inbox' )    => array(
				'{lead_id}'       => __( 'Lead ID', 'submission-inbox' ),
				'{visitor_email}' => __( 'Visitor email', 'submission-inbox' ),
			),
			__( 'Fields', 'submission-inbox' )  => array(
				'{field:name}'    => __( 'Name field', 'submission-inbox' ),
				'{field:email}'   => __( 'Email field', 'submission-inbox' ),
				'{field:message}' => __( 'Message field', 'submission-inbox' ),
			),
		);
	}

	/**
	 * Allowed HTML for gallery previews.
	 *
	 * @return array<string,array<string,bool>>
	 */
	private function email_preview_allowed_html() {
		$attrs = array(
			'class'                    => true,
			'data-subin-component'       => true,
			'data-subin-email-component' => true,
			'data-subin-icon-align'      => true,
			'data-subin-icon-bg'         => true,
			'data-subin-icon-color'      => true,
			'data-subin-icon-key'        => true,
			'data-subin-icon-label'      => true,
			'data-subin-icon-radius'     => true,
			'data-subin-icon-size'       => true,
			'style'                    => true,
		);

		return array(
			'a'      => array_merge(
				$attrs,
				array(
					'href'   => true,
					'rel'    => true,
					'target' => true,
					'title'  => true,
				)
			),
			'b'      => array(),
			'br'     => array(),
			'div'    => $attrs,
			'em'     => array(),
			'h1'     => $attrs,
			'h2'     => $attrs,
			'h3'     => $attrs,
			'hr'     => array(),
			'i'      => array(),
			'img'    => array_merge(
				$attrs,
				array(
					'alt'    => true,
					'height' => true,
					'src'    => true,
					'title'  => true,
					'width'  => true,
				)
			),
			'li'     => $attrs,
			'ol'     => $attrs,
			'p'      => $attrs,
			'span'   => $attrs,
			'svg'    => array(
				'aria-hidden'      => true,
				'class'            => true,
				'fill'             => true,
				'focusable'        => true,
				'height'           => true,
				'role'             => true,
				'stroke'           => true,
				'stroke-linecap'   => true,
				'stroke-linejoin'  => true,
				'stroke-width'     => true,
				'viewbox'          => true,
				'viewBox'          => true,
				'width'            => true,
				'xmlns'            => true,
			),
			'path'   => array(
				'd' => true,
			),
			'circle' => array(
				'cx' => true,
				'cy' => true,
				'r'  => true,
			),
			'line'   => array(
				'x1' => true,
				'x2' => true,
				'y1' => true,
				'y2' => true,
			),
			'rect'   => array(
				'height' => true,
				'rx'     => true,
				'ry'     => true,
				'width'  => true,
				'x'      => true,
				'y'      => true,
			),
			'polyline' => array(
				'points' => true,
			),
			'polygon' => array(
				'points' => true,
			),
			'strong' => array(),
			'table'  => $attrs,
			'tbody'  => $attrs,
			'td'     => $attrs,
			'tr'     => $attrs,
			'ul'     => $attrs,
		);
	}

	/**
	 * Get empty template defaults.
	 *
	 * @return array<string,mixed>
	 */
	private function empty_template() {
		return array(
			'id'            => 0,
			'template_key'  => '',
			'name'          => '',
			'status'        => AutoReplyTemplateRepository::STATUS_ACTIVE,
			'subject'       => '',
			'body'          => '',
			'preheader'     => '',
			'project_json'  => '',
			'rendered_html' => '',
			'rendered_css'  => '',
		);
	}

	/**
	 * Format a database date.
	 *
	 * @param string $date Date.
	 * @return string
	 */
	private function format_date( $date ) {
		if ( '' === $date || '0000-00-00 00:00:00' === $date ) {
			return __( 'Unknown', 'submission-inbox' );
		}

		return mysql2date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $date );
	}

	/**
	 * Current main tab.
	 *
	 * @param string $view Template view.
	 * @return string
	 */
	private function current_tab( $view = '' ) {
		if ( in_array( $view, array( 'new', 'preview', 'editor', 'edit' ), true ) ) {
			return 'templates';
		}

		$tab = SUBIN_Request::get_key( 'subin_auto_replies_tab', 'rules' );

		return in_array( $tab, array( 'rules', 'templates' ), true ) ? $tab : 'rules';
	}

	/**
	 * Empty rule values.
	 *
	 * @return array<string,mixed>
	 */
	private function empty_rule() {
		return array(
			'id'                        => 0,
			'name'                      => '',
			'provider'                  => AutoReplyRuleRepository::PROVIDER_SUBMISSION_INBOX_FORM,
			'form_id'                   => '',
			'form_name'                 => '',
			'visitor_email_field'       => '',
			'visitor_email_field_label' => '',
			'template_id'               => 0,
			'enabled'                   => 1,
		);
	}

	/**
	 * Build form choices across providers.
	 *
	 * @return array<int,array<string,string>>
	 */
	private function all_provider_form_choices() {
		$choices = array();
		foreach ( $this->providers->providers() as $provider ) {
			if ( empty( $provider['forms'] ) ) {
				continue;
			}

			$provider_key   = sanitize_key( (string) $provider['key'] );
			$provider_label = sanitize_text_field( (string) $provider['label'] );
			foreach ( $this->providers->list_forms( $provider_key ) as $form ) {
				$choices[] = array(
					'value' => $provider_key . '|' . sanitize_text_field( (string) ( $form['id'] ?? '' ) ),
					'provider' => $provider_key,
					'label' => sprintf(
						/* translators: 1: provider label, 2: form label. */
						__( '%1$s - %2$s', 'submission-inbox' ),
						$provider_label,
						sanitize_text_field( (string) ( $form['label'] ?? '' ) )
					),
				);
			}
		}

		return $choices;
	}

	/**
	 * Build email field choices across providers.
	 *
	 * @return array<int,array<string,string>>
	 */
	private function all_provider_email_field_choices() {
		$choices = array();
		foreach ( $this->providers->providers() as $provider ) {
			if ( empty( $provider['forms'] ) ) {
				continue;
			}

			$provider_key   = sanitize_key( (string) $provider['key'] );
			$provider_label = sanitize_text_field( (string) $provider['label'] );
			foreach ( $this->providers->list_forms( $provider_key ) as $form ) {
				$form_id    = sanitize_text_field( (string) ( $form['id'] ?? '' ) );
				$form_label = sanitize_text_field( (string) ( $form['label'] ?? $form_id ) );
				if ( '' === $form_id ) {
					continue;
				}

				foreach ( $this->providers->list_email_fields( $provider_key, $form_id ) as $field ) {
					$choices[] = array(
						'value' => $provider_key . '|' . $form_id . '|' . sanitize_key( $field['key'] ?? '' ),
						'provider' => $provider_key,
						'form_value' => $provider_key . '|' . $form_id,
						'label' => sprintf(
							/* translators: 1: provider label, 2: form label, 3: email field label. */
							__( '%1$s - %2$s - %3$s', 'submission-inbox' ),
							$provider_label,
							$form_label,
							sanitize_text_field( (string) ( $field['label'] ?? '' ) )
						),
					);
				}
			}
		}

		return $choices;
	}

	/**
	 * Build rule status display details.
	 *
	 * @param array<string,mixed>      $rule Rule row.
	 * @param array<string,mixed>|null $template Template row.
	 * @return array{label:string,type:string}
	 */
	private function rule_status_details( array $rule, $template ) {
		if ( empty( $rule['form_id'] ) || empty( $rule['visitor_email_field'] ) || empty( $template ) ) {
			return array(
				'label' => __( 'Needs setup', 'submission-inbox' ),
				'type'  => 'warning',
			);
		}

		if ( empty( $rule['enabled'] ) ) {
			return array(
				'label' => __( 'Disabled', 'submission-inbox' ),
				'type'  => 'muted',
			);
		}

		return array(
			'label' => __( 'Enabled', 'submission-inbox' ),
			'type'  => 'success',
		);
	}

	/**
	 * List URL.
	 *
	 * @return string
	 */
	private function list_url() {
		return $this->templates_url();
	}

	/**
	 * Rules URL.
	 *
	 * @return string
	 */
	private function rules_url() {
		return add_query_arg(
			array(
				'page'                 => self::PAGE_SLUG,
				'subin_auto_replies_tab' => 'rules',
			),
			admin_url( 'admin.php' )
		);
	}

	/**
	 * Templates URL.
	 *
	 * @return string
	 */
	private function templates_url() {
		return add_query_arg(
			array(
				'page'                 => self::PAGE_SLUG,
				'subin_auto_replies_tab' => 'templates',
			),
			admin_url( 'admin.php' )
		);
	}

	/**
	 * Rule editor URL.
	 *
	 * @param int $rule_id Rule id.
	 * @return string
	 */
	private function rule_edit_url( $rule_id ) {
		$args = array(
			'rule_view'            => $rule_id > 0 ? 'edit' : 'new',
			'subin_auto_replies_tab' => 'rules',
		);
		if ( $rule_id > 0 ) {
			$args['id'] = absint( $rule_id );
		}

		return add_query_arg( $args, $this->rules_url() );
	}

	/**
	 * Rule row action URL.
	 *
	 * @param string $action Action.
	 * @param int    $rule_id Rule id.
	 * @return string
	 */
	private function rule_action_url( $action, $rule_id ) {
		$rule_id = absint( $rule_id );
		$action  = sanitize_key( $action );
		$url     = add_query_arg(
			array(
				'subin_rule_action'    => $action,
				'id'                 => $rule_id,
				'subin_auto_replies_tab' => 'rules',
			),
			$this->rules_url()
		);

		return wp_nonce_url( $url, 'subin_auto_reply_rule_' . $action . '_' . $rule_id );
	}

	/**
	 * New template URL.
	 *
	 * @return string
	 */
	private function new_url() {
		return add_query_arg( array( 'view' => 'new' ), $this->list_url() );
	}

	/**
	 * Starter editor URL.
	 *
	 * @param string $template_key Starter template key.
	 * @return string
	 */
	private function starter_editor_url( $template_key ) {
		return add_query_arg(
			array(
				'view'         => 'editor',
				'template_key' => sanitize_key( $template_key ),
			),
			$this->list_url()
		);
	}

	/**
	 * Starter preview URL.
	 *
	 * @param string $template_key Starter template key.
	 * @return string
	 */
	private function starter_preview_url( $template_key ) {
		return add_query_arg(
			array(
				'view'         => 'preview',
				'template_key' => sanitize_key( $template_key ),
			),
			$this->list_url()
		);
	}

	/**
	 * Edit template URL.
	 *
	 * @param int $template_id Template id.
	 * @return string
	 */
	private function edit_url( $template_id ) {
		return add_query_arg(
			array(
				'view' => 'edit',
				'id'   => absint( $template_id ),
			),
			$this->list_url()
		);
	}

	/**
	 * Row action URL.
	 *
	 * @param string $action Action.
	 * @param int    $template_id Template id.
	 * @return string
	 */
	private function action_url( $action, $template_id ) {
		$template_id = absint( $template_id );
		$action      = sanitize_key( $action );
		$url         = add_query_arg(
			array(
				'subin_action' => $action,
				'id'         => $template_id,
			),
			$this->list_url()
		);

		return wp_nonce_url( $url, 'subin_auto_reply_' . $action . '_' . $template_id );
	}

	/**
	 * Redirect to list screen.
	 *
	 * @param string $notice Notice key.
	 * @return void
	 */
	private function redirect_to_list( $notice ) {
		$this->safe_admin_redirect(
			add_query_arg(
				array( 'subin_notice' => sanitize_key( $notice ) ),
				$this->list_url()
			)
		);
	}

	/**
	 * Redirect to rules list.
	 *
	 * @param string $notice Notice key.
	 * @return void
	 */
	private function redirect_to_rules( $notice ) {
		$this->safe_admin_redirect(
			add_query_arg(
				array( 'subin_notice' => sanitize_key( $notice ) ),
				$this->rules_url()
			)
		);
	}

	/**
	 * Redirect to edit screen.
	 *
	 * @param int    $template_id Template id.
	 * @param string $notice Notice key.
	 * @return void
	 */
	private function redirect_to_edit( $template_id, $notice ) {
		$this->safe_admin_redirect(
			add_query_arg(
				array( 'subin_notice' => sanitize_key( $notice ) ),
				$this->edit_url( $template_id )
			)
		);
	}

	/**
	 * Redirect from an admin page callback without header warnings.
	 *
	 * @param string $url Target URL.
	 * @return void
	 */
	private function safe_admin_redirect( $url ) {
		$url = esc_url_raw( $url );
		if ( ! headers_sent() ) {
			wp_safe_redirect( $url );
			exit;
		}

		printf(
			'<script>window.location.href=%1$s;</script><noscript><meta http-equiv="refresh" content="0;url=%2$s" /></noscript>',
			wp_json_encode( $url ),
			esc_url( $url )
		);
		exit;
	}
}
