<?php
/**
 * SMS marketing consent checks (TCPA / GDPR).
 *
 * @package CartCue
 */

namespace CartCue;

defined( 'ABSPATH' ) || exit;

final class SmsConsent {

	public const USER_META_KEY  = 'cartcue_sms_consent';
	public const ORDER_META_KEY = '_cartcue_sms_consent';

	public static function default_settings(): array {
		return [
			'sms_consent_enabled'         => '0',
			'sms_consent_enforce'         => '1',
			'sms_consent_checkout'        => '0',
			'sms_consent_checkout_blocks' => '0',
			'sms_consent_text'            => __( 'I agree to receive marketing text messages from {{shop.name}}.', 'cartcue-sales-automation' ),
		];
	}

	public static function get_settings(): array {
		$stored = get_option( 'cartcue_settings', [] );
		if ( ! is_array( $stored ) ) {
			$stored = [];
		}
		return array_merge( self::default_settings(), $stored );
	}

	public static function is_enabled(): bool {
		$s = self::get_settings();
		return '1' === (string) ( $s['sms_consent_enabled'] ?? '0' );
	}

	public static function is_enforced(): bool {
		if ( ! self::is_enabled() ) {
			return false;
		}
		$s = self::get_settings();
		return '1' === (string) ( $s['sms_consent_enforce'] ?? '1' );
	}

	public static function consent_label(): string {
		$s    = self::get_settings();
		$text = (string) ( $s['sms_consent_text'] ?? '' );
		if ( '' === $text ) {
			$text = self::default_settings()['sms_consent_text'];
		}
		return str_replace( '{{shop.name}}', get_bloginfo( 'name' ), $text );
	}

	public static function can_send_to( string $phone, string $email = '' ): bool {
		if ( ! self::is_enforced() ) {
			return true;
		}

		return self::has_consent( $phone, $email );
	}

	public static function has_consent( string $phone, string $email = '' ): bool {
		$phone = self::normalize( $phone );
		if ( '' === $phone && ! is_email( $email ) ) {
			return false;
		}

		if ( is_email( $email ) ) {
			$user = get_user_by( 'email', $email );
			if ( $user && '1' === (string) get_user_meta( $user->ID, self::USER_META_KEY, true ) ) {
				return true;
			}
		}

		if ( '' !== $phone ) {
			$users = get_users(
				[
					'meta_key'   => 'billing_phone',
					'meta_value' => $phone,
					'number'     => 1,
					'fields'     => 'ID',
				]
			);
			if ( ! empty( $users ) && '1' === (string) get_user_meta( (int) $users[0], self::USER_META_KEY, true ) ) {
				return true;
			}

			if ( self::guest_order_has_consent( $phone ) ) {
				return true;
			}
		}

		return false;
	}

	public static function grant( string $phone, string $email = '', string $source = 'unknown' ): void {
		$phone = self::normalize( $phone );
		if ( is_email( $email ) ) {
			$user = get_user_by( 'email', $email );
			if ( $user ) {
				update_user_meta( $user->ID, self::USER_META_KEY, '1' );
				update_user_meta( $user->ID, 'cartcue_sms_consent_at', current_time( 'mysql' ) );
				update_user_meta( $user->ID, 'cartcue_sms_consent_source', sanitize_key( $source ) );
				if ( $phone ) {
					update_user_meta( $user->ID, 'billing_phone', $phone );
				}
				return;
			}
		}

		if ( '' === $phone ) {
			return;
		}

		$users = get_users(
			[
				'meta_key'   => 'billing_phone',
				'meta_value' => $phone,
				'number'     => 1,
				'fields'     => 'ID',
			]
		);
		if ( ! empty( $users ) ) {
			update_user_meta( (int) $users[0], self::USER_META_KEY, '1' );
		}
	}

	public static function persist_order_consent( int $order_id, bool $consented ): void {
		$order = wc_get_order( $order_id );
		if ( ! $order ) {
			return;
		}

		$order->update_meta_data( self::ORDER_META_KEY, $consented ? 'yes' : 'no' );
		$order->save();

		if ( $consented ) {
			self::grant( (string) $order->get_billing_phone(), (string) $order->get_billing_email(), 'checkout' );
		}
	}

	private static function guest_order_has_consent( string $phone ): bool {
		$orders = wc_get_orders(
			[
				'limit'          => 1,
				'billing_phone'  => $phone,
				'meta_key'       => self::ORDER_META_KEY,
				'meta_value'     => 'yes',
				'orderby'        => 'date',
				'order'          => 'DESC',
				'return'         => 'ids',
			]
		);

		return ! empty( $orders );
	}

	private static function normalize( string $phone ): string {
		return preg_replace( '/[^+\d]/', '', $phone ) ?? '';
	}
}
