<?php
/**
 * Teacher portal shortcodes.
 *
 * Shortcodes:
 *   [tsm_teacher_login]   - stand-alone login form
 *   [tsm_teacher_portal]  - main teacher dashboard with class list / grade entry / attendance
 *
 * Self-registration is intentionally NOT provided. Teacher accounts are
 * created in TradeSchool > Teachers (admin only).
 *
 * @package TradeSchoolManager
 */

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

class TSM_Teacher_Shortcodes {

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

	private function __construct() {
		add_shortcode( 'tsm_teacher_login',  array( $this, 'sc_login' ) );
		add_shortcode( 'tsm_teacher_portal', array( $this, 'sc_portal' ) );
	}

	public function sc_login() {
		wp_enqueue_style( 'tsm-public' );
		// Logout handled at init by TSM_Teacher_Portal::maybe_handle_logout().
		$tid    = TSM_Teacher_Portal::current_teacher_id();
		$school = tsm_get_setting( 'school_name', 'TradeSchool' );
		ob_start();
		echo '<div class="tsm-portal-wrap">';
		if ( $tid ) {
			$t = TSM_Teachers::get( $tid );
			$portal_url = TSM_Public::get_page_url( 'teacher_portal_page', remove_query_arg( array( 'assignment_edit', 'tsm_t_login_error' ) ) );
			if ( $portal_url && ! self::is_current_url( $portal_url ) && ! headers_sent() ) {
				wp_safe_redirect( $portal_url );
				exit;
			}
			echo wp_kses_post( $this->already_signed_in_card(
				$t ? trim( $t->first_name . ' ' . $t->last_name ) : '',
				$portal_url,
				add_query_arg( 'tsm_teacher_logout', 1, remove_query_arg( array( 'assignment_edit', 'tsm_t_login_error' ) ) ),
				__( 'You are already signed in to the teacher portal.', 'tradeschool-manager' ),
				__( 'Continue to Teacher Portal', 'tradeschool-manager' )
			) );
		} else {
			?>
			<div class="tsm-auth-shell">
				<div class="tsm-auth-card">
					<h2 class="tsm-auth-title"><?php echo esc_html( $school ); ?></h2>
					<p class="tsm-auth-sub"><?php esc_html_e( 'Teacher Portal Sign In', 'tradeschool-manager' ); ?></p>
					<?php if ( isset( $_GET['tsm_t_login_error'] ) ) : // phpcs:ignore ?>
						<div class="tsm-error"><?php esc_html_e( 'Invalid teacher username or password.', 'tradeschool-manager' ); ?></div>
					<?php endif; ?>
					<form method="post" class="tsm-login-form">
						<?php wp_nonce_field( 'tsm_teacher_login', 'tsm_teacher_login_nonce' ); ?>
						<input type="hidden" name="tsm_teacher_login" value="1">
						<label class="tsm-field">
							<span><?php esc_html_e( 'Username', 'tradeschool-manager' ); ?></span>
							<input type="text" name="tsm_teacher_username" autocomplete="username" required>
						</label>
						<label class="tsm-field">
							<span><?php esc_html_e( 'Password', 'tradeschool-manager' ); ?></span>
							<input type="password" name="tsm_teacher_password" autocomplete="current-password" required>
						</label>
						<button type="submit" class="tsm-btn tsm-btn--primary tsm-btn--block"><?php esc_html_e( 'Sign In', 'tradeschool-manager' ); ?></button>
					</form>
					<p class="tsm-auth-note"><?php esc_html_e( 'Accounts are issued by your school administrator.', 'tradeschool-manager' ); ?></p>
				</div>
			</div>
			<?php
		}
		echo '</div>';
		return ob_get_clean();
	}

	private static function is_current_url( $url ) {
		$host        = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : '';
		$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
		$current     = ( is_ssl() ? 'https://' : 'http://' ) . $host . $request_uri;
		return untrailingslashit( strtok( $current, '?' ) ) === untrailingslashit( strtok( $url, '?' ) );
	}

	private function already_signed_in_card( $name, $portal_url, $logout_url, $message, $button_label ) {
		$name = $name ?: __( 'your account', 'tradeschool-manager' );
		ob_start();
		?>
		<div class="tsm-auth-shell">
			<div class="tsm-auth-card tsm-auth-card--status">
				<div class="tsm-auth-badge"><?php esc_html_e( 'Signed in', 'tradeschool-manager' ); ?></div>
				<h2 class="tsm-auth-title"><?php echo esc_html( $message ); ?></h2>
				<p class="tsm-auth-note">
					<?php
					printf(
						/* translators: %s: account name. */
						esc_html__( 'You are signed in as %s.', 'tradeschool-manager' ),
						esc_html( $name )
					);
					?>
				</p>
				<div class="tsm-auth-actions">
					<a class="tsm-btn tsm-btn--primary" href="<?php echo esc_url( $portal_url ); ?>"><?php echo esc_html( $button_label ); ?></a>
					<a class="tsm-btn tsm-btn--ghost" href="<?php echo esc_url( $logout_url ); ?>"><?php esc_html_e( 'Log out', 'tradeschool-manager' ); ?></a>
				</div>
			</div>
		</div>
		<?php
		return ob_get_clean();
	}

	public function sc_portal() {
		wp_enqueue_style( 'tsm-public' );
		// Logout handled at init by TSM_Teacher_Portal::maybe_handle_logout().
		$tid = TSM_Teacher_Portal::current_teacher_id();
		if ( ! $tid ) {
			return $this->sc_login();
		}
		$teacher = TSM_Teachers::get( $tid );
		$view    = isset( $_GET['tsm_view'] ) ? sanitize_key( $_GET['tsm_view'] ) : 'classes'; // phpcs:ignore
		$school  = tsm_get_setting( 'school_name', 'TradeSchool' );

		// Quick stats for hero tiles. Honor the global active-year selection
		// so a teacher's view always reflects the year they're working in.
		$active_year = class_exists( 'TSM_Active_Year' ) ? TSM_Active_Year::get() : 0;
		$classes = TSM_Classes::classes_for_teacher( $tid, $active_year );
		$class_count   = count( $classes );
		$student_count = 0;
		$assign_count  = 0;
		foreach ( $classes as $c ) {
			$student_count += count( TSM_Classes::students_in_class( $c->id ) );
			$assign_count  += count( TSM_Assignments::for_class( $c->id ) );
		}
		$portal_stats = apply_filters( 'tradeschool_manager_teacher_portal_stats', array(
			array(
				'value' => $class_count,
				'label' => __( 'Classes', 'tradeschool-manager' ),
			),
			array(
				'value' => $student_count,
				'label' => __( 'Students', 'tradeschool-manager' ),
			),
			array(
				'value' => $assign_count,
				'label' => __( 'Assignments', 'tradeschool-manager' ),
			),
		), $tid, $teacher );
		$initials = strtoupper( substr( $teacher->first_name, 0, 1 ) . substr( $teacher->last_name, 0, 1 ) );

		// Pre-compute current class id (if drilled into one) so we can show
		// a contextual sidebar tab without losing the user's place.
		$current_cid = absint( $_GET['cid'] ?? 0 ); // phpcs:ignore
		$current_class = $current_cid ? TSM_Classes::get( $current_cid ) : null;
		if ( $current_class && ! TSM_Teacher_Portal::teacher_owns_class( $tid, $current_cid ) ) {
			$current_class = null;
		}
		$portal_uid = 'tsm_teacher_portal_' . wp_generate_password( 6, false, false );
		ob_start();
		TSM_Inline_Assets::script(
			'tsm-teacher-portal-tabs-' . $portal_uid,
			'(function(){
				function ready(fn){
					if (document.readyState === "loading") {
						document.addEventListener("DOMContentLoaded", fn);
					} else {
						fn();
					}
				}
				ready(function(){
					var wrap = document.getElementById(' . wp_json_encode( $portal_uid ) . ');
					if (!wrap) return;
					var subtabs = wrap.querySelectorAll(\'.tsm-subtab[data-sub]\');
					var subpanels = wrap.querySelectorAll(\'.tsm-subpanel[data-subpanel]\');
					subtabs.forEach(function(t){
						t.addEventListener(\'click\', function(e){
							e.preventDefault();
							subtabs.forEach(function(x){ x.classList.remove(\'is-active\'); });
							subpanels.forEach(function(p){ p.classList.remove(\'is-active\'); });
							t.classList.add(\'is-active\');
							var key = t.getAttribute(\'data-sub\');
							var panel = wrap.querySelector(\'.tsm-subpanel[data-subpanel="\'+key+\'"]\');
							if (panel) panel.classList.add(\'is-active\');
						});
					});
				});
			})();'
		);
		$classes_url = remove_query_arg( array( 'tsm_view', 'cid', 'aid', 'assignment_edit', 'saved', 'ctab', 'composer_done', 'sub', 'tsm_info_saved', 'tsm_pw_error', 'tsm_pw_done' ) );
		$settings_url = add_query_arg( array( 'tsm_view' => 'settings' ), $classes_url );
		$is_classes_tab  = ( 'classes' === $view );
		$is_class_tab    = in_array( $view, array( 'class', 'assignment', 'attendance' ), true ) && $current_class;
		$is_settings_tab = ( 'settings' === $view );

		?>
		<div class="tsm-portal-wrap tsm-teacher-portal" id="<?php echo esc_attr( $portal_uid ); ?>">

			<!-- Sidebar nav (lifted into the console shell by the portal-theme JS). -->
			<nav class="tsm-tabs" role="tablist">
				<a class="tsm-tab<?php echo $is_classes_tab ? ' is-active' : ''; ?>" href="<?php echo esc_url( $classes_url ); ?>"><?php esc_html_e( 'My Classes', 'tradeschool-manager' ); ?></a>
				<?php if ( $is_class_tab ) : ?>
					<a class="tsm-tab is-active" href="<?php echo esc_url( add_query_arg( array( 'tsm_view' => 'class', 'cid' => $current_cid ), remove_query_arg( array( 'aid', 'assignment_edit', 'saved', 'composer_done' ) ) ) . '#tsm-teacher-class-' . (int) $current_cid ); ?>"><?php echo esc_html( $current_class->name ); ?></a>
				<?php endif; ?>
				<?php do_action( 'tradeschool_manager_teacher_portal_nav_items', $view, $tid, $classes_url ); ?>
				<a class="tsm-tab<?php echo $is_settings_tab ? ' is-active' : ''; ?>" href="<?php echo esc_url( $settings_url ); ?>"><?php esc_html_e( 'Settings', 'tradeschool-manager' ); ?></a>
			</nav>

			<!-- Identity card  -  rewire script clones the avatar+name into the sidebar. -->
			<div class="tsm-profile-card tsm-teacher-hero">
				<div class="tsm-cover"></div>
				<div class="tsm-teacher-hero-body">
					<?php if ( ! empty( $teacher->photo_url ) ) : ?>
						<img class="tsm-avatar tsm-teacher-hero-avatar" src="<?php echo esc_url( $teacher->photo_url ); ?>" alt="" style="object-fit:cover;">
					<?php else : ?>
						<div class="tsm-avatar tsm-avatar--initials tsm-teacher-hero-avatar"><?php echo esc_html( $initials ); ?></div>
					<?php endif; ?>
					<div class="tsm-teacher-hero-identity">
						<h2 class="tsm-name"><?php echo esc_html( $teacher->first_name . ' ' . $teacher->last_name ); ?></h2>
						<p class="tsm-tagline">
							<span class="tsm-tagline-school"><?php echo esc_html( $school ); ?></span>
							<span class="tsm-tagline-sep">|</span>
							<span><?php esc_html_e( 'Teacher', 'tradeschool-manager' ); ?></span>
						</p>
					</div>
					<div class="tsm-teacher-hero-actions">
						<?php if ( class_exists( 'TSM_Active_Year' ) ) : ?>
							<span class="tsm-teacher-year-switcher">
								<?php TSM_Active_Year::render_switcher( 'teacher' ); ?>
							</span>
						<?php endif; ?>
					</div>
				</div>
				<div class="tsm-stats">
					<?php foreach ( $portal_stats as $stat ) : ?>
						<div class="tsm-stat"><span class="tsm-stat-num"><?php echo esc_html( $stat['value'] ?? '' ); ?></span><span class="tsm-stat-lbl"><?php echo esc_html( $stat['label'] ?? '' ); ?></span></div>
					<?php endforeach; ?>
				</div>
			</div>

			<?php if ( ! empty( $_GET['saved'] ) && in_array( $view, array( 'assignment', 'attendance' ), true ) ) : // phpcs:ignore ?>
				<div class="tsm-success" style="margin:16px 0;"><?php esc_html_e( 'Saved.', 'tradeschool-manager' ); ?></div>
			<?php endif; ?>

			<div class="tsm-card tsm-card--pad" style="margin-top:18px;">
				<?php
				switch ( $view ) {
					case 'class':
						$this->view_class( $tid, $current_cid );
						break;
					case 'assignment':
						$this->view_assignment( $tid, absint( $_GET['aid'] ?? 0 ) ); // phpcs:ignore
						break;
					case 'attendance':
						$this->view_attendance( $tid, absint( $_GET['cid'] ?? 0 ) ); // phpcs:ignore
						break;
					case 'settings':
						$this->view_settings( $teacher );
						break;
					default:
						if ( ! apply_filters( 'tradeschool_manager_teacher_portal_render_view', false, $view, $tid, $teacher ) ) {
							$this->view_classes( $tid );
						}
				}
				?>
			</div>

			<!-- Hidden logout link  -  the portal-theme JS lifts this into the sidebar as the Log out tab. -->
			<a href="<?php echo esc_url( add_query_arg( 'tsm_teacher_logout', 1, remove_query_arg( array( 'assignment_edit', 'saved', 'composer_done', 'aid' ) ) ) ); ?>" style="display:none;"><?php esc_html_e( 'Log out', 'tradeschool-manager' ); ?></a>
		</div>
		<?php
		return ob_get_clean();
	}

	/* -------------------------- Settings -------------------------- */

	private function view_settings( $teacher ) {
		$active_sub = isset( $_GET['sub'] ) ? sanitize_key( wp_unslash( $_GET['sub'] ) ) : 'info'; // phpcs:ignore
		if ( ! in_array( $active_sub, array( 'info', 'password' ), true ) ) { $active_sub = 'info'; }
		$info_saved = isset( $_GET['tsm_info_saved'] ); // phpcs:ignore
		$pw_err     = isset( $_GET['tsm_pw_error'] ) ? sanitize_text_field( wp_unslash( $_GET['tsm_pw_error'] ) ) : ''; // phpcs:ignore
		$pw_done    = isset( $_GET['tsm_pw_done'] ); // phpcs:ignore
		$initials   = strtoupper( substr( $teacher->first_name, 0, 1 ) . substr( $teacher->last_name, 0, 1 ) );
		?>
		<section>
			<nav class="tsm-subtabs" role="tablist" style="display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px;border-bottom:1px solid var(--tsm-border,#e5e7eb);padding-bottom:8px;">
				<button type="button" class="tsm-subtab<?php echo 'info' === $active_sub ? ' is-active' : ''; ?>" data-sub="info" role="tab"><?php esc_html_e( 'My Information', 'tradeschool-manager' ); ?></button>
				<button type="button" class="tsm-subtab<?php echo 'password' === $active_sub ? ' is-active' : ''; ?>" data-sub="password" role="tab"><?php esc_html_e( 'Change Password', 'tradeschool-manager' ); ?></button>
			</nav>

			<div class="tsm-subpanel<?php echo 'info' === $active_sub ? ' is-active' : ''; ?>" data-subpanel="info">
				<h3 class="tsm-h3"><?php esc_html_e( 'My Information', 'tradeschool-manager' ); ?></h3>
				<?php if ( $info_saved ) : ?>
					<div class="tsm-success"><?php esc_html_e( 'Your information has been updated.', 'tradeschool-manager' ); ?></div>
				<?php endif; ?>
				<form method="post" enctype="multipart/form-data" class="tsm-login-form" style="max-width:520px;">
					<?php wp_nonce_field( 'tsm_teacher_profile', 'tsm_teacher_profile_nonce' ); ?>
					<div style="display:flex;align-items:center;gap:14px;margin-bottom:14px;">
						<?php if ( ! empty( $teacher->photo_url ) ) : ?>
							<img src="<?php echo esc_url( $teacher->photo_url ); ?>" alt="" style="width:72px;height:72px;border-radius:50%;object-fit:cover;border:1px solid var(--tsm-border,#e5e7eb);">
						<?php else : ?>
							<div style="width:72px;height:72px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--tsm-brand,#1f6feb);color:#fff;font-weight:600;font-size:22px;"><?php echo esc_html( $initials ); ?></div>
						<?php endif; ?>
						<label class="tsm-field" style="flex:1;margin:0;">
							<span><?php esc_html_e( 'Profile photo', 'tradeschool-manager' ); ?></span>
							<input type="file" name="photo_file" accept="image/png,image/jpeg,image/webp">
						</label>
					</div>
					<label class="tsm-field"><span><?php esc_html_e( 'Email', 'tradeschool-manager' ); ?></span><input type="email" name="tsm_email" value="<?php echo esc_attr( $teacher->email ); ?>" autocomplete="email"></label>
					<label class="tsm-field"><span><?php esc_html_e( 'Phone', 'tradeschool-manager' ); ?></span><input type="tel" name="tsm_phone" value="<?php echo esc_attr( $teacher->phone ); ?>" autocomplete="tel"></label>
					<button type="submit" class="tsm-btn tsm-btn--primary"><?php esc_html_e( 'Save Changes', 'tradeschool-manager' ); ?></button>
				</form>
			</div>

			<div class="tsm-subpanel<?php echo 'password' === $active_sub ? ' is-active' : ''; ?>" data-subpanel="password">
				<h3 class="tsm-h3"><?php esc_html_e( 'Change Password', 'tradeschool-manager' ); ?></h3>
				<?php if ( $pw_done ) : ?>
					<div class="tsm-success"><?php esc_html_e( 'Password updated successfully.', 'tradeschool-manager' ); ?></div>
				<?php endif;
				if ( 'current' === $pw_err ) : ?>
					<div class="tsm-error"><?php esc_html_e( 'Current password is incorrect.', 'tradeschool-manager' ); ?></div>
				<?php elseif ( 'short' === $pw_err ) : ?>
					<div class="tsm-error"><?php esc_html_e( 'New password must be at least 8 characters.', 'tradeschool-manager' ); ?></div>
				<?php elseif ( 'mismatch' === $pw_err ) : ?>
					<div class="tsm-error"><?php esc_html_e( 'New passwords do not match.', 'tradeschool-manager' ); ?></div>
				<?php elseif ( 'session' === $pw_err ) : ?>
					<div class="tsm-error"><?php esc_html_e( 'Your session expired. Please sign in again.', 'tradeschool-manager' ); ?></div>
				<?php endif; ?>
				<form method="post" class="tsm-login-form" style="max-width:420px;">
					<?php wp_nonce_field( 'tsm_teacher_change_pw', 'tsm_teacher_change_pw_nonce' ); ?>
					<label class="tsm-field"><span><?php esc_html_e( 'Current password', 'tradeschool-manager' ); ?></span><input type="password" name="tsm_current_password" autocomplete="current-password" required></label>
					<label class="tsm-field"><span><?php esc_html_e( 'New password', 'tradeschool-manager' ); ?></span><input type="password" name="tsm_new_password" autocomplete="new-password" required></label>
					<label class="tsm-field"><span><?php esc_html_e( 'Confirm new password', 'tradeschool-manager' ); ?></span><input type="password" name="tsm_new_password2" autocomplete="new-password" required></label>
					<button type="submit" class="tsm-btn tsm-btn--primary"><?php esc_html_e( 'Update Password', 'tradeschool-manager' ); ?></button>
				</form>
			</div>
		</section>
		<?php
	}

	/* -------------------------- Views -------------------------- */

	private function view_classes( $tid ) {
		$active_year = class_exists( 'TSM_Active_Year' ) ? TSM_Active_Year::get() : 0;
		$classes     = TSM_Classes::classes_for_teacher( $tid, $active_year );
		$year_label  = '';
		if ( $active_year && class_exists( 'TSM_School_Years' ) ) {
			$y = TSM_School_Years::get( $active_year );
			if ( $y ) { $year_label = $y->name; }
		} elseif ( ! $active_year ) {
			$year_label = __( 'All years', 'tradeschool-manager' );
		}
		?>
		<section>
			<div class="tsm-section-head">
				<h3><?php esc_html_e( 'My Classes', 'tradeschool-manager' ); ?>
					<?php if ( $year_label ) : ?><span class="tsm-section-meta"> -  <?php echo esc_html( $year_label ); ?></span><?php endif; ?>
				</h3>
				<span class="tsm-section-count"><?php echo (int) count( $classes ); ?> <?php esc_html_e( 'total', 'tradeschool-manager' ); ?></span>
			</div>

			<?php if ( empty( $classes ) ) : ?>
				<p class="tsm-empty"><?php echo esc_html( $active_year ? __( 'No classes assigned to you for this school year. Use the year selector above to switch years.', 'tradeschool-manager' ) : __( 'No classes have been assigned to you yet.', 'tradeschool-manager' ) ); ?></p>
			<?php else : ?>
				<div class="tsm-tcard-grid">
					<?php foreach ( $classes as $c ) :
						$students = TSM_Classes::students_in_class( $c->id );
						$count    = count( $students );
						$pcts     = array();
						foreach ( $students as $s ) {
							$g = TSM_Gradebook::calc_class_grade( $c->id, $s->id );
							if ( null !== $g['percent'] ) { $pcts[] = (float) $g['percent']; }
						}
						$avg = $pcts ? round( array_sum( $pcts ) / count( $pcts ), 1 ) : null;
						?>
						<div class="tsm-tcard">
							<div class="tsm-tcard-head">
								<h4 class="tsm-tcard-title"><?php echo esc_html( $c->name ); ?></h4>
								<span class="tsm-tcard-avg<?php echo ( null === $avg ) ? ' is-empty' : ''; ?>">
									<?php echo ( null === $avg ) ? ' - ' : esc_html( $avg . '%' ); ?>
								</span>
							</div>
							<div class="tsm-tcard-meta">
								<span><strong><?php echo (int) $count; ?></strong> <?php echo esc_html( _n( 'student', 'students', $count, 'tradeschool-manager' ) ); ?></span>
								<span class="tsm-tcard-meta-sep">|</span>
								<span><?php esc_html_e( 'Class average', 'tradeschool-manager' ); ?></span>
							</div>
							<div class="tsm-tcard-actions">
								<a class="tsm-btn tsm-btn--primary" href="<?php echo esc_url( add_query_arg( array( 'tsm_view' => 'class', 'cid' => $c->id ), remove_query_arg( array( 'aid', 'assignment_edit', 'saved', 'composer_done' ) ) ) . '#tsm-teacher-class-' . (int) $c->id ); ?>"><?php esc_html_e( 'Manage', 'tradeschool-manager' ); ?></a>
								<?php if ( class_exists( 'TSMP_Attendance' ) ) : ?>
									<a class="tsm-btn" href="<?php echo esc_url( add_query_arg( array( 'tsm_view' => 'attendance', 'cid' => $c->id ), remove_query_arg( array( 'aid', 'assignment_edit', 'saved', 'composer_done' ) ) ) ); ?>"><?php esc_html_e( 'Attendance', 'tradeschool-manager' ); ?></a>
								<?php endif; ?>
							</div>
						</div>
					<?php endforeach; ?>
				</div>
			<?php endif; ?>
		</section>
		<?php
	}

	private function view_class( $tid, $cid ) {
		if ( ! TSM_Teacher_Portal::teacher_owns_class( $tid, $cid ) ) {
			echo '<div class="tsm-error">' . esc_html__( 'You do not have access to this class.', 'tradeschool-manager' ) . '</div>';
			return;
		}
		$class       = TSM_Classes::get( $cid );
		$students    = TSM_Classes::students_in_class( $cid );
		$assignments = TSM_Assignments::for_class( $cid ); // already ORDER BY due_date ASC
		$method      = $class && $class->grading_method ? $class->grading_method : 'points';
		$is_weighted = ( 'weighted' === $method );
		$is_passfail = ( 'pass_fail' === $method );
		$cats        = $is_weighted ? TSM_Classes::categories( $cid ) : array();
		$ctab        = isset( $_GET['ctab'] ) ? sanitize_key( $_GET['ctab'] ) : 'roster'; // phpcs:ignore
		$class_anchor = 'tsm-teacher-class-' . (int) $cid;
		$tab_url     = function ( $t ) use ( $cid, $class_anchor ) {
			return esc_url( add_query_arg( array( 'tsm_view' => 'class', 'cid' => $cid, 'ctab' => $t, 'aid' => false, 'assignment_edit' => false, 'saved' => false, 'composer_done' => false ) ) . '#' . $class_anchor );
		};
		$csv_url     = wp_nonce_url(
			add_query_arg( array( 'tsm_teacher_action' => 'export_roster', 'cid' => $cid ), home_url( '/' ) ),
			'tsm_teacher_export_roster'
		);
		$done        = isset( $_GET['composer_done'] ) ? sanitize_key( $_GET['composer_done'] ) : ''; // phpcs:ignore
		$assignment_edit_id = isset( $_GET['assignment_edit'] ) ? absint( $_GET['assignment_edit'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only edit state.
		$editing_assignment = null;
		if ( $assignment_edit_id ) {
			foreach ( $assignments as $assignment_candidate ) {
				if ( (int) $assignment_candidate->id === $assignment_edit_id ) {
					$editing_assignment = $assignment_candidate;
					break;
				}
			}
		}

		$method_lbl = $is_weighted ? __( 'Weighted Categories', 'tradeschool-manager' ) : ( $is_passfail ? __( 'Pass / Fail', 'tradeschool-manager' ) : __( 'Points', 'tradeschool-manager' ) );
		?>
		<section id="<?php echo esc_attr( $class_anchor ); ?>" class="tsm-teacher-class-section">
			<div class="tsm-class-head">
				<div>
					<h3 style="margin:0;"><?php echo esc_html( $class->name ); ?></h3>
					<?php if ( ! empty( $class->description ) ) : ?><p style="margin:6px 0 0;color:var(--tsm-muted,#6b7280);"><?php echo esc_html( $class->description ); ?></p><?php endif; ?>
				</div>
				<span class="tsm-pill" title="<?php esc_attr_e( 'Grading method', 'tradeschool-manager' ); ?>"><?php echo esc_html( $method_lbl ); ?></span>
			</div>

			<?php if ( 'assignment' === $done ) : ?>
				<div class="tsm-success" style="margin:12px 0;"><?php esc_html_e( 'Assignment created.', 'tradeschool-manager' ); ?></div>
			<?php elseif ( 'assignment_updated' === $done ) : ?>
				<div class="tsm-success" style="margin:12px 0;"><?php esc_html_e( 'Assignment updated.', 'tradeschool-manager' ); ?></div>
			<?php elseif ( 'assignment_error' === $done ) : ?>
				<div class="tsm-error" style="margin:12px 0;"><?php esc_html_e( 'Assignment could not be saved. Please refresh the page and try again.', 'tradeschool-manager' ); ?></div>
			<?php elseif ( 'announcement' === $done ) : ?>
				<div class="tsm-success" style="margin:12px 0;"><?php esc_html_e( 'Announcement posted to the school portal.', 'tradeschool-manager' ); ?></div>
			<?php elseif ( 'announcement_updated' === $done ) : ?>
				<div class="tsm-success" style="margin:12px 0;"><?php esc_html_e( 'Announcement updated.', 'tradeschool-manager' ); ?></div>
			<?php elseif ( 'announcement_deleted' === $done ) : ?>
				<div class="tsm-success" style="margin:12px 0;"><?php esc_html_e( 'Announcement deleted.', 'tradeschool-manager' ); ?></div>
			<?php elseif ( 'announcement_error' === $done ) : ?>
				<div class="tsm-error" style="margin:12px 0;"><?php esc_html_e( 'Announcement could not be saved. Please refresh the page and try again.', 'tradeschool-manager' ); ?></div>
			<?php endif; ?>

			<nav class="tsm-subtabs" role="tablist">
				<a class="tsm-subtab <?php echo $ctab === 'roster' ? 'is-active' : ''; ?>" href="<?php echo esc_url( $tab_url( 'roster' ) ); ?>"><?php esc_html_e( 'Roster', 'tradeschool-manager' ); ?> <span class="tsm-subtab-count"><?php echo (int) count( $students ); ?></span></a>
				<a class="tsm-subtab <?php echo $ctab === 'assignments' ? 'is-active' : ''; ?>" href="<?php echo esc_url( $tab_url( 'assignments' ) ); ?>"><?php esc_html_e( 'Assignments', 'tradeschool-manager' ); ?> <span class="tsm-subtab-count"><?php echo (int) count( $assignments ); ?></span></a>
				<a class="tsm-subtab <?php echo $ctab === 'announcements' ? 'is-active' : ''; ?>" href="<?php echo esc_url( $tab_url( 'announcements' ) ); ?>"><?php esc_html_e( 'Announcements', 'tradeschool-manager' ); ?></a>
			</nav>

			<?php if ( 'roster' === $ctab ) : ?>
				<div class="tsm-tab-actions">
					<a class="tsm-btn-sm" href="<?php echo esc_url( $csv_url ); ?>"><?php esc_html_e( 'Export CSV', 'tradeschool-manager' ); ?></a>
				</div>
				<?php if ( empty( $students ) ) : ?>
					<p class="tsm-empty"><?php esc_html_e( 'No students enrolled yet.', 'tradeschool-manager' ); ?></p>
				<?php else : ?>
					<table class="tsm-table tsm-stack-table">
						<thead><tr>
							<th><?php esc_html_e( 'Student', 'tradeschool-manager' ); ?></th>
							<th><?php esc_html_e( 'Email', 'tradeschool-manager' ); ?></th>
							<th><?php esc_html_e( 'Current Grade', 'tradeschool-manager' ); ?></th>
							<th></th>
						</tr></thead>
						<tbody>
						<?php foreach ( $students as $s ) :
							$g = TSM_Gradebook::calc_class_grade( $cid, $s->id );
							if ( null === $g['percent'] ) {
								$grade = ' - ';
							} elseif ( $is_passfail ) {
								$grade = $g['letter'] ?: ' - ';
							} else {
								$grade = $g['percent'] . '% (' . $g['letter'] . ')';
							} ?>
							<tr>
								<td data-label="<?php esc_attr_e( 'Student', 'tradeschool-manager' ); ?>"><?php echo esc_html( $s->last_name . ', ' . $s->first_name ); ?></td>
								<td data-label="<?php esc_attr_e( 'Email', 'tradeschool-manager' ); ?>"><?php if ( ! empty( $s->email ) ) : ?><a href="mailto:<?php echo esc_attr( $s->email ); ?>"><?php echo esc_html( $s->email ); ?></a><?php else : ?> - <?php endif; ?></td>
								<td data-label="<?php esc_attr_e( 'Current Grade', 'tradeschool-manager' ); ?>"><?php echo esc_html( $grade ); ?></td>
								<td data-label=""><?php if ( ! empty( $s->email ) ) : ?><a class="tsm-btn-sm" href="mailto:<?php echo esc_attr( $s->email ); ?>?subject=<?php echo rawurlencode( $class->name ); ?>"><?php esc_html_e( 'Email', 'tradeschool-manager' ); ?></a><?php endif; ?></td>
							</tr>
						<?php endforeach; ?>
						</tbody>
					</table>
				<?php endif; ?>

			<?php elseif ( 'assignments' === $ctab ) : ?>
				<details class="tsm-composer tsm-composer--primary tsm-collapsible-composer" <?php echo empty( $assignments ) ? 'open' : ''; ?>>
					<summary><?php esc_html_e( 'Add New Assignment', 'tradeschool-manager' ); ?></summary>
					<form method="post" class="tsm-composer-form">
						<?php wp_nonce_field( 'tsm_teacher_create_assignment' ); ?>
						<input type="hidden" name="tsm_teacher_action" value="create_assignment">
						<input type="hidden" name="class_id" value="<?php echo (int) $cid; ?>">
						<input type="hidden" name="grading_method" value="<?php echo esc_attr( $method ); ?>">

						<label class="tsm-field"><span><?php esc_html_e( 'Title', 'tradeschool-manager' ); ?></span><input type="text" name="title" required></label>

						<?php if ( ! $is_passfail ) : ?>
							<div class="tsm-field-row">
								<label class="tsm-field"><span><?php esc_html_e( 'Category', 'tradeschool-manager' ); ?></span>
									<?php if ( $is_weighted && ! empty( $cats ) ) : ?>
										<select name="category">
											<option value=""><?php esc_html_e( 'Uncategorized', 'tradeschool-manager' ); ?></option>
											<?php foreach ( $cats as $cn ) : ?>
												<option value="<?php echo esc_attr( $cn ); ?>"><?php echo esc_html( $cn ); ?></option>
											<?php endforeach; ?>
										</select>
									<?php else : ?>
										<input type="text" name="category" placeholder="<?php esc_attr_e( 'e.g. Homework', 'tradeschool-manager' ); ?>">
									<?php endif; ?>
								</label>
								<label class="tsm-field"><span><?php esc_html_e( 'Points Possible', 'tradeschool-manager' ); ?></span><input type="number" name="points_possible" step="0.01" min="0" value="100"></label>
							</div>
						<?php else : ?>
							<input type="hidden" name="points_possible" value="1">
						<?php endif; ?>

						<div class="tsm-field-row">
							<label class="tsm-field"><span><?php esc_html_e( 'Assigned Date', 'tradeschool-manager' ); ?></span><input type="text" name="assigned_date" placeholder="MM/DD/YYYY"></label>
							<label class="tsm-field"><span><?php esc_html_e( 'Due Date', 'tradeschool-manager' ); ?></span><input type="text" name="due_date" placeholder="MM/DD/YYYY"></label>
						</div>

						<label class="tsm-field"><span><?php esc_html_e( 'Description', 'tradeschool-manager' ); ?></span><textarea name="description" rows="3"></textarea></label>

						<?php if ( ! $is_passfail ) : ?>
							<div class="tsm-field-row">
								<label class="tsm-check"><input type="checkbox" name="extra_credit" value="1"> <?php esc_html_e( 'Extra credit', 'tradeschool-manager' ); ?></label>
								<label class="tsm-check"><input type="checkbox" name="required" value="1" checked> <?php esc_html_e( 'Required', 'tradeschool-manager' ); ?></label>
							</div>
						<?php else : ?>
							<label class="tsm-check"><input type="checkbox" name="required" value="1" checked> <?php esc_html_e( 'Required', 'tradeschool-manager' ); ?></label>
						<?php endif; ?>

						<button type="submit" class="tsm-btn tsm-btn--primary"><?php esc_html_e( 'Create Assignment', 'tradeschool-manager' ); ?></button>
					</form>
				</details>

				<?php if ( $editing_assignment ) : ?>
					<details class="tsm-composer tsm-composer--primary tsm-collapsible-composer" open>
						<summary><?php esc_html_e( 'Edit Assignment', 'tradeschool-manager' ); ?></summary>
						<form method="post" class="tsm-composer-form">
							<?php wp_nonce_field( 'tsm_teacher_update_assignment' ); ?>
							<input type="hidden" name="tsm_teacher_action" value="update_assignment">
							<input type="hidden" name="assignment_id" value="<?php echo (int) $editing_assignment->id; ?>">
							<input type="hidden" name="class_id" value="<?php echo (int) $cid; ?>">
							<input type="hidden" name="grading_method" value="<?php echo esc_attr( $method ); ?>">

							<label class="tsm-field"><span><?php esc_html_e( 'Title', 'tradeschool-manager' ); ?></span><input type="text" name="title" value="<?php echo esc_attr( $editing_assignment->title ); ?>" required></label>

							<?php if ( ! $is_passfail ) : ?>
								<div class="tsm-field-row">
									<label class="tsm-field"><span><?php esc_html_e( 'Category', 'tradeschool-manager' ); ?></span>
										<?php if ( $is_weighted && ! empty( $cats ) ) : ?>
											<select name="category">
												<option value=""><?php esc_html_e( 'Uncategorized', 'tradeschool-manager' ); ?></option>
												<?php foreach ( $cats as $cn ) : ?>
													<option value="<?php echo esc_attr( $cn ); ?>" <?php selected( $editing_assignment->category, $cn ); ?>><?php echo esc_html( $cn ); ?></option>
												<?php endforeach; ?>
											</select>
										<?php else : ?>
											<input type="text" name="category" value="<?php echo esc_attr( $editing_assignment->category ); ?>" placeholder="<?php esc_attr_e( 'e.g. Homework', 'tradeschool-manager' ); ?>">
										<?php endif; ?>
									</label>
									<label class="tsm-field"><span><?php esc_html_e( 'Points Possible', 'tradeschool-manager' ); ?></span><input type="number" name="points_possible" step="0.01" min="0" value="<?php echo esc_attr( $editing_assignment->points_possible ); ?>"></label>
								</div>
							<?php else : ?>
								<input type="hidden" name="points_possible" value="1">
							<?php endif; ?>

							<div class="tsm-field-row">
								<label class="tsm-field"><span><?php esc_html_e( 'Assigned Date', 'tradeschool-manager' ); ?></span><input type="text" name="assigned_date" value="<?php echo esc_attr( TSM_Date_Utils::display( $editing_assignment->assigned_date ?? '' ) ); ?>" placeholder="MM/DD/YYYY"></label>
								<label class="tsm-field"><span><?php esc_html_e( 'Due Date', 'tradeschool-manager' ); ?></span><input type="text" name="due_date" value="<?php echo esc_attr( TSM_Date_Utils::display( $editing_assignment->due_date ?? '' ) ); ?>" placeholder="MM/DD/YYYY"></label>
							</div>

							<label class="tsm-field"><span><?php esc_html_e( 'Description', 'tradeschool-manager' ); ?></span><textarea name="description" rows="3"><?php echo esc_textarea( $editing_assignment->description ); ?></textarea></label>

							<?php if ( ! $is_passfail ) : ?>
								<div class="tsm-field-row">
									<label class="tsm-check"><input type="checkbox" name="extra_credit" value="1" <?php checked( ! empty( $editing_assignment->extra_credit ) ); ?>> <?php esc_html_e( 'Extra credit', 'tradeschool-manager' ); ?></label>
									<label class="tsm-check"><input type="checkbox" name="required" value="1" <?php checked( ! empty( $editing_assignment->required ) ); ?>> <?php esc_html_e( 'Required', 'tradeschool-manager' ); ?></label>
								</div>
							<?php else : ?>
								<label class="tsm-check"><input type="checkbox" name="required" value="1" <?php checked( ! empty( $editing_assignment->required ) ); ?>> <?php esc_html_e( 'Required', 'tradeschool-manager' ); ?></label>
							<?php endif; ?>

							<div class="tsm-row-actions">
								<button type="submit" class="tsm-btn tsm-btn--primary"><?php esc_html_e( 'Update Assignment', 'tradeschool-manager' ); ?></button>
								<a class="tsm-btn tsm-btn--ghost" href="<?php echo esc_url( add_query_arg( array( 'tsm_view' => 'class', 'cid' => $cid, 'ctab' => 'assignments' ), remove_query_arg( array( 'assignment_edit', 'saved', 'composer_done', 'aid' ) ) ) . '#' . $class_anchor ); ?>"><?php esc_html_e( 'Cancel', 'tradeschool-manager' ); ?></a>
							</div>
						</form>
					</details>
				<?php endif; ?>

				<h4 class="tsm-section-title"><?php esc_html_e( 'Assignments', 'tradeschool-manager' ); ?></h4>
				<?php if ( empty( $assignments ) ) : ?>
					<p class="tsm-empty"><?php esc_html_e( 'No assignments yet. Create the first one above.', 'tradeschool-manager' ); ?></p>
				<?php else : ?>
					<table class="tsm-table tsm-stack-table">
						<thead><tr>
							<th><?php esc_html_e( 'Assignment', 'tradeschool-manager' ); ?></th>
							<th><?php esc_html_e( 'Due', 'tradeschool-manager' ); ?></th>
							<th><?php esc_html_e( 'Type', 'tradeschool-manager' ); ?></th>
							<?php if ( ! $is_passfail ) : ?><th><?php esc_html_e( 'Value', 'tradeschool-manager' ); ?></th><?php endif; ?>
							<th><?php esc_html_e( 'Graded', 'tradeschool-manager' ); ?></th>
							<th><?php esc_html_e( 'Avg Grade', 'tradeschool-manager' ); ?></th>
							<th></th>
						</tr></thead>
						<tbody>
						<?php foreach ( $assignments as $a ) :
							$sum_pct = 0; $n_pct = 0;
							foreach ( $students as $s ) {
								$g = TSM_Gradebook::get_grade( $a->id, $s->id );
								$total = TSM_Gradebook::total_for( $g );
								if ( null === $total || (float) $a->points_possible <= 0 ) { continue; }
								$sum_pct += ( $total / (float) $a->points_possible ) * 100;
								$n_pct++;
							}
							$avg = $n_pct ? round( $sum_pct / $n_pct, 2 ) . '%' : ' - ';
							?>
							<tr>
								<td data-label="<?php esc_attr_e( 'Assignment', 'tradeschool-manager' ); ?>"><strong><?php echo esc_html( $a->title ); ?></strong><?php if ( ! $is_passfail && $a->category ) : ?><br><small><?php echo esc_html( $a->category ); ?></small><?php endif; ?></td>
								<td data-label="<?php esc_attr_e( 'Due', 'tradeschool-manager' ); ?>"><?php echo esc_html( TSM_Date_Utils::display( $a->due_date ?? '' ) ); ?></td>
								<td data-label="<?php esc_attr_e( 'Type', 'tradeschool-manager' ); ?>"><?php echo $a->extra_credit ? esc_html__( 'Extra Credit', 'tradeschool-manager' ) : esc_html__( 'Standard', 'tradeschool-manager' ); ?></td>
								<?php if ( ! $is_passfail ) : ?><td data-label="<?php esc_attr_e( 'Value', 'tradeschool-manager' ); ?>"><?php echo esc_html( $a->points_possible ); ?></td><?php endif; ?>
								<td data-label="<?php esc_attr_e( 'Graded', 'tradeschool-manager' ); ?>"><?php echo (int) $n_pct; ?>/<?php echo (int) count( $students ); ?></td>
								<td data-label="<?php esc_attr_e( 'Avg Grade', 'tradeschool-manager' ); ?>"><?php echo esc_html( $avg ); ?></td>
								<td data-label="">
									<div class="tsm-row-actions">
										<a class="tsm-btn-sm" href="<?php echo esc_url( add_query_arg( array( 'tsm_view' => 'class', 'cid' => $cid, 'ctab' => 'assignments', 'assignment_edit' => $a->id ), remove_query_arg( array( 'saved', 'composer_done', 'aid' ) ) ) . '#' . $class_anchor ); ?>"><?php esc_html_e( 'Edit', 'tradeschool-manager' ); ?></a>
										<a class="tsm-btn-sm tsm-btn--primary" href="<?php echo esc_url( add_query_arg( array( 'tsm_view' => 'assignment', 'aid' => $a->id ), remove_query_arg( array( 'saved', 'composer_done', 'assignment_edit' ) ) ) ); ?>"><?php esc_html_e( 'Enter Grades', 'tradeschool-manager' ); ?></a>
									</div>
								</td>
							</tr>
						<?php endforeach; ?>
						</tbody>
					</table>
				<?php endif; ?>

			<?php elseif ( 'announcements' === $ctab ) : ?>
				<?php if ( class_exists( 'TSM_Announcements' ) ) :
					$class_anns  = method_exists( 'TSM_Announcements', 'for_class' ) ? TSM_Announcements::for_class( $cid ) : array();
					$ann_edit_id = isset( $_GET['ann_edit'] ) ? absint( $_GET['ann_edit'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only edit state.
					$editing_ann = null;
					if ( $ann_edit_id ) {
						foreach ( $class_anns as $candidate ) {
							if ( (int) $candidate->id === $ann_edit_id ) {
								$editing_ann = $candidate;
								break;
							}
						}
					}
					$ann_form_url = add_query_arg(
						array(
							'tsm_view' => 'class',
							'cid'      => $cid,
							'ctab'     => 'announcements',
						),
					remove_query_arg( array( 'assignment_edit', 'composer_done', 'ann_edit' ) )
					);
					?>
					<div class="tsm-composer tsm-composer--primary">
						<h4><?php echo $editing_ann ? esc_html__( 'Edit Announcement', 'tradeschool-manager' ) : esc_html__( 'Post Announcement', 'tradeschool-manager' ); ?></h4>
						<form method="post" action="<?php echo esc_url( $ann_form_url ); ?>" class="tsm-composer-form">
							<?php wp_nonce_field( 'tsm_teacher_post_announcement', 'tsm_teacher_ann_nonce' ); ?>
							<input type="hidden" name="tsm_teacher_action" value="post_announcement">
							<input type="hidden" name="class_id" value="<?php echo (int) $cid; ?>">
							<input type="hidden" name="announcement_id" value="<?php echo $editing_ann ? (int) $editing_ann->id : 0; ?>">
							<label class="tsm-field"><span><?php esc_html_e( 'Title', 'tradeschool-manager' ); ?></span><input type="text" name="title" required maxlength="180" value="<?php echo esc_attr( $editing_ann->title ?? '' ); ?>"></label>
							<label class="tsm-field"><span><?php esc_html_e( 'Message', 'tradeschool-manager' ); ?></span><textarea name="body" required rows="4"><?php echo esc_textarea( $editing_ann->body ?? '' ); ?></textarea></label>
							<label class="tsm-field"><span><?php esc_html_e( 'Show until', 'tradeschool-manager' ); ?></span><input type="date" name="end_date" value="<?php echo esc_attr( $editing_ann->end_date ?? '' ); ?>"></label>
							<label class="tsm-check"><input type="checkbox" name="active" value="1" <?php checked( $editing_ann ? (int) $editing_ann->active : 1, 1 ); ?>> <?php esc_html_e( 'Show on portal', 'tradeschool-manager' ); ?></label>
							<div class="tsm-form-actions">
								<button type="submit" class="tsm-btn tsm-btn--primary"><?php echo $editing_ann ? esc_html__( 'Update Announcement', 'tradeschool-manager' ) : esc_html__( 'Post to Portal', 'tradeschool-manager' ); ?></button>
								<?php if ( $editing_ann ) : ?>
									<a class="tsm-btn-sm" href="<?php echo esc_url( $ann_form_url ); ?>"><?php esc_html_e( 'Cancel Edit', 'tradeschool-manager' ); ?></a>
								<?php endif; ?>
							</div>
						</form>
					</div>

					<h4 class="tsm-section-title"><?php esc_html_e( 'Class Announcements', 'tradeschool-manager' ); ?></h4>
					<?php if ( empty( $class_anns ) ) : ?>
						<p class="tsm-empty"><?php esc_html_e( 'No class announcements yet. Post the first one above.', 'tradeschool-manager' ); ?></p>
					<?php else : ?>
						<ul class="tsm-ann-list">
							<?php foreach ( $class_anns as $r ) :
								$expired  = ( ! empty( $r->end_date ) && $r->end_date < current_time( 'Y-m-d' ) );
								$status   = ! $r->active ? __( 'Hidden', 'tradeschool-manager' ) : ( $expired ? __( 'Expired', 'tradeschool-manager' ) : __( 'Live', 'tradeschool-manager' ) );
								$edit_url = add_query_arg( 'ann_edit', (int) $r->id, $ann_form_url );
								?>
								<li class="tsm-ann-item">
									<div class="tsm-ann-row">
										<div>
											<div class="tsm-ann-title"><?php echo esc_html( $r->title ); ?></div>
											<div class="tsm-ann-meta"><?php echo esc_html( $status ); ?> | <?php /* translators: placeholder(s) for dynamic value(s). */ echo esc_html( mysql2date( get_option( 'date_format' ), $r->created_at ) ); ?><?php if ( ! empty( $r->end_date ) ) : ?> | <?php printf( esc_html__( 'Ends %s', 'tradeschool-manager' ), esc_html( TSM_Date_Utils::display( $r->end_date ) ) ); ?><?php endif; ?></div>
										</div>
										<div class="tsm-ann-actions">
											<a class="tsm-btn-sm" href="<?php echo esc_url( $edit_url ); ?>"><?php esc_html_e( 'Edit', 'tradeschool-manager' ); ?></a>
											<form method="post" action="<?php echo esc_url( $ann_form_url ); ?>" onsubmit="return confirm('<?php echo esc_js( __( 'Delete this announcement?', 'tradeschool-manager' ) ); ?>');">
												<?php wp_nonce_field( 'tsm_teacher_delete_announcement', 'tsm_teacher_ann_delete_nonce' ); ?>
												<input type="hidden" name="tsm_teacher_action" value="delete_announcement">
												<input type="hidden" name="class_id" value="<?php echo (int) $cid; ?>">
												<input type="hidden" name="announcement_id" value="<?php echo (int) $r->id; ?>">
												<button type="submit" class="tsm-btn-sm tsm-btn--danger"><?php esc_html_e( 'Delete', 'tradeschool-manager' ); ?></button>
											</form>
										</div>
									</div>
									<div class="tsm-ann-body"><?php echo wp_kses_post( $r->body ); ?></div>
								</li>
							<?php endforeach; ?>
						</ul>
					<?php endif; ?>
				<?php else : ?>
					<p class="tsm-empty"><?php esc_html_e( 'Announcements are not available.', 'tradeschool-manager' ); ?></p>
				<?php endif; ?>
			<?php endif; ?>
		</section>
		<?php
	}

	private function view_assignment( $tid, $aid ) {
		$assignment = TSM_Assignments::get( $aid );
		if ( ! $assignment || ! TSM_Teacher_Portal::teacher_owns_class( $tid, $assignment->class_id ) ) {
			echo '<div class="tsm-error">' . esc_html__( 'Assignment not found.', 'tradeschool-manager' ) . '</div>';
			return;
		}
		$class       = TSM_Classes::get( $assignment->class_id );
		$method      = $class && $class->grading_method ? $class->grading_method : 'points';
		$is_passfail = ( 'pass_fail' === $method );
		$students    = TSM_Classes::students_in_class( $assignment->class_id );
		?>
		<section>
			<h3><?php echo esc_html( $assignment->title ); ?></h3>
			<p style="color:var(--tsm-muted,#6b7280);">
				<?php if ( $is_passfail ) : ?>
					<?php esc_html_e( 'Pass / Fail', 'tradeschool-manager' ); ?>
				<?php else : ?>
					<?php esc_html_e( 'Points possible:', 'tradeschool-manager' ); ?> <strong><?php echo esc_html( $assignment->points_possible ); ?></strong>
				<?php endif; ?>
				<?php if ( $assignment->due_date ) : ?> | <?php esc_html_e( 'Due:', 'tradeschool-manager' ); ?> <?php echo esc_html( TSM_Date_Utils::display( $assignment->due_date ) ); ?><?php endif; ?>
				<?php if ( ! empty( $assignment->category ) ) : ?> | <?php echo esc_html( $assignment->category ); ?><?php endif; ?>
			</p>
			<?php if ( ! empty( $assignment->description ) ) : ?>
				<p><?php echo wp_kses_post( wpautop( $assignment->description ) ); ?></p>
			<?php endif; ?>
			<form method="post">
				<?php wp_nonce_field( 'tsm_teacher_save_grades' ); ?>
				<input type="hidden" name="tsm_teacher_action" value="save_grades">
				<input type="hidden" name="assignment_id" value="<?php echo esc_attr( $aid ); ?>">
				<input type="hidden" name="grading_method" value="<?php echo esc_attr( $method ); ?>">
				<?php $statuses = TSM_Gradebook::statuses(); unset( $statuses[''] ); ?>
				<div class="tsm-grade-entry-scroll">
				<table class="tsm-table tsm-stack-table tsm-grade-entry" data-points="<?php echo esc_attr( $assignment->points_possible ); ?>" data-due="<?php echo esc_attr( $assignment->due_date ?? '' ); ?>">
					<thead><tr>
						<th><?php esc_html_e( 'Student', 'tradeschool-manager' ); ?></th>
						<th><?php esc_html_e( 'Status', 'tradeschool-manager' ); ?></th>
						<th><?php esc_html_e( 'Submitted', 'tradeschool-manager' ); ?></th>
						<?php if ( ! $is_passfail ) : ?>
							<th><?php esc_html_e( 'Raw', 'tradeschool-manager' ); ?></th>
							<th><?php esc_html_e( 'Bonus', 'tradeschool-manager' ); ?></th>
							<th><?php esc_html_e( 'Penalty %', 'tradeschool-manager' ); ?></th>
							<th><?php esc_html_e( 'Total', 'tradeschool-manager' ); ?></th>
							<th><?php esc_html_e( 'Grade', 'tradeschool-manager' ); ?></th>
						<?php endif; ?>
						<th><?php esc_html_e( 'Counts', 'tradeschool-manager' ); ?></th>
						<th><?php esc_html_e( 'Comments', 'tradeschool-manager' ); ?></th>
					</tr></thead>
					<tbody>
					<?php foreach ( $students as $s ) :
						$g  = TSM_Gradebook::get_grade( $aid, $s->id );
						$st = $g ? (string) $g->status : ''; ?>
						<tr class="tsm-grade-row" data-status="<?php echo esc_attr( $st ?: 'ungraded' ); ?>">
							<td data-label="<?php esc_attr_e( 'Student', 'tradeschool-manager' ); ?>" class="tsm-grade-name"><?php echo esc_html( $s->last_name . ', ' . $s->first_name ); ?></td>
							<td data-label="<?php esc_attr_e( 'Status', 'tradeschool-manager' ); ?>">
								<select name="grades[<?php echo esc_attr( $s->id ); ?>][status]" class="tsm-ge-status">
									<?php foreach ( $statuses as $k => $v ) : ?>
										<option value="<?php echo esc_attr( $k ); ?>" <?php selected( $st ?: 'ungraded', $k ); ?>><?php echo esc_html( $v['label'] ); ?></option>
									<?php endforeach; ?>
								</select>
							</td>
							<td data-label="<?php esc_attr_e( 'Submitted', 'tradeschool-manager' ); ?>"><input type="text" class="tsm-ge-submitted" name="grades[<?php echo esc_attr( $s->id ); ?>][submitted_date]" value="<?php echo esc_attr( TSM_Date_Utils::display( $g->submitted_date ?? '', '' ) ); ?>" placeholder="MM/DD/YYYY"></td>
							<?php if ( ! $is_passfail ) : ?>
								<td data-label="<?php esc_attr_e( 'Raw', 'tradeschool-manager' ); ?>"><input type="number" inputmode="decimal" step="0.01" class="tsm-ge-raw tsm-grade-num" name="grades[<?php echo esc_attr( $s->id ); ?>][points_earned]" value="<?php echo esc_attr( $g->points_earned ?? '' ); ?>" placeholder="<?php echo esc_attr( $assignment->points_possible ); ?>"></td>
								<td data-label="<?php esc_attr_e( 'Bonus', 'tradeschool-manager' ); ?>"><input type="number" inputmode="decimal" step="0.01" class="tsm-ge-bonus tsm-grade-num" name="grades[<?php echo esc_attr( $s->id ); ?>][bonus]" value="<?php echo esc_attr( $g->bonus ?? '' ); ?>"></td>
								<td data-label="<?php esc_attr_e( 'Penalty %', 'tradeschool-manager' ); ?>"><input type="number" inputmode="decimal" step="0.01" min="0" max="100" class="tsm-ge-lp tsm-grade-num" name="grades[<?php echo esc_attr( $s->id ); ?>][late_penalty]" value="<?php echo esc_attr( $g->late_penalty ?? '' ); ?>"></td>
								<td data-label="<?php esc_attr_e( 'Total', 'tradeschool-manager' ); ?>" class="tsm-ge-total"> - </td>
								<td data-label="<?php esc_attr_e( 'Grade', 'tradeschool-manager' ); ?>" class="tsm-ge-pct"> - </td>
							<?php endif; ?>
							<td data-label="<?php esc_attr_e( 'Counts', 'tradeschool-manager' ); ?>" class="tsm-ge-counts"> - </td>
							<td data-label="<?php esc_attr_e( 'Comments', 'tradeschool-manager' ); ?>"><input type="text" name="grades[<?php echo esc_attr( $s->id ); ?>][comments]" value="<?php echo $g ? esc_attr( $g->comments ) : ''; ?>" class="tsm-grade-comments" placeholder="<?php esc_attr_e( 'Optional', 'tradeschool-manager' ); ?>"></td>
						</tr>
					<?php endforeach; ?>
					</tbody>
				</table>
				</div>
				<div class="tsm-save-bar">
					<button type="submit" class="tsm-btn tsm-btn--primary tsm-btn--lg"><?php esc_html_e( 'Save Grades', 'tradeschool-manager' ); ?></button>
					<a class="tsm-btn tsm-btn--ghost" href="<?php echo esc_url( add_query_arg( array( 'tsm_view' => 'class', 'cid' => $assignment->class_id, 'ctab' => 'assignments' ), remove_query_arg( array( 'aid', 'assignment_edit', 'saved', 'composer_done' ) ) ) . '#tsm-teacher-class-' . (int) $assignment->class_id ); ?>"><?php esc_html_e( 'Back to class', 'tradeschool-manager' ); ?></a>
				</div>
				<?php
				$grade_meta = wp_json_encode( array_map( function( $v ) { return array( 'counts' => $v['counts'], 'zero' => $v['zero'] ); }, $statuses ) );
				TSM_Inline_Assets::script(
					'tsm-teacher-grade-entry-' . absint( $assignment->id ),
					"(function(){
						var META = {$grade_meta};
						var tbl = document.querySelector('.tsm-grade-entry'); if (!tbl) return;
						var POSSIBLE = parseFloat(tbl.dataset.points) || 0;
						var DUE = tbl.dataset.due || '';
						function fmt(d){ var p=function(n){return(n<10?'0':'')+n;}; return p(d.getMonth()+1)+'/'+p(d.getDate())+'/'+d.getFullYear(); }
						function todayDisplay(){ return fmt(new Date()); }
						function displayYmd(v){ var m=/^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(v||''); return m ? m[2]+'/'+m[3]+'/'+m[1] : v; }
						function recalc(row){
							var st=row.querySelector('.tsm-ge-status').value, m=META[st]||{counts:false,zero:false};
							var raw=parseFloat((row.querySelector('.tsm-ge-raw')||{}).value)||0;
							var bn=parseFloat((row.querySelector('.tsm-ge-bonus')||{}).value)||0;
							var lp=Math.max(0,Math.min(100,parseFloat((row.querySelector('.tsm-ge-lp')||{}).value)||0));
							row.dataset.status = st;
							var t=row.querySelector('.tsm-ge-total'),p=row.querySelector('.tsm-ge-pct'),c=row.querySelector('.tsm-ge-counts');
							if (!m.counts){ if(t)t.textContent=' - '; if(p)p.textContent=' - '; if(c)c.textContent='No'; return; }
							var total = m.zero ? 0 : Math.max(0, raw*(1-lp/100)+bn);
							if(t) t.textContent = total.toFixed(2);
							if(p) p.textContent = POSSIBLE>0 ? ((total/POSSIBLE)*100).toFixed(2)+'%' : ' - ';
							if(c) c.textContent = 'Yes';
						}
						document.querySelectorAll('.tsm-grade-row').forEach(function(row){
							row.querySelector('.tsm-ge-status').addEventListener('change', function(){
								var st=row.querySelector('.tsm-ge-status').value, sub=row.querySelector('.tsm-ge-submitted');
								if (['completed_ontime','completed_late','incomplete','missing'].indexOf(st)>=0 && !sub.value) sub.value=todayDisplay();
								else if (['ungraded','excluded'].indexOf(st)>=0) sub.value='';
								recalc(row);
							});
							function onRaw(){
								var status=row.querySelector('.tsm-ge-status'), raw=row.querySelector('.tsm-ge-raw'), sub=row.querySelector('.tsm-ge-submitted');
								if (status && raw && '' !== raw.value && ['','ungraded'].indexOf(status.value)>=0) {
									status.value='completed_ontime';
									if (sub && !sub.value) sub.value=displayYmd(DUE) || todayDisplay();
								}
								recalc(row);
							}
							['tsm-ge-raw','tsm-ge-bonus','tsm-ge-lp'].forEach(function(c){
								var el=row.querySelector('.'+c); if(el) el.addEventListener('input', function(){ c === 'tsm-ge-raw' ? onRaw() : recalc(row); });
							});
							recalc(row);
						});
					})();"
				);
				?>
			</form>
		</section>
		<?php
	}

	private function view_attendance( $tid, $cid ) {
		if ( ! class_exists( 'TSMP_Attendance' ) ) {
			echo '<p>' . esc_html__( 'Attendance is not available.', 'tradeschool-manager' ) . '</p>';
			return;
		}
		if ( ! TSM_Teacher_Portal::teacher_owns_class( $tid, $cid ) ) {
			echo '<div class="tsm-error">' . esc_html__( 'You do not have access to this class.', 'tradeschool-manager' ) . '</div>';
			return;
		}
		$class = TSM_Classes::get( $cid );
		$tab   = isset( $_GET['att_tab'] ) ? sanitize_key( $_GET['att_tab'] ) : 'take'; // phpcs:ignore
		$date  = isset( $_GET['date'] ) ? sanitize_text_field( wp_unslash( $_GET['date'] ) ) : gmdate( 'Y-m-d' ); // phpcs:ignore
		$sid   = isset( $_GET['sid'] ) ? absint( $_GET['sid'] ) : 0; // phpcs:ignore
		$base  = remove_query_arg( array( 'att_tab', 'date', 'sid', 'assignment_edit', 'saved' ) );
		$base  = add_query_arg( array( 'tsm_view' => 'attendance', 'cid' => $cid ), $base );
		?>
		<section>
			<h3><?php echo esc_html( $class->name ); ?>  -  <?php esc_html_e( 'Attendance', 'tradeschool-manager' ); ?></h3>
			<?php
			TSMP_Attendance::render_panel( array(
				'class_id'   => $cid,
				'tab'        => $tab,
				'date'       => $date,
				'student_id' => $sid,
				'base_url'   => $base,
				'admin'      => false,
			) );
			?>
		</section>
		<?php
	}
}
