<?php
/**
 * Report Issue AJAX handler for SiteStaffr admin.
 *
 * @package    SiteStaffr
 * @subpackage SiteStaffr/admin/traits
 * @since      1.0.3
 */

if ( ! defined( 'WPINC' ) ) {
	die;
}

/**
 * Encapsulates the report-issue AJAX action.
 */
trait SiteStaffr_Admin_Report_Issue_Ajax_Trait {

	/**
	 * Valid issue types for report-issue submissions.
	 *
	 * @since 1.0.3
	 * @var array
	 */
	private static $report_issue_types = array(
		'incorrect_information',
		'inappropriate_response',
		'cut_off_early',
		'lost_context',
		'other',
	);

	/**
	 * AJAX handler to report an issue with a conversation.
	 *
	 * Validates input, assembles payload from DB, and fires
	 * a POST to the middleware report-issue endpoint.
	 * Returns success regardless of middleware response (fire and forget).
	 *
	 * @since 1.0.3
	 * @return void
	 */
	public function ajax_report_issue() {
		if ( ! check_ajax_referer( 'sitestaffr_ajax_nonce', 'nonce', false ) ) {
			SiteStaffr_Logger::legacy( 'SiteStaffr Admin: Report issue nonce verification failed' );
			wp_send_json_error( array( 'message' => __( 'Security check failed. Please refresh the page and try again.', 'sitestaffr' ) ) );
			return;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			SiteStaffr_Logger::legacy( 'SiteStaffr Admin: Report issue permission denied' );
			wp_send_json_error( array( 'message' => __( 'You do not have permission to do this.', 'sitestaffr' ) ) );
			return;
		}

		$call_id    = isset( $_POST['call_id'] ) ? absint( wp_unslash( $_POST['call_id'] ) ) : 0;
		$issue_type = isset( $_POST['issue_type'] ) ? sanitize_key( wp_unslash( $_POST['issue_type'] ) ) : '';
		$note       = isset( $_POST['note'] ) ? sanitize_textarea_field( wp_unslash( $_POST['note'] ) ) : '';

		if ( $call_id <= 0 ) {
			wp_send_json_error( array( 'message' => __( 'Invalid conversation ID.', 'sitestaffr' ) ) );
			return;
		}

		if ( ! in_array( $issue_type, self::$report_issue_types, true ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid issue type.', 'sitestaffr' ) ) );
			return;
		}

		// Verify the call exists.
		$call = SiteStaffr_Call_Manager::get_call_by_id( $call_id );
		if ( ! $call ) {
			wp_send_json_error( array( 'message' => __( 'Conversation not found.', 'sitestaffr' ) ) );
			return;
		}

		// Consent checkbox state — pre-checked in the modal; '1' means include the link.
		$include_link = isset( $_POST['include_link'] ) && '1' === sanitize_text_field( wp_unslash( $_POST['include_link'] ) );

		$payload = self::build_report_issue_payload( $call, $call_id, $issue_type, $note, $include_link );

		// Fire and forget to middleware (with HMAC signing).
		$middleware_url = defined( 'SITESTAFFR_MIDDLEWARE_URL' ) ? SITESTAFFR_MIDDLEWARE_URL : '';
		$api_secret     = get_option( 'sitestaffr_site_api_secret', get_option( 'sitestaffr_api_secret', '' ) );

		if ( ! empty( $middleware_url ) && ! empty( $api_secret ) ) {
			$payload_json    = wp_json_encode( $payload );
			$timestamp       = (string) time();
			$payload_to_sign = $timestamp . '.' . $payload_json;
			$signature_raw   = hash_hmac( 'sha256', $payload_to_sign, $api_secret, true );
			$signature_b64   = base64_encode( $signature_raw );

			wp_remote_post(
				rtrim( $middleware_url, '/' ) . '/api/v1/report-issue',
				array(
					'timeout'  => 5,
					'blocking' => false,
					'headers'  => array(
						'Content-Type'           => 'application/json',
						'X-SiteStaffr-Signature' => $signature_b64,
						'X-SiteStaffr-Timestamp' => $timestamp,
						'X-SiteStaffr-Site-URL'  => esc_url_raw( get_site_url() ),
					),
					'body'     => $payload_json,
				)
			);
		}

		wp_send_json_success( array( 'message' => __( 'Issue reported successfully. Thank you for your feedback!', 'sitestaffr' ) ) );
	}

	/**
	 * Assemble the report-issue payload sent to the middleware.
	 *
	 * With $include_link true and a signing secret configured, adds an expiring
	 * HMAC view-link to this site's own transcript viewer (transcript_url) plus
	 * its expiry timestamp (transcript_url_expires). The presence of
	 * transcript_url IS the consent record — nothing else is stored anywhere.
	 * Transcript content never leaves WordPress; only the URL travels (HIPAA).
	 *
	 * @since 1.31.0
	 * @param  object $call         Call record (session_id is read).
	 * @param  int    $call_id      Call ID.
	 * @param  string $issue_type   Validated issue type.
	 * @param  string $note         Sanitized note.
	 * @param  bool   $include_link Consent checkbox state.
	 * @return array                Payload for POST /api/v1/report-issue.
	 */
	public static function build_report_issue_payload( $call, $call_id, $issue_type, $note, $include_link ) {
		$settings = get_option( 'sitestaffr_settings', array() );
		$payload  = array(
			'account_id'         => sanitize_text_field( get_option( 'sitestaffr_account_id', '' ) ),
			'installation_id'    => sanitize_text_field( get_option( 'sitestaffr_installation_id', '' ) ),
			'call_id'            => $call_id,
			'session_id'         => isset( $call->session_id ) ? $call->session_id : '',
			'issue_type'         => $issue_type,
			'note'               => $note,
			'plugin_version'     => defined( 'SITESTAFFR_VERSION' ) ? SITESTAFFR_VERSION : '',
			'site_url'           => esc_url_raw( get_site_url() ),
			'business_name'      => sanitize_text_field( ! empty( $settings['business_name'] ) ? $settings['business_name'] : '' ),
			'notification_email' => sanitize_email( ! empty( $settings['notification_email'] ) ? $settings['notification_email'] : get_option( 'admin_email', '' ) ),
		);

		if ( $include_link ) {
			$transcript_url = SiteStaffr_Magic_Link::generate_scoped_url(
				'transcript-view',
				$call_id,
				'sitestaffr_transcript',
				14 * DAY_IN_SECONDS
			);

			if ( '' !== $transcript_url ) {
				$query = array();
				parse_str( (string) wp_parse_url( $transcript_url, PHP_URL_QUERY ), $query );

				$payload['transcript_url']         = $transcript_url;
				$payload['transcript_url_expires'] = isset( $query['exp'] ) ? (int) $query['exp'] : 0;
			}
		}

		return $payload;
	}
}
