<?php
/**
 * GDPR export/erase integration.
 *
 * @package MailDoctor
 */

namespace MailDoctor;

use MailDoctor\Helpers\Formatter;

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

/**
 * Registers personal data exporters and erasers.
 */
class Privacy {

	/**
	 * Export/erase batch size.
	 */
	const EXPORT_BATCH = 50;

	/**
	 * Hook into WordPress privacy APIs.
	 *
	 * @return void
	 */
	public static function init(): void {
		add_filter( 'wp_privacy_personal_data_exporters', array( __CLASS__, 'register_exporter' ) );
		add_filter( 'wp_privacy_personal_data_erasers', array( __CLASS__, 'register_eraser' ) );
	}

	/**
	 * Register exporter callback.
	 *
	 * @param array<string, mixed> $exporters Existing exporters.
	 * @return array<string, mixed>
	 */
	public static function register_exporter( array $exporters ): array {
		$exporters['mail-doctor-logs'] = array(
			'exporter_friendly_name' => __( 'Mail Doctor Email Logs', 'mail-doctor' ),
			'callback'               => array( __CLASS__, 'export_personal_data' ),
		);

		return $exporters;
	}

	/**
\t * Register eraser callback.
	 *
	 * @param array<string, mixed> $erasers Existing erasers.
	 * @return array<string, mixed>
	 */
	public static function register_eraser( array $erasers ): array {
		$erasers['mail-doctor-logs'] = array(
			'eraser_friendly_name' => __( 'Mail Doctor Email Logs', 'mail-doctor' ),
			'callback'             => array( __CLASS__, 'erase_personal_data' ),
		);

		return $erasers;
	}

	/**
	 * Export personal data for a given email address.
	 *
	 * @param string $email_address Email address.
	 * @param int    $page          Page number.
	 * @return array<string, mixed>
	 */
	public static function export_personal_data( string $email_address, int $page ): array {
		$email_address = sanitize_email( $email_address );

		if ( '' === $email_address ) {
			return self::empty_export();
		}

		$results = Logger::find_logs_by_recipient( $email_address, $page, self::EXPORT_BATCH );

		$items = array();

		foreach ( (array) $results['items'] as $row ) {
			$payload = json_decode( $row['payload'] ?? '', true );
			$meta    = is_array( $payload['meta'] ?? null ) ? $payload['meta'] : array();

			$recipients = array();
			if ( ! empty( $meta['recipients_plain'] ) && is_array( $meta['recipients_plain'] ) ) {
				$recipients = array_map( 'sanitize_email', $meta['recipients_plain'] );
			} elseif ( ! empty( $meta['recipients_hash'] ) && is_array( $meta['recipients_hash'] ) ) {
				$recipients = $meta['recipients_hash'];
			} else {
				$recipients = array_filter( array_map( 'trim', explode( ',', (string) ( $row['to_email'] ?? '' ) ) ) );
			}

			$history = array();
			if ( isset( $payload['retry']['history'] ) && is_array( $payload['retry']['history'] ) ) {
				foreach ( $payload['retry']['history'] as $entry ) {
					if ( ! isset( $entry['status'] ) ) {
						continue;
					}
					$history[] = sprintf(
						/* translators: 1: status, 2: occurred at */
						__( '%1$s at %2$s', 'mail-doctor' ),
						ucfirst( (string) $entry['status'] ),
						isset( $entry['occurred_at_gmt'] ) ? Formatter::local_time( $entry['occurred_at_gmt'] ) : ''
					);
				}
			}

			$data = array(
				array(
					'name'  => __( 'Log ID', 'mail-doctor' ),
					'value' => (int) $row['id'],
				),
				array(
					'name'  => __( 'Created', 'mail-doctor' ),
					'value' => Formatter::local_time( $row['created_at'] ),
				),
				array(
					'name'  => __( 'Event', 'mail-doctor' ),
					'value' => $row['event'] ?? '',
				),
				array(
					'name'  => __( 'Recipients', 'mail-doctor' ),
					'value' => implode( ', ', array_filter( $recipients ) ),
				),
				array(
					'name'  => __( 'Subject', 'mail-doctor' ),
					'value' => $row['subject'] ?? '',
				),
				array(
					'name'  => __( 'Status', 'mail-doctor' ),
					'value' => $row['status'] ?? '',
				),
			);

			if ( ! empty( $history ) ) {
				$data[] = array(
					'name'  => __( 'Retry History', 'mail-doctor' ),
					'value' => implode( '; ', $history ),
				);
			}

			$items[] = array(
				'group_id'    => 'mail-doctor-logs',
				'group_label' => __( 'Mail Doctor Email Logs', 'mail-doctor' ),
				'item_id'     => 'mail-doctor-log-' . (int) $row['id'],
				'data'        => $data,
			);
		}

		$done = count( $results['items'] ) < self::EXPORT_BATCH;

		return array(
			'data' => $items,
			'done' => $done,
		);
	}

	/**
	 * Erase personal data for an email address.
	 *
	 * @param string $email_address Email to erase.
	 * @param int    $page          Page number (unused, single pass).
	 * @return array<string, mixed>
	 */
	public static function erase_personal_data( string $email_address, int $page ): array {
		$email_address = sanitize_email( $email_address );

		if ( '' === $email_address ) {
			return self::empty_erase();
		}

		$updated = Logger::anonymize_recipient( $email_address );

		return array(
			'items_removed'  => $updated > 0,
			'items_retained' => false,
			'messages'       => array(),
			'done'           => true,
		);
	}

	/**
	 * Empty exporter response.
	 *
	 * @return array<string, mixed>
	 */
	protected static function empty_export(): array {
		return array(
			'data' => array(),
			'done' => true,
		);
	}

	/**
	 * Empty eraser response.
	 *
	 * @return array<string, mixed>
	 */
	protected static function empty_erase(): array {
		return array(
			'items_removed'  => false,
			'items_retained' => false,
			'messages'       => array(),
			'done'           => true,
		);
	}
}
