import { getApiBaseUrl } from '$lib/api';
import { authenticatedFetch } from '$lib/auth';

export interface Student {
	id: string;
	firstName: string;
	lastName: string;
	email: string | null;
	classId: string | null;
	className: string | null;
	classLevel: string | null;
	statut: string;
	studentNumber: string | null;
	dateNaissance: string | null;
}

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

export interface FetchStudentsParams {
	page: number;
	itemsPerPage: number;
	search?: string | undefined;
	classId?: string | undefined;
	signal?: AbortSignal | undefined;
}

export interface FetchStudentsResult {
	members: Student[];
	totalItems: number;
}

export interface CreateStudentData {
	firstName: string;
	lastName: string;
	classId: string;
	email?: string | undefined;
	dateNaissance?: string | undefined;
	studentNumber?: string | undefined;
	parentalConsent?: boolean | undefined;
}

/**
 * Récupère la liste paginée des élèves.
 */
export async function fetchStudents(params: FetchStudentsParams): Promise<FetchStudentsResult> {
	const apiUrl = getApiBaseUrl();
	const searchParams = new URLSearchParams();
	searchParams.set('page', String(params.page));
	searchParams.set('itemsPerPage', String(params.itemsPerPage));
	if (params.search) searchParams.set('search', params.search);
	if (params.classId) searchParams.set('classId', params.classId);

	const options: RequestInit = {};
	if (params.signal) options.signal = params.signal;

	const response = await authenticatedFetch(
		`${apiUrl}/students?${searchParams.toString()}`,
		options
	);

	if (!response.ok) {
		throw new Error('Erreur lors du chargement des élèves');
	}

	const data = await response.json();
	const members: Student[] =
		data['hydra:member'] ?? data['member'] ?? (Array.isArray(data) ? data : []);
	const totalItems: number = data['hydra:totalItems'] ?? data['totalItems'] ?? members.length;

	return { members, totalItems };
}

/**
 * Récupère la liste des classes disponibles.
 */
export async function fetchClasses(): Promise<SchoolClass[]> {
	const apiUrl = getApiBaseUrl();
	const response = await authenticatedFetch(`${apiUrl}/classes?itemsPerPage=200`);

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

	const data = await response.json();
	return data['hydra:member'] ?? data['member'] ?? (Array.isArray(data) ? data : []);
}

/**
 * Crée un nouvel élève.
 */
export async function createStudent(studentData: CreateStudentData): Promise<Student> {
	const apiUrl = getApiBaseUrl();
	const body: Record<string, string | boolean> = {
		firstName: studentData.firstName,
		lastName: studentData.lastName,
		classId: studentData.classId
	};
	if (studentData.email) body['email'] = studentData.email;
	if (studentData.dateNaissance) body['dateNaissance'] = studentData.dateNaissance;
	if (studentData.studentNumber) body['studentNumber'] = studentData.studentNumber;
	if (studentData.parentalConsent) body['parentalConsent'] = true;

	const response = await authenticatedFetch(`${apiUrl}/students`, {
		method: 'POST',
		headers: { 'Content-Type': 'application/json' },
		body: JSON.stringify(body)
	});

	if (!response.ok) {
		let errorMessage = `Erreur lors de la création (${response.status})`;
		try {
			const errorData = await response.json();
			if (errorData['hydra:description']) errorMessage = errorData['hydra:description'];
			else if (errorData.message) errorMessage = errorData.message;
			else if (errorData.detail) errorMessage = errorData.detail;
		} catch {
			// JSON parsing failed
		}
		throw new Error(errorMessage);
	}

	return await response.json();
}

/**
 * Change la classe d'un élève.
 */
export async function changeStudentClass(studentId: string, newClassId: string): Promise<void> {
	const apiUrl = getApiBaseUrl();
	const response = await authenticatedFetch(`${apiUrl}/students/${studentId}/class`, {
		method: 'PATCH',
		headers: { 'Content-Type': 'application/merge-patch+json' },
		body: JSON.stringify({ classId: newClassId })
	});

	if (!response.ok) {
		let errorMessage = `Erreur lors du changement de classe (${response.status})`;
		try {
			const errorData = await response.json();
			if (errorData['hydra:description']) errorMessage = errorData['hydra:description'];
			else if (errorData.message) errorMessage = errorData.message;
			else if (errorData.detail) errorMessage = errorData.detail;
		} catch {
			// JSON parsing failed
		}
		throw new Error(errorMessage);
	}
}
