<?php
/**
 * Form submission handler.
 *
 * @package TonItaliaRegistration
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class TON_Reg_Registration_Handler
 */
class TON_Reg_Registration_Handler {

	/**
	 * Register hooks.
	 */
	public static function register() {
		add_action( 'template_redirect', array( __CLASS__, 'maybe_handle_frontend_submit' ), 1 );
		add_action( 'admin_post_nopriv_ton_reg_submit', array( __CLASS__, 'handle' ) );
		add_action( 'admin_post_ton_reg_submit', array( __CLASS__, 'handle' ) );
	}

	/**
	 * Handle POST on the public form page (avoids wp-admin/admin-post.php).
	 */
	public static function maybe_handle_frontend_submit() {
		if ( is_admin() || 'POST' !== ( $_SERVER['REQUEST_METHOD'] ?? '' ) ) {
			return;
		}

		if ( empty( $_POST['ton_reg_frontend'] ) || '1' !== (string) wp_unslash( $_POST['ton_reg_frontend'] ) ) {
			return;
		}

		self::handle();
	}

	/**
	 * Handle POST.
	 */
	public static function handle() {
		$redirect = self::resolve_redirect_url();

		if ( ! isset( $_POST['ton_reg_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ton_reg_nonce'] ) ), TON_Reg_Captcha::NONCE_ACTION ) ) {
			self::redirect_error( $redirect, __( 'Sessione non valida.', 'ton-italia-registration' ) );
		}

		if ( ! TON_Reg_Captcha::check_rate_limit() ) {
			self::redirect_error( $redirect, __( 'Troppi tentativi. Riprova più tardi.', 'ton-italia-registration' ) );
		}

		$captcha = TON_Reg_Captcha::validate( $_POST );
		if ( is_wp_error( $captcha ) ) {
			self::redirect_error( $redirect, $captcha->get_error_message() );
		}

		$data = self::sanitize_post( $_POST );
		$valid = self::validate( $data );
		if ( is_wp_error( $valid ) ) {
			self::redirect_error( $redirect, $valid->get_error_message() );
		}

		$existing = TON_Reg_Database::find_active_by_email_or_cf( $data['email'], $data['codice_fiscale'] );
		if ( $existing ) {
			self::redirect_error( $redirect, __( 'Esiste già una richiesta attiva con questa email o codice fiscale.', 'ton-italia-registration' ) );
		}

		$user_id = TON_Reg_User_Manager::create_subscriber( $data );
		if ( is_wp_error( $user_id ) ) {
			self::redirect_error( $redirect, $user_id->get_error_message() );
		}

		$now     = current_time( 'mysql', true );
		$privacy = (string) get_option( 'ton_reg_privacy_version', '1' );

		$row = array(
			'user_id'               => $user_id,
			'cognome'               => $data['cognome'],
			'nome'                  => $data['nome'],
			'luogo_nascita'         => $data['luogo_nascita'],
			'provincia_nascita'     => $data['provincia_nascita'],
			'data_nascita'          => $data['data_nascita'],
			'codice_fiscale'        => $data['codice_fiscale'],
			'comune_residenza'      => $data['comune_residenza'],
			'provincia_residenza'   => $data['provincia_residenza'],
			'indirizzo'             => $data['indirizzo'],
			'numero_civico'         => $data['numero_civico'],
			'cap'                   => $data['cap'],
			'telefono'              => $data['telefono'],
			'email'                 => $data['email'],
			'luogo_dichiarazione'   => $data['luogo_dichiarazione'],
			'data_dichiarazione'    => $data['data_dichiarazione'],
			'bonifico_effettuato'   => $data['bonifico_effettuato'],
			'consenso_statuto'      => 1,
			'consenso_privacy'      => 1,
			'consenso_newsletter'   => $data['consenso_newsletter'],
			'registration_ip'       => TON_Reg_Captcha::get_client_ip(),
			'user_agent'            => self::user_agent(),
			'privacy_text_version'  => $privacy,
			'consent_statuto_at'    => $now,
			'consent_privacy_at'    => $now,
			'status'                => 'pending',
		);

		$reg_id = TON_Reg_Database::insert( $row );
		if ( ! $reg_id ) {
			wp_delete_user( $user_id );
			self::redirect_error( $redirect, __( 'Errore nel salvataggio. Riprova.', 'ton-italia-registration' ) );
		}

		update_user_meta( $user_id, 'ton_reg_registration_id', $reg_id );
		$data['registration_id'] = $reg_id;
		TON_Reg_User_Manager::sync_user_meta( $user_id, $data );

		$registration = TON_Reg_Database::get( $reg_id );
		TON_Reg_Documents::ensure_member_folder( $registration );
		TON_Reg_Mailer::send_admin_notification( $registration, $user_id );
		TON_Reg_Mailer::send_user_confirmation( $registration, $user_id );

		/**
		 * Fires after a registration is stored and notification emails are sent.
		 *
		 * @param int                  $reg_id       Registration ID.
		 * @param array<string,mixed>  $data         Sanitized form data.
		 * @param object               $registration Registration row.
		 */
		do_action( 'ton_reg_registration_complete', $reg_id, $data, $registration );

		if ( ! empty( $data['consenso_newsletter'] ) && TON_Reg_Mailchimp::is_configured() ) {
			TON_Reg_Mailchimp::schedule_sync( $reg_id );
		}

		$success_redirect = self::get_success_redirect_url();
		if ( ! $success_redirect ) {
			$success_redirect = self::resolve_redirect_url();
		}

		$success_url = add_query_arg(
			array(
				'ton_reg' => 'success',
			),
			$success_redirect
		);
		wp_safe_redirect( $success_url );
		exit;
	}

	/**
	 * @param array<string,mixed> $post Raw POST.
	 * @return array<string,mixed>
	 */
	private static function sanitize_post( $post ) {
		$cf = isset( $post['codice_fiscale'] ) ? strtoupper( preg_replace( '/\s+/', '', sanitize_text_field( wp_unslash( $post['codice_fiscale'] ) ) ) ) : '';

		return array(
			'cognome'              => sanitize_text_field( wp_unslash( $post['cognome'] ?? '' ) ),
			'nome'                 => sanitize_text_field( wp_unslash( $post['nome'] ?? '' ) ),
			'luogo_nascita'        => sanitize_text_field( wp_unslash( $post['luogo_nascita'] ?? '' ) ),
			'provincia_nascita'    => strtoupper( sanitize_text_field( wp_unslash( $post['provincia_nascita'] ?? '' ) ) ),
			'data_nascita'         => self::parse_date_input( sanitize_text_field( wp_unslash( $post['data_nascita'] ?? '' ) ) ),
			'codice_fiscale'       => $cf,
			'comune_residenza'     => sanitize_text_field( wp_unslash( $post['comune_residenza'] ?? '' ) ),
			'provincia_residenza'  => strtoupper( sanitize_text_field( wp_unslash( $post['provincia_residenza'] ?? '' ) ) ),
			'indirizzo'            => sanitize_text_field( wp_unslash( $post['indirizzo'] ?? '' ) ),
			'numero_civico'        => sanitize_text_field( wp_unslash( $post['numero_civico'] ?? '' ) ),
			'cap'                  => sanitize_text_field( wp_unslash( $post['cap'] ?? '' ) ),
			'telefono'             => sanitize_text_field( wp_unslash( $post['telefono'] ?? '' ) ),
			'email'                => sanitize_email( wp_unslash( $post['email'] ?? '' ) ),
			'luogo_dichiarazione'  => sanitize_text_field( wp_unslash( $post['luogo_dichiarazione'] ?? '' ) ),
			'data_dichiarazione'   => self::parse_date_input( sanitize_text_field( wp_unslash( $post['data_dichiarazione'] ?? '' ) ) ),
			'bonifico_effettuato'  => ! empty( $post['bonifico_effettuato'] ) ? 1 : 0,
			'consenso_statuto'     => ! empty( $post['accettazione_statuto'] ) ? 1 : 0,
			'consenso_privacy'     => ! empty( $post['consenso_privacy'] ) ? 1 : 0,
			'consenso_newsletter'  => ! empty( $post['consenso_newsletter'] ) ? 1 : 0,
		);
	}

	/**
	 * @param array<string,mixed> $data Data.
	 * @return true|WP_Error
	 */
	private static function validate( $data ) {
		$required = array(
			'cognome'             => __( 'Cognome', 'ton-italia-registration' ),
			'nome'                => __( 'Nome', 'ton-italia-registration' ),
			'luogo_nascita'       => __( 'Luogo di nascita', 'ton-italia-registration' ),
			'provincia_nascita'    => __( 'Provincia di nascita', 'ton-italia-registration' ),
			'data_nascita'        => __( 'Data di nascita', 'ton-italia-registration' ),
			'codice_fiscale'      => __( 'Codice fiscale', 'ton-italia-registration' ),
			'comune_residenza'    => __( 'Comune di residenza', 'ton-italia-registration' ),
			'provincia_residenza' => __( 'Provincia di residenza', 'ton-italia-registration' ),
			'indirizzo'           => __( 'Indirizzo', 'ton-italia-registration' ),
			'numero_civico'       => __( 'Numero civico', 'ton-italia-registration' ),
			'cap'                 => __( 'CAP', 'ton-italia-registration' ),
			'telefono'            => __( 'Telefono', 'ton-italia-registration' ),
			'email'               => __( 'Email', 'ton-italia-registration' ),
			'luogo_dichiarazione' => __( 'Luogo dichiarazione', 'ton-italia-registration' ),
			'data_dichiarazione'  => __( 'Data dichiarazione', 'ton-italia-registration' ),
		);

		foreach ( $required as $key => $label ) {
			if ( empty( $data[ $key ] ) ) {
				return new WP_Error( 'required', sprintf( __( 'Il campo %s è obbligatorio.', 'ton-italia-registration' ), $label ) );
			}
		}

		if ( ! is_email( $data['email'] ) ) {
			return new WP_Error( 'email', __( 'Email non valida.', 'ton-italia-registration' ) );
		}

		if ( ! TON_Reg_User_Manager::validate_codice_fiscale( $data['codice_fiscale'] ) ) {
			return new WP_Error( 'cf', __( 'Codice fiscale non valido.', 'ton-italia-registration' ) );
		}

		if ( ! preg_match( '/^\d{5}$/', $data['cap'] ) ) {
			return new WP_Error( 'cap', __( 'CAP non valido.', 'ton-italia-registration' ) );
		}

		if ( ! preg_match( '/^[A-Z]{2}$/', $data['provincia_nascita'] ) || ! preg_match( '/^[A-Z]{2}$/', $data['provincia_residenza'] ) ) {
			return new WP_Error( 'prov', __( 'Provincia non valida (2 lettere).', 'ton-italia-registration' ) );
		}

		if ( ! self::is_valid_date( $data['data_nascita'] ) || ! self::is_valid_date( $data['data_dichiarazione'] ) ) {
			return new WP_Error( 'date', __( 'Data non valida. Usa il formato gg-mm-aaaa.', 'ton-italia-registration' ) );
		}

		if ( ! self::is_date_not_in_future( $data['data_dichiarazione'] ) ) {
			return new WP_Error( 'date_future', __( 'La data di dichiarazione non può essere futura.', 'ton-italia-registration' ) );
		}

		if ( empty( $data['consenso_statuto'] ) ) {
			return new WP_Error( 'statuto', __( 'Devi accettare la dichiarazione sullo statuto.', 'ton-italia-registration' ) );
		}

		if ( empty( $data['consenso_privacy'] ) ) {
			return new WP_Error( 'privacy', __( 'Devi accettare l\'informativa privacy.', 'ton-italia-registration' ) );
		}

		if ( '1' === get_option( 'ton_reg_newsletter_required', '0' ) && empty( $data['consenso_newsletter'] ) ) {
			return new WP_Error( 'newsletter', __( 'Devi accettare il consenso newsletter.', 'ton-italia-registration' ) );
		}

		return true;
	}

	/**
	 * Pad single-digit day/month (1-9) in gg-mm-aaaa input.
	 *
	 * @param string $part Day or month segment.
	 * @return string
	 */
	private static function pad_date_part( $part ) {
		$num = (int) $part;
		if ( 1 === strlen( $part ) && $num >= 1 && $num <= 9 ) {
			return '0' . $part;
		}
		return $part;
	}

	/**
	 * Parse gg-mm-aaaa (or already normalized aaaa-mm-gg) to DB format Y-m-d.
	 *
	 * @param string $value User input.
	 * @return string Empty if invalid.
	 */
	private static function parse_date_input( $value ) {
		$value = str_replace( array( '/', '.' ), '-', trim( $value ) );
		if ( preg_match( '/^(\d{1,2})-(\d{1,2})-(\d{4})$/', $value, $m ) ) {
			$day_str   = self::pad_date_part( $m[1] );
			$month_str = self::pad_date_part( $m[2] );
			$day       = (int) $day_str;
			$month     = (int) $month_str;
			$year      = (int) $m[3];
			if ( checkdate( $month, $day, $year ) ) {
				return sprintf( '%04d-%02d-%02d', $year, $month, $day );
			}
			return '';
		}
		if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $value ) ) {
			$parts = array_map( 'intval', explode( '-', $value ) );
			if ( checkdate( $parts[1], $parts[2], $parts[0] ) ) {
				return $value;
			}
		}
		return '';
	}

	/**
	 * @param string $date Date Y-m-d.
	 * @return bool
	 */
	private static function is_valid_date( $date ) {
		if ( ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date ) ) {
			return false;
		}
		$parts = array_map( 'intval', explode( '-', $date ) );
		return checkdate( $parts[1], $parts[2], $parts[0] );
	}

	/**
	 * @param string $date Date in Y-m-d format.
	 * @return bool
	 */
	private static function is_date_not_in_future( $date ) {
		if ( ! self::is_valid_date( $date ) ) {
			return false;
		}

		return $date <= current_time( 'Y-m-d' );
	}

	/**
	 * Resolve redirect URL after form submit (public form page only).
	 *
	 * @return string
	 */
	private static function resolve_redirect_url() {
		if ( ! empty( $_POST['ton_reg_page_id'] ) ) {
			$post_id = (int) wp_unslash( $_POST['ton_reg_page_id'] );
			if ( self::is_publicly_viewable_page( $post_id ) ) {
				return get_permalink( $post_id );
			}
		}

		if ( ! empty( $_POST['ton_reg_redirect'] ) ) {
			$public_url = self::get_public_redirect_url(
				esc_url_raw( wp_unslash( $_POST['ton_reg_redirect'] ) )
			);
			if ( $public_url ) {
				return $public_url;
			}
		}

		return home_url( '/' );
	}

	/**
	 * Public permalink of the configured success page.
	 *
	 * @return string Empty when not configured.
	 */
	public static function get_success_redirect_url() {
		$page_id = (int) get_option( 'ton_reg_success_page_id', 0 );
		if ( ! $page_id || ! self::is_publicly_viewable_page( $page_id ) ) {
			return '';
		}

		return get_permalink( $page_id );
	}

	/**
	 * Public URL used as form action (same page, never wp-admin).
	 *
	 * @return string
	 */
	public static function get_form_page_action_url() {
		global $post;

		if ( $post instanceof WP_Post && self::is_publicly_viewable_page( $post->ID ) ) {
			return get_permalink( $post );
		}

		return home_url( '/' );
	}

	/**
	 * @return int Page ID when the form is on a public page, else 0.
	 */
	public static function get_form_page_id() {
		global $post;

		if ( $post instanceof WP_Post && self::is_publicly_viewable_page( $post->ID ) ) {
			return (int) $post->ID;
		}

		return 0;
	}

	/**
	 * Permalink for the current form page when it is publicly viewable.
	 *
	 * @return string
	 */
	public static function get_form_page_redirect_url() {
		return self::get_form_page_action_url();
	}

	/**
	 * @param string $url Candidate URL.
	 * @return string Sanitized public URL or empty string.
	 */
	public static function get_public_redirect_url( $url ) {
		$url = wp_validate_redirect( esc_url_raw( (string) $url ), false );
		if ( ! $url || self::is_restricted_redirect_url( $url ) ) {
			return '';
		}

		$post_id = url_to_postid( $url );
		if ( $post_id && self::is_publicly_viewable_page( $post_id ) ) {
			return get_permalink( $post_id );
		}

		if ( self::is_public_home_url( $url ) ) {
			return $url;
		}

		return '';
	}

	/**
	 * @param int $post_id Post ID.
	 * @return bool
	 */
	public static function is_publicly_viewable_page( $post_id ) {
		$post = get_post( (int) $post_id );
		if ( ! $post instanceof WP_Post ) {
			return false;
		}

		if ( function_exists( 'is_post_publicly_viewable' ) ) {
			return (bool) is_post_publicly_viewable( $post );
		}

		return 'publish' === $post->post_status && '' === $post->post_password;
	}

	/**
	 * @param string $url URL.
	 * @return bool
	 */
	private static function is_restricted_redirect_url( $url ) {
		$path = wp_parse_url( $url, PHP_URL_PATH );
		if ( ! is_string( $path ) || '' === $path ) {
			return false;
		}

		$path = strtolower( untrailingslashit( $path ) );

		return str_contains( $path, '/wp-admin' )
			|| str_contains( $path, '/wp-login.php' )
			|| str_contains( $path, 'admin-post.php' );
	}

	/**
	 * @param string $url URL.
	 * @return bool
	 */
	private static function is_public_home_url( $url ) {
		if ( self::is_restricted_redirect_url( $url ) ) {
			return false;
		}

		$home_host = wp_parse_url( home_url( '/' ), PHP_URL_HOST );
		$url_host  = wp_parse_url( $url, PHP_URL_HOST );
		if ( $home_host && $url_host && strtolower( (string) $home_host ) !== strtolower( (string) $url_host ) ) {
			return false;
		}

		$home_path = wp_parse_url( home_url( '/' ), PHP_URL_PATH );
		$url_path  = wp_parse_url( $url, PHP_URL_PATH );
		$home_path = is_string( $home_path ) ? untrailingslashit( $home_path ) : '';
		$url_path  = is_string( $url_path ) ? untrailingslashit( $url_path ) : '';

		return $url_path === $home_path || '' === $url_path;
	}

	/**
	 * @return string
	 */
	private static function user_agent() {
		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
			return '';
		}
		return substr( sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ), 0, 255 );
	}

	/**
	 * @param string $url     URL.
	 * @param string $message Message.
	 */
	private static function redirect_error( $url, $message ) {
		$url = add_query_arg(
			array(
				'ton_reg' => 'error',
				'ton_msg' => rawurlencode( $message ),
			),
			$url
		);
		wp_safe_redirect( $url );
		exit;
	}
}
