<?php
/**
 * Scheduler booking confirmations and staff notifications.
 *
 * @package Niwa_AI
 */

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

class Niwa_AI_Appointment_Notifier {

	/** @var object|null */
	private $whatsapp_outreach;

	/** @param object|null $whatsapp_outreach Existing Niwa WhatsApp outreach service. */
	public function __construct( $whatsapp_outreach = null ) {
		$this->whatsapp_outreach = $whatsapp_outreach;
	}

	/** Register the post-commit booking hook. */
	public function register_hooks() {
		add_action( 'niwa_ai_appointment_booked', array( $this, 'send_notifications' ), 10, 3 );
	}

	/**
	 * Send enabled visitor confirmations plus mandatory admin/team emails.
	 * Delivery failures never invalidate the already committed booking.
	 *
	 * @param array  $appointment Saved appointment snapshot.
	 * @param string $session_id  Verified frontend session.
	 * @param int    $contact_id  Contact ID when one was collected.
	 */
	public function send_notifications( $appointment, $session_id = '', $contact_id = 0 ) {
		unset( $session_id );
		if ( ! is_array( $appointment ) ) {
			return;
		}

		$settings = $this->scheduler_settings();
		$channels = isset( $settings['confirmation_channels'] ) && is_array( $settings['confirmation_channels'] )
			? $settings['confirmation_channels']
			: array();
		$labels   = $this->labels();
		$service  = $this->value( $appointment, 'service_name', $labels['not_provided'] );
		$subject  = sprintf( $labels['customer_subject'], $service );

		if ( in_array( 'email', $channels, true ) && ! empty( $appointment['customer_email'] ) && is_email( $appointment['customer_email'] ) ) {
			$this->safe_mail( $appointment['customer_email'], $subject, $this->customer_message( $appointment, $labels ) );
		}

		if ( in_array( 'whatsapp', $channels, true ) && ! empty( $appointment['customer_phone'] ) && $this->whatsapp_is_available() ) {
			try {
				$this->whatsapp_outreach->send_outreach(
					array(
						'contact_id'   => max( 0, (int) $contact_id ),
						'phone'        => (string) $appointment['customer_phone'],
						'name'         => isset( $appointment['customer_name'] ) ? (string) $appointment['customer_name'] : '',
						'email'        => isset( $appointment['customer_email'] ) ? (string) $appointment['customer_email'] : '',
						'message'      => $this->customer_message( $appointment, $labels ),
						'source'       => 'scheduler_confirmation',
						'workflow_key' => 'scheduler_confirmation_' . sanitize_key( $this->value( $appointment, 'booking_uid', (string) ( $appointment['id'] ?? '' ) ) ),
					)
				);
			} catch ( Throwable $error ) {
				// The booking is already committed; transport failures are non-fatal.
			}
		}

		$internal_subject = sprintf( $labels['staff_subject'], $service );
		$internal_message = $this->staff_message( $appointment, $labels );
		foreach ( $this->staff_recipients( $appointment ) as $recipient ) {
			$this->safe_mail( $recipient, $internal_subject, $internal_message );
		}
	}

	/** @return array */
	private function scheduler_settings() {
		try {
			return class_exists( 'Niwa_AI_Appointment_Service' ) ? Niwa_AI_Appointment_Service::get_settings() : array();
		} catch ( Throwable $error ) {
			return array();
		}
	}

	/** @return bool */
	private function whatsapp_is_available() {
		if ( ! is_object( $this->whatsapp_outreach ) || ! method_exists( $this->whatsapp_outreach, 'send_outreach' ) ) {
			return false;
		}
		if ( ! class_exists( 'Niwa_AI_Lead_WhatsApp_Outreach_Service' ) || ! ( $this->whatsapp_outreach instanceof Niwa_AI_Lead_WhatsApp_Outreach_Service ) ) {
			return true;
		}
		if ( ! class_exists( 'Niwa_AI_Admin_Autonomy_WhatsApp' ) ) {
			return false;
		}
		try {
			$settings = ( new Niwa_AI_Admin_Autonomy_WhatsApp() )->get_settings();
			return ! empty( $settings['enabled'] );
		} catch ( Throwable $error ) {
			return false;
		}
	}

	/** @return array */
	private function staff_recipients( array $appointment ) {
		$emails = array(
			get_option( 'admin_email', '' ),
			isset( $appointment['team_member_email'] ) ? $appointment['team_member_email'] : '',
		);
		$out = array();
		foreach ( $emails as $email ) {
			$email = sanitize_email( (string) $email );
			if ( '' !== $email && is_email( $email ) ) {
				$out[ strtolower( $email ) ] = $email;
			}
		}
		return array_values( $out );
	}

	/** @return bool */
	private function safe_mail( $to, $subject, $message ) {
		try {
			return (bool) wp_mail( $to, $subject, $message, array( 'Content-Type: text/plain; charset=UTF-8' ) );
		} catch ( Throwable $error ) {
			return false;
		}
	}

	/** @return string */
	private function customer_message( array $appointment, array $labels ) {
		return implode(
			"\n",
			array(
				$labels['customer_intro'],
				'',
				$labels['service'] . ': ' . $this->value( $appointment, 'service_name', $labels['not_provided'] ),
				$labels['team_member'] . ': ' . $this->value( $appointment, 'team_member_name', $labels['not_provided'] ),
				$labels['date'] . ': ' . $this->date_part( $appointment ),
				$labels['time'] . ': ' . $this->time_part( $appointment ),
				$labels['timezone'] . ': ' . $this->value( $appointment, 'timezone', 'UTC' ),
				$labels['booking_reference'] . ': ' . $this->value( $appointment, 'booking_uid', (string) ( $appointment['id'] ?? '' ) ),
			)
		);
	}

	/** @return string */
	private function staff_message( array $appointment, array $labels ) {
		return implode(
			"\n",
			array(
				$labels['staff_intro'],
				'',
				$labels['service'] . ': ' . $this->value( $appointment, 'service_name', $labels['not_provided'] ),
				$labels['team_member'] . ': ' . $this->value( $appointment, 'team_member_name', $labels['not_provided'] ),
				$labels['date'] . ': ' . $this->date_part( $appointment ),
				$labels['time'] . ': ' . $this->time_part( $appointment ),
				$labels['timezone'] . ': ' . $this->value( $appointment, 'timezone', 'UTC' ),
				$labels['booking_reference'] . ': ' . $this->value( $appointment, 'booking_uid', (string) ( $appointment['id'] ?? '' ) ),
				'',
				$labels['name'] . ': ' . $this->value( $appointment, 'customer_name', $labels['not_provided'] ),
				$labels['email'] . ': ' . $this->value( $appointment, 'customer_email', $labels['not_provided'] ),
				$labels['phone'] . ': ' . $this->value( $appointment, 'customer_phone', $labels['not_provided'] ),
				'',
				$labels['lead_description'] . ': ' . $this->value( $appointment, 'details_snapshot', $labels['not_provided'] ),
			)
		);
	}

	/** @return string */
	private function date_part( array $appointment ) {
		$value = $this->value( $appointment, 'starts_at', '' );
		return '' !== $value ? substr( $value, 0, 10 ) : $this->labels()['not_provided'];
	}

	/** @return string */
	private function time_part( array $appointment ) {
		$value = $this->value( $appointment, 'starts_at', '' );
		return strlen( $value ) >= 16 ? substr( $value, 11, 5 ) : $this->labels()['not_provided'];
	}

	/** @return string */
	private function value( array $source, $key, $fallback ) {
		$value = isset( $source[ $key ] ) ? trim( (string) $source[ $key ] ) : '';
		return '' !== $value ? $value : (string) $fallback;
	}

	/** @return array */
	private function labels() {
		$option_key = class_exists( 'Niwa_AI_Constants' ) ? Niwa_AI_Constants::OPT_UI_SETTINGS : 'niwa_ai_ui_settings';
		$settings   = get_option( $option_key, array() );
		$lang       = is_array( $settings ) && ! empty( $settings['ui_language'] ) ? sanitize_key( $settings['ui_language'] ) : 'en';
		$all        = array(
			'en' => array( 'customer_subject' => 'Appointment confirmed: %s', 'customer_intro' => 'Your appointment is reserved.', 'staff_subject' => 'New appointment: %s', 'staff_intro' => 'A new appointment has been booked.', 'service' => 'Service', 'team_member' => 'Team member', 'date' => 'Date', 'time' => 'Time', 'timezone' => 'Time zone', 'booking_reference' => 'Booking reference', 'name' => 'Name', 'email' => 'Email', 'phone' => 'Phone', 'lead_description' => 'AI lead description', 'not_provided' => 'Not provided' ),
			'sr' => array( 'customer_subject' => 'Termin potvrđen: %s', 'customer_intro' => 'Vaš termin je rezervisan.', 'staff_subject' => 'Novi zakazani termin: %s', 'staff_intro' => 'Zakazan je novi termin.', 'service' => 'Usluga', 'team_member' => 'Član tima', 'date' => 'Datum', 'time' => 'Vreme', 'timezone' => 'Vremenska zona', 'booking_reference' => 'Broj rezervacije', 'name' => 'Ime', 'email' => 'Email', 'phone' => 'Telefon', 'lead_description' => 'AI opis leada', 'not_provided' => 'Nije navedeno' ),
			'hr' => array( 'customer_subject' => 'Termin potvrđen: %s', 'customer_intro' => 'Vaš termin je rezerviran.', 'staff_subject' => 'Novi rezervirani termin: %s', 'staff_intro' => 'Rezerviran je novi termin.', 'service' => 'Usluga', 'team_member' => 'Član tima', 'date' => 'Datum', 'time' => 'Vrijeme', 'timezone' => 'Vremenska zona', 'booking_reference' => 'Broj rezervacije', 'name' => 'Ime', 'email' => 'Email', 'phone' => 'Telefon', 'lead_description' => 'AI opis potencijalnog klijenta', 'not_provided' => 'Nije navedeno' ),
			'de' => array( 'customer_subject' => 'Termin bestätigt: %s', 'customer_intro' => 'Ihr Termin wurde reserviert.', 'staff_subject' => 'Neuer Termin: %s', 'staff_intro' => 'Ein neuer Termin wurde gebucht.', 'service' => 'Leistung', 'team_member' => 'Teammitglied', 'date' => 'Datum', 'time' => 'Uhrzeit', 'timezone' => 'Zeitzone', 'booking_reference' => 'Buchungsnummer', 'name' => 'Name', 'email' => 'E-Mail', 'phone' => 'Telefon', 'lead_description' => 'KI-Lead-Beschreibung', 'not_provided' => 'Nicht angegeben' ),
			'es' => array( 'customer_subject' => 'Cita confirmada: %s', 'customer_intro' => 'Su cita está reservada.', 'staff_subject' => 'Nueva cita: %s', 'staff_intro' => 'Se ha reservado una nueva cita.', 'service' => 'Servicio', 'team_member' => 'Miembro del equipo', 'date' => 'Fecha', 'time' => 'Hora', 'timezone' => 'Zona horaria', 'booking_reference' => 'Referencia de reserva', 'name' => 'Nombre', 'email' => 'Correo electrónico', 'phone' => 'Teléfono', 'lead_description' => 'Descripción del lead por IA', 'not_provided' => 'No indicado' ),
			'fr' => array( 'customer_subject' => 'Rendez-vous confirmé : %s', 'customer_intro' => 'Votre rendez-vous est réservé.', 'staff_subject' => 'Nouveau rendez-vous : %s', 'staff_intro' => 'Un nouveau rendez-vous a été réservé.', 'service' => 'Service', 'team_member' => 'Membre de l’équipe', 'date' => 'Date', 'time' => 'Heure', 'timezone' => 'Fuseau horaire', 'booking_reference' => 'Référence de réservation', 'name' => 'Nom', 'email' => 'E-mail', 'phone' => 'Téléphone', 'lead_description' => 'Description du prospect par IA', 'not_provided' => 'Non indiqué' ),
		);
		return isset( $all[ $lang ] ) ? $all[ $lang ] : $all['en'];
	}
}
