<?php
/**
 * Global "active school year" context for admins and teachers.
 *
 * The selection persists per-user via user meta. When a user has not made
 * a selection, the default is the current unarchived school year (most
 * recent start_date with status=active and archived=0). Pages can read
 * the current value with TSM_Active_Year::get() and render the global
 * switcher with TSM_Active_Year::render_switcher().
 *
 * Selecting "All years" (value=0) shows everything regardless of year  - 
 * useful for cross-year reports or looking up historical records.
 *
 * @package TradeSchoolManager
 */

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

class TSM_Active_Year {

	const META_KEY     = 'tsm_active_year_id';
	const COOKIE_KEY   = 'tsm_active_year_id';
	const QUERY_PARAM  = 'tsm_year';
	const NONCE_ACTION = 'tsm_set_active_year';

	/**
	 * Resolve the active year for the current request.
	 *
	 * Order of precedence:
	 *   1. ?tsm_year=N in the URL (with valid nonce) -> persists to user meta.
	 *   2. User meta selection (admin user or teacher).
	 *   3. Cookie fallback (so pre-login pages and teacher portal share a value).
	 *   4. Default current year (most recent unarchived active).
	 *
	 * Returns 0 when the user explicitly chose "All years".
	 */
	public static function get() {
		static $cached = null;
		if ( null !== $cached ) {
			return $cached;
		}

		$resolved = null;

		// 1. URL override.
		if ( isset( $_REQUEST[ self::QUERY_PARAM ] ) && isset( $_REQUEST['_tsm_year_nonce'] )
			&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['_tsm_year_nonce'] ) ), self::NONCE_ACTION )
		) {
			$resolved = absint( wp_unslash( $_REQUEST[ self::QUERY_PARAM ] ) );
		}

		// 2. User meta.
		if ( null === $resolved ) {
			$uid = get_current_user_id();
			if ( $uid ) {
				$val = get_user_meta( $uid, self::META_KEY, true );
				if ( '' !== $val && null !== $val ) {
					$resolved = (int) $val;
				}
			}
		}

		// 3. Teacher portal cookie.
		if ( null === $resolved && ! empty( $_COOKIE[ self::COOKIE_KEY ] ) ) {
			$resolved = (int) $_COOKIE[ self::COOKIE_KEY ];
		}

		// "All years" (0) is no longer supported  -  always coerce to a real year.
		if ( ! $resolved ) {
			$resolved = (int) self::default_year_id();
		}

		// Persist the URL override (and re-persist coerced values) so the
		// switcher reflects the active year on the next request.
		if ( isset( $_REQUEST[ self::QUERY_PARAM ] ) && isset( $_REQUEST['_tsm_year_nonce'] )
			&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['_tsm_year_nonce'] ) ), self::NONCE_ACTION )
		) {
			self::set( $resolved );
		}

		$cached = $resolved;
		return $cached;
	}

	/**
	 * Persist a selection for the current user (and a cookie fallback).
	 */
	public static function set( $year_id ) {
		$year_id = (int) $year_id;
		$uid     = get_current_user_id();
		if ( $uid ) {
			update_user_meta( $uid, self::META_KEY, $year_id );
		}
		// 90-day cookie covers the teacher portal where there may not be a WP user.
		if ( ! headers_sent() ) {
			setcookie( self::COOKIE_KEY, (string) $year_id, time() + ( 90 * DAY_IN_SECONDS ), COOKIEPATH ?: '/', COOKIE_DOMAIN );
		}
		$_COOKIE[ self::COOKIE_KEY ] = (string) $year_id;
	}

	/**
	 * Default = the unarchived, "active" year with the most recent start_date.
	 * Falls back to the most recent year regardless of status when none qualify.
	 */
	public static function default_year_id() {
		global $wpdb;
		$t  = $wpdb->prefix . 'tsm_school_years';
		$id = (int) $wpdb->get_var( "SELECT id FROM {$t} WHERE archived = 0 AND status = 'active' ORDER BY start_date DESC, id DESC LIMIT 1" ); // phpcs:ignore
		if ( $id ) { return $id; }
		return (int) $wpdb->get_var( "SELECT id FROM {$t} ORDER BY start_date DESC, id DESC LIMIT 1" ); // phpcs:ignore
	}

	/**
	 * Render the global year switcher. Used in the admin topbar and the
	 * teacher portal hero.
	 *
	 * @param string $context 'admin' | 'teacher' (controls styling only).
	 */
	public static function render_switcher( $context = 'admin' ) {
		$years     = class_exists( 'TSM_School_Years' ) ? TSM_School_Years::all() : array();
		if ( empty( $years ) ) { return; }
		$current   = self::get();
		$base_url  = remove_query_arg( array( self::QUERY_PARAM, '_tsm_year_nonce' ) );
		$nonce     = wp_create_nonce( self::NONCE_ACTION );
		$wrap_cls  = 'tsm-active-year tsm-active-year--' . esc_attr( $context );
		?>
		<form method="get" action="<?php echo esc_url( $base_url ); ?>" class="<?php echo esc_attr( $wrap_cls ); ?>" style="display:inline-flex;align-items:center;gap:6px;">
			<?php
			// Re-emit existing query params so we don't lose page/tab context.
			$preserve = $_GET; // phpcs:ignore
			unset( $preserve[ self::QUERY_PARAM ], $preserve['_tsm_year_nonce'] );
			foreach ( $preserve as $k => $v ) {
				if ( is_array( $v ) ) { continue; }
				$key   = sanitize_key( wp_unslash( $k ) );
				$value = sanitize_text_field( wp_unslash( $v ) );
				if ( '' === $key ) { continue; }
				echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '">';
			}
			?>
			<input type="hidden" name="_tsm_year_nonce" value="<?php echo esc_attr( $nonce ); ?>">
			<label style="font-size:12px;font-weight:600;color:inherit;">
				<span class="dashicons dashicons-calendar-alt" style="vertical-align:middle;"></span>
				<?php esc_html_e( 'Year:', 'tradeschool-manager' ); ?>
			</label>
			<select name="<?php echo esc_attr( self::QUERY_PARAM ); ?>" onchange="this.form.submit()" style="min-width:150px;">
				<?php foreach ( $years as $y ) :
					$label = $y->name;
					if ( ! empty( $y->archived ) ) { $label .= ' ' . __( '(archived)', 'tradeschool-manager' ); }
					?>
					<option value="<?php echo esc_attr( $y->id ); ?>" <?php selected( $current, (int) $y->id ); ?>><?php echo esc_html( $label ); ?></option>
				<?php endforeach; ?>
			</select>
		</form>
		<?php
	}
}
