<?php
/**
 * Instant alerts + digest. Free channel is wp_mail only; Pro layers
 * Slack/webhook onto the post-throttle `ffrd_alert` action.
 *
 * @package Form_Flight_Recorder
 */

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

/**
 * Alerts.
 */
class Ffrd_Alerts {

	/**
	 * Container.
	 *
	 * @var Ffrd_Plugin
	 */
	private $plugin;

	/**
	 * Constructor.
	 *
	 * @param Ffrd_Plugin $plugin Container.
	 */
	public function __construct( $plugin ) {
		$this->plugin = $plugin;
		add_action( 'ffrd_event', array( $this, 'maybe_instant_alert' ), 10, 5 );
	}

	/**
	 * Instant email on the first problem per form per 24h.
	 *
	 * @param string $type     Event type.
	 * @param string $ref      Ref.
	 * @param string $severity Severity.
	 * @param array  $data     Payload.
	 * @param int    $id       Event id.
	 */
	public function maybe_instant_alert( $type, $ref, $severity, $data, $id ) {
		unset( $severity, $id );

		if ( ! in_array( $type, array( 'notification_missing', 'notification_failed', 'form_silent', 'presence_missing' ), true ) ) {
			return;
		}
		$settings = $this->plugin->settings();
		if ( empty( $settings['instant_alerts'] ) ) {
			return;
		}

		$form_key = isset( $data['form_key'] ) ? $data['form_key'] : $ref;
		$events   = $this->plugin->get( 'events' );

		$throttle_ref = 'i-' . $type . '-' . $form_key;
		$last         = $events->latest( 'alert_sent', $throttle_ref );
		if ( $last && ( time() - strtotime( $last->created_at . ' UTC' ) ) < DAY_IN_SECONDS ) {
			return;
		}

		$title = isset( $data['title'] ) && '' !== $data['title'] ? $data['title'] : $form_key;
		$site  = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );

		$lines = array();
		switch ( $type ) {
			case 'notification_missing':
				/* translators: %s: form title. */
				$subject = sprintf( __( '[%1$s] Form "%2$s": a submission produced NO notification', 'form-flight-recorder' ), $site, $title );
				$lines[] = __( 'A form submission completed, at least one notification was expected, and no email was generated at all. Nobody was told about this lead.', 'form-flight-recorder' );
				$lines[] = '';
				$lines[] = __( 'If this form intentionally sends no email, mark it "off" on the Forms tab and this alert stops.', 'form-flight-recorder' );
				break;
			case 'notification_failed':
				/* translators: %s: form title. */
				$subject = sprintf( __( '[%1$s] Form "%2$s": notification email FAILED to send', 'form-flight-recorder' ), $site, $title );
				$lines[] = __( 'The notification email was generated but the mail transport rejected it:', 'form-flight-recorder' );
				foreach ( (array) ( isset( $data['errors'] ) ? $data['errors'] : array() ) as $error ) {
					$lines[] = '- ' . $error;
				}
				break;
			case 'form_silent':
				/* translators: %s: form title. */
				$subject = sprintf( __( '[%1$s] Form "%2$s" has gone silent', 'form-flight-recorder' ), $site, $title );
				$lines[] = sprintf(
					/* translators: 1: submissions per week, 2: hours silent. */
					__( 'This form normally gets ~%1$s submissions/week but nothing has arrived for %2$d hours. The form may be broken on the page (a plugin/theme update, a JS error, or an over-eager spam filter).', 'form-flight-recorder' ),
					isset( $data['per_week'] ) ? (string) $data['per_week'] : '?',
					isset( $data['hours_silent'] ) ? (int) $data['hours_silent'] : 0
				);
				break;
			default: // presence_missing.
				/* translators: %s: form title. */
				$subject = sprintf( __( '[%1$s] Form "%2$s" no longer renders on its page', 'form-flight-recorder' ), $site, $title );
				$lines[] = sprintf(
					/* translators: %s: page URL. */
					__( 'The page %s no longer contains this form\'s markup. An update may have removed or broken it.', 'form-flight-recorder' ),
					isset( $data['url'] ) ? $data['url'] : ''
				);
				break;
		}

		$lines[] = '';
		$lines[] = __( 'Cockpit:', 'form-flight-recorder' ) . ' ' . admin_url( 'admin.php?page=ffrd' );

		$to = sanitize_email( $settings['digest_email'] );
		if ( ! $to ) {
			$to = get_option( 'admin_email' );
		}
		wp_mail( $to, $subject, implode( "\n", $lines ) );

		$events->insert(
			'alert_sent',
			$throttle_ref,
			'info',
			array(
				'kind'     => $type,
				'form_key' => $form_key,
			)
		);

		/**
		 * Fires after an instant alert passed the throttle (Pro channels).
		 *
		 * @param string $type     Event type.
		 * @param string $form_key Form key.
		 * @param array  $data     Payload.
		 */
		do_action( 'ffrd_alert', $type, $form_key, $data );
	}

	/**
	 * Send the digest when the cadence says so and there is something to say.
	 */
	public function maybe_send_digest() {
		$settings = $this->plugin->settings();
		$cadence  = $settings['digest'];

		if ( ! in_array( $cadence, array( 'daily', 'weekly' ), true ) ) {
			return;
		}

		$events = $this->plugin->get( 'events' );
		$last   = $events->latest( 'alert_sent', 'digest' );
		$gap    = ( 'daily' === $cadence ) ? 20 * HOUR_IN_SECONDS : 6.5 * DAY_IN_SECONDS;
		if ( $last && ( time() - strtotime( $last->created_at . ' UTC' ) ) < $gap ) {
			return;
		}

		$counts = $this->plugin->get( 'reconciler' )->counts();
		if ( 0 === $counts['submissions_7d'] && 0 === $counts['missing_7d'] && 0 === $counts['failed_7d'] && empty( $counts['silent'] ) ) {
			return;
		}

		$lines   = array();
		$lines[] = __( 'Form Flight Recorder — your forms, reconciled.', 'form-flight-recorder' );
		$lines[] = '';
		$lines[] = sprintf(
			/* translators: 1: submissions in 7 days, 2: missing count, 3: failed count. */
			__( 'Last 7 days: %1$d submissions · %2$d produced NO notification · %3$d notification(s) failed at the transport', 'form-flight-recorder' ),
			$counts['submissions_7d'],
			$counts['missing_7d'],
			$counts['failed_7d']
		);

		if ( $counts['silent'] ) {
			$lines[] = '';
			$lines[] = __( 'FORMS GONE SILENT:', 'form-flight-recorder' );
			foreach ( $counts['silent'] as $silent ) {
				$lines[] = sprintf(
					'- %1$s (~%2$s/week, silent %3$dh)',
					isset( $silent['title'] ) ? $silent['title'] : '?',
					isset( $silent['per_week'] ) ? (string) $silent['per_week'] : '?',
					isset( $silent['hours_silent'] ) ? (int) $silent['hours_silent'] : 0
				);
			}
		}

		$lines[] = '';
		$lines[] = __( 'Cockpit:', 'form-flight-recorder' ) . ' ' . admin_url( 'admin.php?page=ffrd' );

		$subject = sprintf(
			/* translators: 1: site name, 2: number of problems. */
			__( '[%1$s] Form Flight Recorder digest — %2$d to review', 'form-flight-recorder' ),
			wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ),
			(int) ( $counts['missing_7d'] + $counts['failed_7d'] + count( $counts['silent'] ) )
		);

		$to = sanitize_email( $settings['digest_email'] );
		if ( ! $to ) {
			$to = get_option( 'admin_email' );
		}

		/**
		 * Filters the digest body before sending.
		 *
		 * @param string $body   Plain-text body.
		 * @param array  $counts Counts.
		 */
		$body = apply_filters( 'ffrd_digest_body', implode( "\n", $lines ), $counts );

		wp_mail( $to, $subject, $body );

		$events->insert(
			'alert_sent',
			'digest',
			'info',
			array(
				'cadence' => $cadence,
				'missing' => (int) $counts['missing_7d'],
				'silent'  => count( $counts['silent'] ),
			)
		);
	}
}
