<script lang="ts">
	import { goto } from '$app/navigation';
	import { page } from '$app/state';
	import { getApiBaseUrl } from '$lib/api/config';
	import { authenticatedFetch } from '$lib/auth';
	import Pagination from '$lib/components/molecules/Pagination/Pagination.svelte';
	import SearchInput from '$lib/components/molecules/SearchInput/SearchInput.svelte';
	import { untrack } from 'svelte';

	// Types
	interface TeacherReplacement {
		id: string;
		replacedTeacherId: string;
		replacementTeacherId: string;
		startDate: string;
		endDate: string;
		status: string;
		classes: Array<{ classId: string; subjectId: string }>;
		reason: string | null;
		createdAt: string | null;
		endedAt: string | null;
	}

	interface User {
		id: string;
		firstName: string;
		lastName: string;
		email: string;
		roles: string[];
	}

	interface SchoolClass {
		id: string;
		name: string;
		level: string | null;
		status: string;
	}

	interface Subject {
		id: string;
		name: string;
		code: string;
		color: string | null;
		status: string;
	}

	interface ClassSubjectPair {
		classId: string;
		subjectId: string;
	}

	// State
	let replacements = $state<TeacherReplacement[]>([]);
	let teachers = $state<User[]>([]);
	let classes = $state<SchoolClass[]>([]);
	let subjects = $state<Subject[]>([]);
	let isLoading = $state(true);
	let error = $state<string | null>(null);
	let successMessage = $state<string | null>(null);

	// Pagination & Search
	let currentPage = $state(Number(page.url.searchParams.get('page')) || 1);
	let searchTerm = $state(page.url.searchParams.get('search') ?? '');
	let totalItems = $state(0);
	const itemsPerPage = 30;
	let totalPages = $derived(Math.ceil(totalItems / itemsPerPage));

	// Create modal
	let showCreateModal = $state(false);
	let selectedReplacedTeacherId = $state('');
	let selectedReplacementTeacherId = $state('');
	let selectedStartDate = $state('');
	let selectedEndDate = $state('');
	let selectedReason = $state('');
	let classPairs = $state<ClassSubjectPair[]>([{ classId: '', subjectId: '' }]);
	let isSubmitting = $state(false);

	// Delete (end) state
	let showEndModal = $state(false);
	let replacementToEnd = $state<TeacherReplacement | null>(null);
	let isEnding = $state(false);

	// Validation
	let isFormValid = $derived(
		selectedReplacedTeacherId !== '' &&
			selectedReplacementTeacherId !== '' &&
			selectedReplacedTeacherId !== selectedReplacementTeacherId &&
			selectedStartDate !== '' &&
			selectedEndDate !== '' &&
			selectedEndDate >= selectedStartDate &&
			classPairs.some((p) => p.classId !== '' && p.subjectId !== '')
	);

	// Load everything on mount
	$effect(() => {
		untrack(() => loadAll());
	});

	async function loadAll() {
		try {
			isLoading = true;
			error = null;
			const apiUrl = getApiBaseUrl();

			const [teachersRes, classesRes, subjectsRes] = await Promise.all([
				authenticatedFetch(`${apiUrl}/users?role=ROLE_PROF&itemsPerPage=100`),
				authenticatedFetch(`${apiUrl}/classes?itemsPerPage=100`),
				authenticatedFetch(`${apiUrl}/subjects?itemsPerPage=100`)
			]);

			if (!teachersRes.ok) throw new Error('Erreur lors du chargement des enseignants');
			if (!classesRes.ok) throw new Error('Erreur lors du chargement des classes');
			if (!subjectsRes.ok) throw new Error('Erreur lors du chargement des matières');

			const [teachersData, classesData, subjectsData] = await Promise.all([
				teachersRes.json(),
				classesRes.json(),
				subjectsRes.json()
			]);

			teachers = extractCollection(teachersData);
			classes = extractCollection(classesData);
			subjects = extractCollection(subjectsData);

			await loadReplacements();
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		} finally {
			isLoading = false;
		}
	}

	let replacementsAbortController: AbortController | null = null;

	async function loadReplacements() {
		replacementsAbortController?.abort();
		const controller = new AbortController();
		replacementsAbortController = controller;

		const apiUrl = getApiBaseUrl();
		const params = new URLSearchParams();
		params.set('page', String(currentPage));
		params.set('itemsPerPage', String(itemsPerPage));
		if (searchTerm) params.set('search', searchTerm);
		const response = await authenticatedFetch(
			`${apiUrl}/teacher-replacements?${params.toString()}`,
			{ signal: controller.signal }
		);

		if (controller.signal.aborted) return;

		if (!response.ok) {
			throw new Error('Erreur lors du chargement des remplacements');
		}

		const data = await response.json();
		replacements = data['hydra:member'] ?? data['member'] ?? [];
		totalItems = data['hydra:totalItems'] ?? data['totalItems'] ?? replacements.length;
	}

	function extractCollection<T>(data: Record<string, unknown>): T[] {
		const hydra = data['hydra:member'];
		if (Array.isArray(hydra)) return hydra as T[];
		const member = data['member'];
		if (Array.isArray(member)) return member as T[];
		if (Array.isArray(data)) return data as T[];
		return [];
	}

	function getTeacherName(teacherId: string): string {
		const teacher = teachers.find((t) => t.id === teacherId);
		return teacher ? `${teacher.firstName} ${teacher.lastName}` : teacherId;
	}

	function getClassName(classId: string): string {
		const cls = classes.find((c) => c.id === classId);
		return cls?.name ?? classId;
	}

	function getSubjectName(subjectId: string): string {
		const subject = subjects.find((s) => s.id === subjectId);
		return subject?.name ?? subjectId;
	}

	function getSubjectColor(subjectId: string): string | null {
		const subject = subjects.find((s) => s.id === subjectId);
		return subject?.color ?? null;
	}

	function daysRemaining(endDate: string): number {
		const end = new Date(endDate);
		const now = new Date();
		now.setHours(0, 0, 0, 0);
		end.setHours(0, 0, 0, 0);
		return Math.ceil((end.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
	}

	function updateUrl() {
		const params = new URLSearchParams();
		if (currentPage > 1) params.set('page', String(currentPage));
		if (searchTerm) params.set('search', searchTerm);
		const query = params.toString();
		goto(`?${query}`, { replaceState: true, noScroll: true, keepFocus: true });
	}

	function handleSearch(value: string) {
		searchTerm = value;
		currentPage = 1;
		updateUrl();
		reloadReplacements();
	}

	function handlePageChange(newPage: number) {
		currentPage = newPage;
		updateUrl();
		reloadReplacements();
	}

	async function reloadReplacements() {
		try {
			isLoading = true;
			error = null;
			await loadReplacements();
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		} finally {
			isLoading = false;
		}
	}

	function openCreateModal() {
		showCreateModal = true;
		selectedReplacedTeacherId = '';
		selectedReplacementTeacherId = '';
		selectedStartDate = '';
		selectedEndDate = '';
		selectedReason = '';
		classPairs = [{ classId: '', subjectId: '' }];
		error = null;
	}

	function closeCreateModal() {
		showCreateModal = false;
	}

	function addClassPair() {
		classPairs = [...classPairs, { classId: '', subjectId: '' }];
	}

	function removeClassPair(index: number) {
		classPairs = classPairs.filter((_, i) => i !== index);
	}

	async function handleCreate() {
		if (!isFormValid) return;

		const validPairs = classPairs.filter((p) => p.classId !== '' && p.subjectId !== '');

		try {
			isSubmitting = true;
			error = null;
			const apiUrl = getApiBaseUrl();

			const response = await authenticatedFetch(`${apiUrl}/teacher-replacements`, {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({
					replacedTeacherId: selectedReplacedTeacherId,
					replacementTeacherId: selectedReplacementTeacherId,
					startDate: selectedStartDate,
					endDate: selectedEndDate,
					classes: validPairs,
					reason: selectedReason || null
				})
			});

			if (!response.ok) {
				const data = await response.json().catch(() => null);
				const message =
					data?.['hydra:description'] ??
					data?.message ??
					data?.detail ??
					`Erreur (${response.status})`;
				throw new Error(message);
			}

			successMessage = 'Remplacement créé avec succès';
			closeCreateModal();
			await reloadReplacements();
			globalThis.setTimeout(() => {
				successMessage = null;
			}, 3000);
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur lors de la création';
		} finally {
			isSubmitting = false;
		}
	}

	function openEndModal(replacement: TeacherReplacement) {
		replacementToEnd = replacement;
		showEndModal = true;
	}

	function closeEndModal() {
		showEndModal = false;
		replacementToEnd = null;
	}

	async function handleEnd() {
		if (!replacementToEnd) return;

		try {
			isEnding = true;
			error = null;
			const apiUrl = getApiBaseUrl();

			const response = await authenticatedFetch(
				`${apiUrl}/teacher-replacements/${replacementToEnd.id}`,
				{ method: 'DELETE' }
			);

			if (!response.ok && response.status !== 204) {
				const data = await response.json().catch(() => null);
				const message =
					data?.['hydra:description'] ??
					data?.message ??
					data?.detail ??
					`Erreur (${response.status})`;
				throw new Error(message);
			}

			replacements = replacements.filter((r) => r.id !== replacementToEnd!.id);
			totalItems = Math.max(0, totalItems - 1);
			if (replacements.length === 0 && currentPage > 1) {
				currentPage -= 1;
				updateUrl();
				reloadReplacements();
			}
			successMessage = 'Remplacement terminé avec succès';
			closeEndModal();
			globalThis.setTimeout(() => {
				successMessage = null;
			}, 3000);
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur lors de la terminaison';
		} finally {
			isEnding = false;
		}
	}
</script>

<svelte:head>
	<title>Remplacements enseignants - Classeo</title>
</svelte:head>

<div class="replacements-page">
	<header class="page-header">
		<div class="header-content">
			<h1>Remplacements enseignants</h1>
			<p class="subtitle">Désignez des remplaçants pour les enseignants absents</p>
		</div>
		<button class="btn-primary" onclick={openCreateModal}>
			<span class="btn-icon">+</span>
			Nouveau remplacement
		</button>
	</header>

	{#if error}
		<div class="alert alert-error">
			<span class="alert-icon">!</span>
			{error}
			<button class="alert-close" onclick={() => (error = null)}>x</button>
		</div>
	{/if}

	{#if successMessage}
		<div class="alert alert-success">
			{successMessage}
		</div>
	{/if}

	<SearchInput
		value={searchTerm}
		onSearch={handleSearch}
		placeholder="Rechercher par enseignant..."
	/>

	{#if isLoading}
		<div class="loading-state" aria-live="polite" role="status">
			<div class="spinner"></div>
			<p>Chargement des remplacements...</p>
		</div>
	{:else if replacements.length === 0}
		<div class="empty-state">
			<span class="empty-icon">&#x1F504;</span>
			{#if searchTerm}
				<h2>Aucun résultat</h2>
				<p>Aucun remplacement ne correspond à votre recherche</p>
				<button class="btn-secondary" onclick={() => handleSearch('')}>Effacer la recherche</button>
			{:else}
				<h2>Aucun remplacement actif</h2>
				<p>Désignez un remplaçant pour un enseignant absent</p>
				<button class="btn-primary" onclick={openCreateModal}>Nouveau remplacement</button>
			{/if}
		</div>
	{:else}
		<div class="table-container">
			<table class="replacements-table">
				<thead>
					<tr>
						<th>Enseignant remplacé</th>
						<th>Remplaçant</th>
						<th>Classes / Matières</th>
						<th>Période</th>
						<th>Statut</th>
						<th>Actions</th>
					</tr>
				</thead>
				<tbody>
					{#each replacements as replacement (replacement.id)}
						{@const days = daysRemaining(replacement.endDate)}
						<tr>
							<td data-label="Remplacé" class="teacher-cell">
								<span class="teacher-name">{getTeacherName(replacement.replacedTeacherId)}</span>
							</td>
							<td data-label="Remplaçant" class="teacher-cell">
								<span class="teacher-name">{getTeacherName(replacement.replacementTeacherId)}</span>
							</td>
							<td data-label="Classes / Matières" class="classes-cell">
								{#each replacement.classes as pair}
									{@const color = getSubjectColor(pair.subjectId)}
									<span class="class-pair">
										<span class="class-name">{getClassName(pair.classId)}</span>
										{#if color}
											<span
												class="subject-badge"
												style="background-color: {color}; color: white"
											>
												{getSubjectName(pair.subjectId)}
											</span>
										{:else}
											<span class="subject-badge subject-badge-default">
												{getSubjectName(pair.subjectId)}
											</span>
										{/if}
									</span>
								{/each}
							</td>
							<td data-label="Période" class="date-cell">
								<div class="date-range">
									{new Date(replacement.startDate).toLocaleDateString('fr-FR')}
									&rarr;
									{new Date(replacement.endDate).toLocaleDateString('fr-FR')}
								</div>
								{#if replacement.status === 'active'}
									<span
										class="countdown"
										class:countdown-warning={days <= 3}
										class:countdown-urgent={days <= 1}
									>
										{#if days > 1}
											{days} jours restants
										{:else if days === 1}
											1 jour restant
										{:else if days === 0}
											Dernier jour
										{:else}
											Expiré
										{/if}
									</span>
								{/if}
							</td>
							<td data-label="Statut">
								{#if replacement.status === 'active'}
									<span class="status-badge status-active">Actif</span>
								{:else}
									<span class="status-badge status-ended">Terminé</span>
								{/if}
							</td>
							<td data-label="Actions" class="actions-cell">
								{#if replacement.status === 'active'}
									<button
										class="btn-remove"
										onclick={() => openEndModal(replacement)}
									>
										Terminer
									</button>
								{/if}
							</td>
						</tr>
					{/each}
				</tbody>
			</table>
		</div>
		<Pagination {currentPage} {totalPages} onPageChange={handlePageChange} />
	{/if}
</div>

<!-- Create Modal -->
{#if showCreateModal}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="modal-overlay" onclick={closeCreateModal} role="presentation">
		<div
			class="modal modal-large"
			role="dialog"
			aria-modal="true"
			aria-labelledby="create-modal-title"
			tabindex="-1"
			onclick={(e) => e.stopPropagation()}
			onkeydown={(e) => { if (e.key === 'Escape') closeCreateModal(); }}
		>
			<header class="modal-header">
				<h2 id="create-modal-title">Nouveau remplacement</h2>
				<button class="modal-close" onclick={closeCreateModal} aria-label="Fermer">x</button>
			</header>

			<form
				class="modal-body"
				onsubmit={(e) => {
					e.preventDefault();
					handleCreate();
				}}
			>
				<div class="form-row">
					<div class="form-group">
						<label for="replaced-teacher">Enseignant remplacé *</label>
						<select id="replaced-teacher" bind:value={selectedReplacedTeacherId} required>
							<option value="">-- Sélectionner --</option>
							{#each teachers as teacher (teacher.id)}
								<option value={teacher.id} disabled={teacher.id === selectedReplacementTeacherId}>
									{teacher.firstName} {teacher.lastName}
								</option>
							{/each}
						</select>
					</div>

					<div class="form-group">
						<label for="replacement-teacher">Remplaçant *</label>
						<select id="replacement-teacher" bind:value={selectedReplacementTeacherId} required>
							<option value="">-- Sélectionner --</option>
							{#each teachers as teacher (teacher.id)}
								<option value={teacher.id} disabled={teacher.id === selectedReplacedTeacherId}>
									{teacher.firstName} {teacher.lastName}
								</option>
							{/each}
						</select>
					</div>
				</div>

				{#if selectedReplacedTeacherId && selectedReplacementTeacherId && selectedReplacedTeacherId === selectedReplacementTeacherId}
					<div class="form-error">
						L'enseignant remplacé et le remplaçant doivent être différents.
					</div>
				{/if}

				<div class="form-row">
					<div class="form-group">
						<label for="start-date">Date de début *</label>
						<input type="date" id="start-date" bind:value={selectedStartDate} required />
					</div>

					<div class="form-group">
						<label for="end-date">Date de fin *</label>
						<input type="date" id="end-date" bind:value={selectedEndDate} min={selectedStartDate} required />
					</div>
				</div>

				{#if selectedStartDate && selectedEndDate && selectedEndDate < selectedStartDate}
					<div class="form-error">
						La date de fin doit être postérieure à la date de début.
					</div>
				{/if}

				<div class="form-group" role="group" aria-labelledby="classes-label">
					<span id="classes-label" class="form-label">Classes et matières concernées *</span>
					{#each classPairs as pair, index}
						<div class="class-pair-row">
							<select bind:value={pair.classId} required>
								<option value="">-- Classe --</option>
								{#each classes as cls (cls.id)}
									<option value={cls.id}>{cls.name}{cls.level ? ` (${cls.level})` : ''}</option>
								{/each}
							</select>
							<select bind:value={pair.subjectId} required>
								<option value="">-- Matière --</option>
								{#each subjects as subject (subject.id)}
									<option value={subject.id}>{subject.name} ({subject.code})</option>
								{/each}
							</select>
							{#if classPairs.length > 1}
								<button type="button" class="btn-remove-pair" onclick={() => removeClassPair(index)} aria-label="Retirer cette classe/matière">
									x
								</button>
							{/if}
						</div>
					{/each}
					<button type="button" class="btn-add-pair" onclick={addClassPair}>
						+ Ajouter une classe/matière
					</button>
				</div>

				<div class="form-group">
					<label for="reason">Motif (optionnel)</label>
					<input type="text" id="reason" bind:value={selectedReason} placeholder="Ex: Congé maladie" />
				</div>

				<div class="form-hint">
					Le remplaçant pourra saisir de nouvelles notes et consulter les notes existantes en lecture seule.
				</div>

				<div class="modal-actions">
					<button type="button" class="btn-secondary" onclick={closeCreateModal} disabled={isSubmitting}>
						Annuler
					</button>
					<button
						type="submit"
						class="btn-primary"
						disabled={isSubmitting || !isFormValid}
					>
						{#if isSubmitting}
							Création...
						{:else}
							Désigner le remplaçant
						{/if}
					</button>
				</div>
			</form>
		</div>
	</div>
{/if}

<!-- End Replacement Confirmation Modal -->
{#if showEndModal && replacementToEnd}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="modal-overlay" onclick={closeEndModal} role="presentation">
		<div
			class="modal modal-confirm"
			role="alertdialog"
			aria-modal="true"
			aria-labelledby="end-modal-title"
			aria-describedby="end-modal-description"
			tabindex="-1"
			onclick={(e) => e.stopPropagation()}
			onkeydown={(e) => { if (e.key === 'Escape') closeEndModal(); }}
		>
			<header class="modal-header modal-header-danger">
				<h2 id="end-modal-title">Terminer le remplacement</h2>
				<button class="modal-close" onclick={closeEndModal} aria-label="Fermer">x</button>
			</header>

			<div class="modal-body">
				<p id="end-modal-description">
					Terminer le remplacement de <strong>{getTeacherName(replacementToEnd.replacedTeacherId)}</strong>
					par <strong>{getTeacherName(replacementToEnd.replacementTeacherId)}</strong> ?
				</p>
				<p class="delete-warning">
					Le remplaçant perdra immédiatement l'accès aux classes concernées.
				</p>
			</div>

			<div class="modal-actions modal-actions-padded">
				<button type="button" class="btn-secondary" onclick={closeEndModal} disabled={isEnding}>
					Annuler
				</button>
				<button type="button" class="btn-danger" onclick={handleEnd} disabled={isEnding}>
					{#if isEnding}
						Terminaison...
					{:else}
						Terminer
					{/if}
				</button>
			</div>
		</div>
	</div>
{/if}

<style>
	.replacements-page {
		padding: 1.5rem;
		max-width: 1200px;
		margin: 0 auto;
	}

	.page-header {
		display: flex;
		justify-content: space-between;
		align-items: flex-start;
		gap: 1rem;
		margin-bottom: 1.5rem;
		flex-wrap: wrap;
	}

	.header-content h1 {
		margin: 0;
		font-size: 1.5rem;
		font-weight: 700;
		color: #1f2937;
	}

	.subtitle {
		margin: 0.25rem 0 0;
		color: #6b7280;
		font-size: 0.875rem;
	}

	/* Buttons */
	.btn-primary {
		display: inline-flex;
		align-items: center;
		gap: 0.5rem;
		padding: 0.75rem 1.25rem;
		background: var(--btn-primary-bg, #3b82f6);
		color: white;
		border: none;
		border-radius: 0.5rem;
		font-weight: 600;
		cursor: pointer;
		transition: background 0.2s;
	}

	.btn-primary:hover:not(:disabled) {
		background: var(--btn-primary-hover-bg, #2563eb);
	}

	.btn-primary:disabled {
		opacity: 0.6;
		cursor: not-allowed;
	}

	.btn-secondary {
		padding: 0.5rem 1rem;
		background: white;
		color: #374151;
		border: 1px solid #d1d5db;
		border-radius: 0.375rem;
		font-weight: 500;
		cursor: pointer;
		transition: all 0.2s;
	}

	.btn-secondary:hover:not(:disabled) {
		background: #f3f4f6;
	}

	.btn-danger {
		display: inline-flex;
		align-items: center;
		gap: 0.5rem;
		padding: 0.5rem 1rem;
		background: #dc2626;
		color: white;
		border: none;
		border-radius: 0.375rem;
		font-weight: 500;
		cursor: pointer;
		transition: background 0.2s;
	}

	.btn-danger:hover:not(:disabled) {
		background: #b91c1c;
	}

	.btn-danger:disabled {
		opacity: 0.6;
		cursor: not-allowed;
	}

	.btn-remove {
		padding: 0.375rem 0.75rem;
		font-size: 0.75rem;
		background: #fef2f2;
		border: 1px solid #fecaca;
		color: #991b1b;
		border-radius: 0.25rem;
		cursor: pointer;
		transition: background 0.15s;
	}

	.btn-remove:hover {
		background: #fee2e2;
	}

	.btn-icon {
		font-size: 1.25rem;
		line-height: 1;
	}

	/* Alerts */
	.alert {
		display: flex;
		align-items: center;
		gap: 0.75rem;
		padding: 1rem;
		border-radius: 0.5rem;
		margin-bottom: 1rem;
	}

	.alert-error {
		background: #fef2f2;
		border: 1px solid #fecaca;
		color: #dc2626;
	}

	.alert-success {
		background: #f0fdf4;
		border: 1px solid #bbf7d0;
		color: #16a34a;
	}

	.alert-icon {
		flex-shrink: 0;
		font-weight: bold;
	}

	.alert-close {
		margin-left: auto;
		padding: 0.25rem 0.5rem;
		background: none;
		border: none;
		font-size: 1.25rem;
		cursor: pointer;
		opacity: 0.6;
	}

	.alert-close:hover {
		opacity: 1;
	}

	/* Loading & Empty */
	.loading-state,
	.empty-state {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		padding: 3rem;
		text-align: center;
		background: white;
		border-radius: 0.75rem;
		border: 2px dashed #e5e7eb;
	}

	.spinner {
		width: 2rem;
		height: 2rem;
		border: 3px solid #e5e7eb;
		border-top-color: #3b82f6;
		border-radius: 50%;
		animation: spin 0.8s linear infinite;
	}

	@keyframes spin {
		to {
			transform: rotate(360deg);
		}
	}

	.empty-icon {
		font-size: 3rem;
		margin-bottom: 1rem;
	}

	.empty-state h2 {
		margin: 0 0 0.5rem;
		font-size: 1.25rem;
		color: #1f2937;
	}

	.empty-state p {
		margin: 0 0 1.5rem;
		color: #6b7280;
	}

	/* Table */
	.table-container {
		background: white;
		border: 1px solid #e5e7eb;
		border-radius: 0.75rem;
		overflow-x: auto;
	}

	.replacements-table {
		width: 100%;
		border-collapse: collapse;
	}

	.replacements-table th {
		text-align: left;
		padding: 0.75rem 1rem;
		font-size: 0.75rem;
		font-weight: 600;
		color: #6b7280;
		text-transform: uppercase;
		letter-spacing: 0.05em;
		border-bottom: 1px solid #e5e7eb;
		background: #f9fafb;
	}

	.replacements-table td {
		padding: 0.75rem 1rem;
		font-size: 0.875rem;
		color: #374151;
		border-bottom: 1px solid #f3f4f6;
		vertical-align: top;
	}

	.replacements-table tr:last-child td {
		border-bottom: none;
	}

	.replacements-table tr:hover td {
		background: #f9fafb;
	}

	.teacher-cell {
		white-space: nowrap;
	}

	.teacher-name {
		font-weight: 500;
		color: #1f2937;
	}

	.classes-cell {
		min-width: 200px;
	}

	.class-pair {
		display: inline-flex;
		align-items: center;
		gap: 0.25rem;
		margin: 0.125rem 0.25rem 0.125rem 0;
	}

	.class-name {
		font-size: 0.8125rem;
		color: #4b5563;
	}

	.subject-badge {
		display: inline-block;
		padding: 0.125rem 0.5rem;
		border-radius: 9999px;
		font-size: 0.6875rem;
		font-weight: 500;
	}

	.subject-badge-default {
		background: #f3f4f6;
		color: #374151;
	}

	.date-cell {
		white-space: nowrap;
	}

	.date-range {
		color: #374151;
		font-size: 0.8125rem;
	}

	.countdown {
		display: block;
		margin-top: 0.25rem;
		font-size: 0.75rem;
		font-weight: 500;
		color: #16a34a;
	}

	.countdown-warning {
		color: #d97706;
	}

	.countdown-urgent {
		color: #dc2626;
	}

	.status-badge {
		display: inline-block;
		padding: 0.125rem 0.5rem;
		border-radius: 9999px;
		font-size: 0.75rem;
		font-weight: 500;
	}

	.status-active {
		background: #f0fdf4;
		color: #16a34a;
	}

	.status-ended {
		background: #f3f4f6;
		color: #6b7280;
	}

	.actions-cell {
		white-space: nowrap;
	}

	/* Modal */
	.modal-overlay {
		position: fixed;
		inset: 0;
		background: rgba(0, 0, 0, 0.5);
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 1rem;
		z-index: 100;
	}

	.modal {
		background: white;
		border-radius: 0.75rem;
		width: 100%;
		max-width: 28rem;
		max-height: 90vh;
		overflow: auto;
		box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
	}

	.modal-large {
		max-width: 36rem;
	}

	.modal-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 1.25rem 1.5rem;
		border-bottom: 1px solid #e5e7eb;
	}

	.modal-header h2 {
		margin: 0;
		font-size: 1.125rem;
		font-weight: 600;
		color: #1f2937;
	}

	.modal-close {
		padding: 0.25rem 0.5rem;
		background: none;
		border: none;
		font-size: 1.5rem;
		line-height: 1;
		color: #6b7280;
		cursor: pointer;
	}

	.modal-close:hover {
		color: #1f2937;
	}

	.modal-body {
		padding: 1.5rem;
	}

	.form-row {
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: 1rem;
	}

	.form-group {
		margin-bottom: 1.25rem;
	}

	.form-group label,
	.form-label {
		display: block;
		margin-bottom: 0.5rem;
		font-weight: 500;
		color: #374151;
	}

	.form-group select,
	.form-group input {
		width: 100%;
		padding: 0.75rem 1rem;
		border: 1px solid #d1d5db;
		border-radius: 0.375rem;
		font-size: 1rem;
		transition: border-color 0.2s;
		background: white;
	}

	.form-group select:focus,
	.form-group input:focus {
		outline: none;
		border-color: #3b82f6;
		box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
	}

	.form-error {
		padding: 0.5rem 0.75rem;
		background: #fef2f2;
		border: 1px solid #fecaca;
		border-radius: 0.375rem;
		color: #dc2626;
		font-size: 0.875rem;
		margin-bottom: 1rem;
	}

	.class-pair-row {
		display: grid;
		grid-template-columns: 1fr 1fr auto;
		gap: 0.5rem;
		margin-bottom: 0.5rem;
		align-items: center;
	}

	.class-pair-row select {
		padding: 0.5rem 0.75rem;
		border: 1px solid #d1d5db;
		border-radius: 0.375rem;
		font-size: 0.875rem;
		background: white;
	}

	.class-pair-row select:focus {
		outline: none;
		border-color: #3b82f6;
		box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
	}

	.btn-remove-pair {
		padding: 0.375rem 0.5rem;
		background: #fef2f2;
		border: 1px solid #fecaca;
		color: #991b1b;
		border-radius: 0.25rem;
		cursor: pointer;
		font-size: 0.875rem;
		line-height: 1;
	}

	.btn-remove-pair:hover {
		background: #fee2e2;
	}

	.btn-add-pair {
		padding: 0.5rem 0.75rem;
		background: none;
		border: 1px dashed #d1d5db;
		border-radius: 0.375rem;
		color: #6b7280;
		cursor: pointer;
		font-size: 0.875rem;
		width: 100%;
		transition: all 0.2s;
	}

	.btn-add-pair:hover {
		border-color: #3b82f6;
		color: #3b82f6;
		background: #eff6ff;
	}

	.form-hint {
		padding: 0.75rem 1rem;
		background: #eff6ff;
		border-radius: 0.375rem;
		font-size: 0.875rem;
		color: #3b82f6;
		margin-bottom: 1.25rem;
	}

	.modal-actions {
		display: flex;
		justify-content: flex-end;
		gap: 0.75rem;
		padding-top: 1rem;
		border-top: 1px solid #e5e7eb;
	}

	.modal-actions-padded {
		padding: 1rem 1.5rem;
	}

	/* End confirmation modal */
	.modal-confirm {
		max-width: 24rem;
	}

	.modal-header-danger {
		background: #fef2f2;
		border-bottom-color: #fecaca;
	}

	.modal-header-danger h2 {
		color: #dc2626;
	}

	.delete-warning {
		margin: 0.75rem 0 0;
		font-size: 0.875rem;
		color: #6b7280;
	}

	@media (max-width: 640px) {
		.form-row {
			grid-template-columns: 1fr;
		}

		.class-pair-row {
			grid-template-columns: 1fr;
		}
	}

	@media (max-width: 767px) {
		.table-container {
			background: transparent;
			border: none;
		}

		.replacements-table thead {
			display: none;
		}

		.replacements-table tbody tr {
			display: block;
			background: white;
			border: 1px solid #e5e7eb;
			border-radius: 0.75rem;
			margin-bottom: 0.75rem;
			padding: 0.25rem 0;
		}

		.replacements-table tr:hover td {
			background: transparent;
		}

		.replacements-table td {
			display: flex;
			justify-content: space-between;
			align-items: baseline;
			padding: 0.5rem 1rem;
			border-bottom: none;
			text-align: right;
		}

		.replacements-table td::before {
			content: attr(data-label);
			font-weight: 600;
			font-size: 0.75rem;
			color: #6b7280;
			text-transform: uppercase;
			letter-spacing: 0.05em;
			text-align: left;
			margin-right: 1rem;
			flex-shrink: 0;
		}

		.teacher-cell {
			white-space: normal;
		}

		.classes-cell {
			min-width: 0;
		}

		.date-cell {
			white-space: normal;
		}

		.actions-cell {
			justify-content: flex-end;
			padding-top: 0.75rem;
			border-top: 1px solid #f3f4f6;
		}
	}
</style>
