<?php
/**
 * Public/portal session helpers.
 *
 * @package TradeSchoolManager
 */

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

class TSM_Public {
	private static $instance = null;
	const COOKIE = 'tsm_student_session';

	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	private function __construct() {
		add_action( 'init', array( $this, 'maybe_handle_logout' ) );
		add_action( 'init', array( $this, 'maybe_handle_login' ) );
		add_action( 'init', array( $this, 'maybe_handle_photo_upload' ) );
		add_action( 'init', array( $this, 'maybe_handle_forgot_password' ) );
		add_action( 'init', array( $this, 'maybe_handle_reset_password' ) );
		add_action( 'init', array( $this, 'maybe_handle_change_password' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ) );

		// Front-end portal actions use our own session, not WP auth.
		// Student report-card downloads are registered by the Reports & Transcripts add-on.
		// Certificate portal download handler ships in the Certificates add-on.
	}

	public function enqueue() {
		$public_css = TSM_PLUGIN_DIR . 'assets/css/public.css';
		$css_ver    = file_exists( $public_css ) ? TSM_VERSION . '.' . filemtime( $public_css ) : TSM_VERSION;
		wp_register_style( 'tsm-public', TSM_PLUGIN_URL . 'assets/css/public.css', array(), $css_ver );
	}

	public function maybe_handle_logout() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Logout link is a simple GET flag; clears local cookie only.
		if ( ! isset( $_GET['tsm_logout'] ) ) {
			return;
		}
		self::logout();
		// Send back to login page if configured, otherwise strip the flag.
		$login_url = self::get_page_url( 'student_login_page', self::current_url_base() );
		wp_safe_redirect( add_query_arg( 'tsm_logged_out', 1, $login_url ) );
		exit;
	}

	public function maybe_handle_login() {
		if ( ! isset( $_POST['tsm_login'] ) ) {
			return;
		}
		if ( ! isset( $_POST['tsm_login_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tsm_login_nonce'] ) ), 'tsm_login' ) ) {
			return;
		}
		$user = sanitize_user( wp_unslash( $_POST['tsm_username'] ?? '' ) );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw password is verified against hash; sanitizing would corrupt input.
		$pass = isset( $_POST['tsm_password'] ) ? (string) wp_unslash( $_POST['tsm_password'] ) : '';
		$student = TSM_Students::verify_login( $user, $pass );
		if ( $student ) {
			self::set_current_student( (int) $student->id );
			$portal_url = self::get_page_url( 'student_portal_page', remove_query_arg( array( 'tsm_logged_out', 'tsm_login_error' ) ) );
			wp_safe_redirect( $portal_url );
			exit;
		}
		wp_safe_redirect( add_query_arg( 'tsm_login_error', 1 ) );
		exit;
	}

	/**
	 * Resolve a configured page setting to a permalink.
	 * Falls back to $fallback when the setting is empty / page missing.
	 */
	public static function get_page_url( $setting_key, $fallback ) {
		$page_id = (int) tsm_get_setting( $setting_key, 0 );
		if ( $page_id ) {
			$url = get_permalink( $page_id );
			if ( $url ) {
				return $url;
			}
		}
		return $fallback;
	}

	/**
	 * Allow logged-in students to update their own profile photo, email and phone.
	 * Reused as the "My Information" form in the Settings tab.
	 */
	public function maybe_handle_photo_upload() {
		if ( ! isset( $_POST['tsm_photo_upload_nonce'] ) ) {
			return;
		}
		if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tsm_photo_upload_nonce'] ) ), 'tsm_photo_upload' ) ) {
			return;
		}
		$sid = self::current_student_id();
		if ( ! $sid ) {
			return;
		}
		global $wpdb;
		$updates = array();

		if ( ! empty( $_FILES['photo_file']['name'] ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
			$uploaded = wp_handle_upload(
				$_FILES['photo_file'], // phpcs:ignore
				array(
					'test_form' => false,
					'mimes'     => array(
						'png'  => 'image/png',
						'jpg'  => 'image/jpeg',
						'jpeg' => 'image/jpeg',
						'webp' => 'image/webp',
					),
				)
			);
			if ( ! empty( $uploaded['url'] ) ) {
				$updates['photo_url'] = esc_url_raw( $uploaded['url'] );
			}
		}

		$has_info = isset( $_POST['tsm_profile_fields'] );
		if ( $has_info ) {
			$email = isset( $_POST['tsm_email'] ) ? sanitize_email( wp_unslash( $_POST['tsm_email'] ) ) : '';
			$phone = isset( $_POST['tsm_phone'] ) ? sanitize_text_field( wp_unslash( $_POST['tsm_phone'] ) ) : '';
			$updates['email'] = '' === $email ? null : $email;
			$updates['phone'] = $phone;
		}

		if ( ! empty( $updates ) ) {
			$wpdb->update( TSM_Students::table(), $updates, array( 'id' => $sid ) ); // phpcs:ignore
		}
		$redirect = remove_query_arg( array( 'tsm_logged_out', 'tsm_login_error' ) );
		if ( $has_info ) {
			$redirect = add_query_arg( array( 'tab' => 'settings', 'sub' => 'info', 'tsm_info_saved' => 1 ), $redirect );
		}
		wp_safe_redirect( $redirect );
		exit;
	}

	/* portal_certificate moved to the Certificates add-on plugin. */

	/**
	 * Step 1: student requests a password reset by entering their email
	 * on the login page. We always show a generic success notice so the
	 * form cannot be used to enumerate which emails are on file.
	 */
	public function maybe_handle_forgot_password() {
		if ( empty( $_POST['tsm_forgot_nonce'] ) ) {
			return;
		}
		if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tsm_forgot_nonce'] ) ), 'tsm_forgot' ) ) {
			return;
		}
		$email   = sanitize_email( wp_unslash( $_POST['tsm_email'] ?? '' ) );
		$student = $email ? TSM_Students::get_by_email( $email ) : null;
		if ( $student ) {
			$token = TSM_Students::create_reset_token( (int) $student->id );
			if ( $token ) {
				$reset_url = add_query_arg(
					array( 'tsm_reset' => $token ),
					self::current_url_base()
				);
				$school    = tsm_get_setting( 'school_name', get_bloginfo( 'name' ) );
				/* translators: placeholder(s) for dynamic value(s). */
				$subject   = sprintf( __( '[%s] Password reset request', 'tradeschool-manager' ), $school );
				$message   = sprintf(
					/* translators: 1: student first name 2: school 3: link 4: minutes */
					__( "Hi %1\$s,\n\nWe received a request to reset your %2\$s student portal password. To choose a new one, open the link below within %4\$d minutes:\n\n%3\$s\n\nIf you didn't request this, you can ignore this email  -  your password will stay the same.", 'tradeschool-manager' ),
					$student->first_name,
					$school,
					$reset_url,
					60
				);
				wp_mail( $student->email, $subject, $message );
			}
		}
		wp_safe_redirect( add_query_arg( 'tsm_forgot_sent', 1, remove_query_arg( array( 'tsm_login_error', 'tsm_reset' ) ) ) );
		exit;
	}

	/**
	 * Step 2: student submits the new password after clicking the link.
	 */
	public function maybe_handle_reset_password() {
		if ( empty( $_POST['tsm_reset_nonce'] ) ) {
			return;
		}
		if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tsm_reset_nonce'] ) ), 'tsm_reset' ) ) {
			return;
		}
		$token = sanitize_text_field( wp_unslash( $_POST['tsm_reset_token'] ?? '' ) );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw password; sanitizing would corrupt.
		$pw1   = (string) wp_unslash( $_POST['tsm_new_password'] ?? '' );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw password; sanitizing would corrupt.
		$pw2   = (string) wp_unslash( $_POST['tsm_new_password2'] ?? '' );
		$student = TSM_Students::get_by_reset_token( $token );

		if ( ! $student ) {
			wp_safe_redirect( add_query_arg( 'tsm_reset_error', 'invalid', remove_query_arg( 'tsm_reset' ) ) );
			exit;
		}
		if ( strlen( $pw1 ) < 8 ) {
			wp_safe_redirect( add_query_arg( array( 'tsm_reset' => $token, 'tsm_reset_error' => 'short' ) ) );
			exit;
		}
		if ( $pw1 !== $pw2 ) {
			wp_safe_redirect( add_query_arg( array( 'tsm_reset' => $token, 'tsm_reset_error' => 'mismatch' ) ) );
			exit;
		}
		TSM_Students::set_password( (int) $student->id, $pw1 );
		wp_safe_redirect( add_query_arg( 'tsm_reset_done', 1, remove_query_arg( array( 'tsm_reset', 'tsm_reset_error' ) ) ) );
		exit;
	}

	/**
	 * Logged-in students can change their password from the portal.
	 */
	public function maybe_handle_change_password() {
		if ( empty( $_POST['tsm_change_pw_nonce'] ) ) {
			return;
		}
		if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tsm_change_pw_nonce'] ) ), 'tsm_change_pw' ) ) {
			return;
		}
		$return = add_query_arg( 'tab', 'settings', self::current_url_base() );
		$sid = self::current_student_id();
		if ( ! $sid ) {
			wp_safe_redirect( add_query_arg( 'tsm_pw_error', 'session', $return ) );
			exit;
			return;
		}
		$student = TSM_Students::get( $sid );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw password; sanitizing would corrupt.
		$current = (string) wp_unslash( $_POST['tsm_current_password'] ?? '' );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw password; sanitizing would corrupt.
		$pw1     = (string) wp_unslash( $_POST['tsm_new_password'] ?? '' );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw password; sanitizing would corrupt.
		$pw2     = (string) wp_unslash( $_POST['tsm_new_password2'] ?? '' );

		if ( ! $student || empty( $student->password_hash ) || ! wp_check_password( $current, $student->password_hash ) ) {
			wp_safe_redirect( add_query_arg( 'tsm_pw_error', 'current', $return ) );
			exit;
		}
		if ( strlen( $pw1 ) < 8 ) {
			wp_safe_redirect( add_query_arg( 'tsm_pw_error', 'short', $return ) );
			exit;
		}
		if ( $pw1 !== $pw2 ) {
			wp_safe_redirect( add_query_arg( 'tsm_pw_error', 'mismatch', $return ) );
			exit;
		}
		$ok = TSM_Students::set_password( $sid, $pw1 );
		if ( ! $ok ) {
			wp_safe_redirect( add_query_arg( 'tsm_pw_error', 'save', $return ) );
			exit;
		}
		wp_safe_redirect( add_query_arg( 'tsm_pw_done', 1, remove_query_arg( 'tsm_pw_error', $return ) ) );
		exit;

	}

	/**
	 * Permalink of the current request, without our own query args.
	 */
	private static function current_url_base() {
		$host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : '';
		$uri  = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
		$url  = is_ssl() ? 'https://' : 'http://';
		$url .= $host . $uri;
		$url = remove_query_arg( array( 'tsm_reset', 'tsm_reset_error', 'tsm_reset_done', 'tsm_forgot_sent', 'tsm_login_error', 'tsm_logout', 'tsm_pw_error', 'tsm_pw_done', 'tab' ), $url );
		return $url;
	}

	public static function set_current_student( $student_id ) {
		$token   = wp_generate_password( 32, false, false );
		set_transient( 'tsm_session_' . $token, $student_id, DAY_IN_SECONDS * 7 );
		setcookie( self::COOKIE, $token, time() + DAY_IN_SECONDS * 7, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
		$_COOKIE[ self::COOKIE ] = $token;
	}

	public static function current_student_id() {
		if ( empty( $_COOKIE[ self::COOKIE ] ) ) {
			return 0;
		}
		$token = sanitize_text_field( wp_unslash( $_COOKIE[ self::COOKIE ] ) );
		$sid   = get_transient( 'tsm_session_' . $token );
		return $sid ? (int) $sid : 0;
	}

	public static function logout() {
		if ( ! empty( $_COOKIE[ self::COOKIE ] ) ) {
			delete_transient( 'tsm_session_' . sanitize_text_field( wp_unslash( $_COOKIE[ self::COOKIE ] ) ) );
		}
		setcookie( self::COOKIE, '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN );
	}
}
