import { browser } from '$app/environment';

// API Client für Backend-Kommunikation
const API_BASE_URL = browser 
	? (import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000/api')
	: (import.meta.env.VITE_INTERNAL_API_URL || 'http://backend:3000/api');

interface ApiResponse<T> {
	data?: T;
	error?: string;
}

class ApiClient {
	private baseUrl: string;

	constructor(baseUrl: string) {
		this.baseUrl = baseUrl;
	}

	private async request<T>(
		endpoint: string,
		options: RequestInit = {}
	): Promise<ApiResponse<T>> {
		try {
			const headers: HeadersInit = { ...options.headers };
			
			// Content-Type nur setzen, wenn kein FormData gesendet wird (Browser setzt Boundary automatisch)
			if (!(options.body instanceof FormData)) {
				(headers as any)['Content-Type'] = 'application/json';
			}

			const response = await fetch(`${this.baseUrl}${endpoint}`, {
				...options,
				credentials: 'include', // Wichtig für httpOnly Cookies
				headers
			});

			if (!response.ok) {
				const errorData = await response.json().catch(() => ({ message: 'Ein Fehler ist aufgetreten' }));
				return { error: errorData.message || `HTTP Error ${response.status}` };
			}

			const data = await response.json();
			return { data };
		} catch (error) {
			return { error: error instanceof Error ? error.message : 'Netzwerkfehler' };
		}
	}

    async post<T>(endpoint: string, body: any) {
        return this.request<T>(endpoint, {
            method: 'POST',
            body: JSON.stringify(body)
        });
    }

	// Auth Endpoints
	async login(username: string, password: string) {
		return this.request<{ message: string; user: User }>('/auth/login', {
			method: 'POST',
			body: JSON.stringify({ username, password })
		});
	}

	async register(email: string, username: string, password: string, role: 'Student' | 'Lehrer' = 'Student') {
		return this.request<{ message: string; user: User }>('/auth/register', {
			method: 'POST',
			body: JSON.stringify({ email, username, password, role })
		});
	}

	async logout() {
		return this.request<{ message: string }>('/auth/logout', {
			method: 'POST'
		});
	}

	async getMe() {
		return this.request<User>('/auth/me');
	}

	// Users Endpoints (nur für Lehrer)
	async getUsers() {
		return this.request<User[]>('/users');
	}

	async getUser(id: number) {
		return this.request<User>(`/users/${id}`);
	}

	async updateUser(id: number, data: Partial<UpdateUserDto>) {
		return this.request<User>(`/users/${id}`, {
			method: 'PATCH',
			body: JSON.stringify(data)
		});
	}

	async deleteUser(id: number) {
		return this.request<{ message: string }>(`/users/${id}`, {
			method: 'DELETE'
		});
	}

	// Files Endpoints
	async uploadFile(file: File, timetableEntryId?: number) {
		const formData = new FormData();
		formData.append('file', file);
		if (timetableEntryId) {
			formData.append('timetableEntryId', timetableEntryId.toString());
		}

		return this.request<FileEntity>('/files/upload', {
			method: 'POST',
			body: formData
		});
	}

	async getGeneralFiles() {
		return this.request<FileEntity[]>('/files');
	}

	async getLessonFiles(lessonId: number) {
		return this.request<FileEntity[]>(`/files/lesson/${lessonId}`);
	}

	async deleteFile(id: number) {
		return this.request<{ success: boolean }>(`/files/${id}`, {
			method: 'DELETE'
		});
	}

	getDownloadUrl(id: number) {
		return `${this.baseUrl}/files/download/${id}`;
	}

	// Subjects Endpoints
	async getSubjects() {
		return this.request<Subject[]>('/subjects');
	}

	async getSubject(id: number) {
		return this.request<Subject>(`/subjects/${id}`);
	}

	async createSubject(data: CreateSubjectDto) {
		return this.request<Subject>('/subjects', {
			method: 'POST',
			body: JSON.stringify(data)
		});
	}

	async updateSubject(id: number, data: Partial<CreateSubjectDto>) {
		return this.request<Subject>(`/subjects/${id}`, {
			method: 'PUT',
			body: JSON.stringify(data)
		});
	}

	async deleteSubject(id: number) {
		return this.request<{ message: string }>(`/subjects/${id}`, {
			method: 'DELETE'
		});
	}

	// Rooms Endpoints
	async getRooms() {
		return this.request<Room[]>('/rooms');
	}

	async getRoom(id: number) {
		return this.request<Room>(`/rooms/${id}`);
	}

	async createRoom(data: CreateRoomDto) {
		return this.request<Room>('/rooms', {
			method: 'POST',
			body: JSON.stringify(data)
		});
	}

	async updateRoom(id: number, data: Partial<CreateRoomDto>) {
		return this.request<Room>(`/rooms/${id}`, {
			method: 'PUT',
			body: JSON.stringify(data)
		});
	}

	async deleteRoom(id: number) {
		return this.request<{ message: string }>(`/rooms/${id}`, {
			method: 'DELETE'
		});
	}

	// Timetable Endpoints
	async getTimetable(weekNumber?: number, year?: number) {
		const params = new URLSearchParams();
		if (weekNumber !== undefined) params.append('weekNumber', weekNumber.toString());
		if (year !== undefined) params.append('year', year.toString());
		const query = params.toString() ? `?${params.toString()}` : '';
		return this.request<TimetableEntry[]>(`/timetable${query}`);
	}

	async createTimetableEntry(data: CreateTimetableEntryDto) {
		return this.request<TimetableEntry>('/timetable', {
			method: 'POST',
			body: JSON.stringify(data)
		});
	}

	async updateTimetableEntry(id: number, data: Partial<CreateTimetableEntryDto>) {
		return this.request<TimetableEntry>(`/timetable/${id}`, {
			method: 'PUT',
			body: JSON.stringify(data)
		});
	}

	async deleteTimetableEntry(id: number) {
		return this.request<{ message: string }>(`/timetable/${id}`, {
			method: 'DELETE'
		});
	}

	// Feedback Endpoints
	async getFeedback() {
		return this.request<Feedback[]>('/feedback/all');
	}

	async getFeedbackByLesson(lessonId: string) {
		return this.request<Feedback[]>(`/feedback/lesson/${lessonId}`);
	}

	async createFeedback(data: CreateFeedbackDto) {
		return this.request<Feedback>('/feedback', {
			method: 'POST',
			body: JSON.stringify(data)
		});
	}

	async getTeachers() {
		return this.request<User[]>('/users/teachers');
	}

	// Grades Endpoints
	async getGradesByTimetableEntry(timetableEntryId: number, weekNumber: number, year: number) {
		return this.request<Grade[]>(`/grades/timetable/${timetableEntryId}?weekNumber=${weekNumber}&year=${year}`);
	}

	async getGrades(filters?: { studentId?: number; timetableEntryId?: number; teacherId?: number }) {
		const params = new URLSearchParams();
		if (filters?.studentId) params.append('studentId', filters.studentId.toString());
		if (filters?.timetableEntryId) params.append('timetableEntryId', filters.timetableEntryId.toString());
		if (filters?.teacherId) params.append('teacherId', filters.teacherId.toString());
		const query = params.toString() ? `?${params.toString()}` : '';
		return this.request<Grade[]>(`/grades${query}`);
	}

	async getAverageGrade(timetableEntryId: number) {
		return this.request<GradeAverage>(`/grades/average/${timetableEntryId}`);
	}

	async getStudentOverview() {
		return this.request<SubjectOverview[]>('/grades/overview');
	}

	async createGrade(data: CreateGradeDto) {
		return this.request<Grade>('/grades', {
			method: 'POST',
			body: JSON.stringify(data)
		});
	}

	async updateGrade(id: number, data: Partial<CreateGradeDto>) {
		return this.request<Grade>(`/grades/${id}`, {
			method: 'PUT',
			body: JSON.stringify(data)
		});
	}

	async deleteGrade(id: number) {
		return this.request<{ message: string }>(`/grades/${id}`, {
			method: 'DELETE'
		});
	}

	// Lehrer: Komplette Notenübersicht für alle Fächer
	async getTeacherGradesOverview() {
		return this.request<TeacherGradesOverview[]>('/grades/teacher/overview');
	}

	// Lehrer: Detaillierte Notenansicht für ein spezifisches Fach
	async getSubjectGradeDetails(timetableEntryId: number) {
		return this.request<SubjectGradeDetails>(`/grades/subject/${timetableEntryId}`);
	}

	// Lehrer: Detaillierte Notenansicht für alle Stundenplan-Einträge mit gleichem Fachnamen
	async getSubjectGradeDetailsByName(subjectName: string) {
		return this.request<SubjectGradeDetailsByName>(`/grades/subject-by-name/${encodeURIComponent(subjectName)}`);
	}

    // Attendance Endpoints
    async getPresentStudents() {
        return this.request<AttendanceStatus>('/attendance/present');
    }
}

// Types
export interface PresentStudent {
    studentId: number;
    name: string;
    className: string;
    checkInTime: string;
    minutesPresent: number;
}

export interface AbsentStudent {
    studentId: number;
    name: string;
    className: string;
}

export interface AttendanceStatus {
    date: string;
    time: string;
    presentStudents: PresentStudent[];
    absentStudents: AbsentStudent[];
    totalPresent: number;
    totalAbsent: number;
}

export interface User {
	id: number;
	email: string;
	username: string;
	role: 'Student' | 'Lehrer';
	createdAt?: string;
	updatedAt?: string;
}

export interface UpdateUserDto {
	email?: string;
	username?: string;
	password?: string;
	role?: 'Student' | 'Lehrer';
}

export interface Subject {
	id: number;
	name: string; // z.B. "Mathematik", "Deutsch"
	abbreviation?: string | null; // z.B. "Mathe", "DE"
	color?: string | null; // z.B. "#FF5733"
	createdAt?: string;
	updatedAt?: string;
}

export interface CreateSubjectDto {
	name: string;
	abbreviation?: string;
	color?: string;
}

export interface Room {
	id: number;
	number: string; // z.B. "A101", "B203"
	building?: string | null; // z.B. "Hauptgebäude"
	capacity?: number | null;
	equipment?: string | null; // z.B. "Beamer, Whiteboard"
	createdAt?: string;
	updatedAt?: string;
}

export interface CreateRoomDto {
	number: string;
	building?: string;
	capacity?: number;
	equipment?: string;
}

export interface TimetableEntry {
	id: number;
	dayOfWeek: number; // 1-5 (Montag-Freitag)
	startTime: string; // Format: "HH:MM"
	endTime: string; // Format: "HH:MM"
	subjectId: number;
	subject: Subject;
	teacherId?: number | null;
	teacher?: User | null;
	roomId?: number | null;
	room?: Room | null;
	weekNumber?: number; // 1-53 (Kalenderwoche)
	year?: number; // Jahr (z.B. 2025)
	isRecurring?: boolean; // true = wiederholt sich jede Woche
	allowStudentUploads?: boolean;
	createdAt?: string;
	updatedAt?: string;
}

export interface CreateTimetableEntryDto {
	dayOfWeek: number;
	startTime: string;
	endTime: string;
	subjectId?: number;
    subjectName?: string;
	teacherId?: number;
	roomId?: number;
    roomNumber?: string;
	weekNumber?: number;
	year?: number;
	isRecurring?: boolean;
	allowStudentUploads?: boolean;
}

export interface FileEntity {
	id: number;
	filename: string;
	path: string;
	mimetype: string;
	size: number;
	uploadedById: number;
	uploadedBy: {
		id?: number;
		username: string;
		role: string;
	};
	timetableEntryId?: number | null;
	createdAt: string;
}

export interface Feedback {
	id: number;
	studentId: number;
	student?: {
		id: number;
		username: string;
		email: string;
	};
	teacherId: number;
	teacher?: {
		id: number;
		username: string;
		email: string;
	};
	lessonId: number;
	timetableEntry?: {
		id: number;
		subject: Subject;
		teacher?: User | null;
		room?: Room | null;
		dayOfWeek: number;
		startTime: string;
		endTime: string;
	};
	lessonDate: string;
	overallRating: number;
	categories?: {
		clarity?: number;
		pace?: number;
		interaction?: number;
		materials?: number;
		atmosphere?: number;
	};
	whatWasGood?: string;
	whatCanImprove?: string;
	additionalComments?: string;
	isAnonymous: boolean;
	allowTeacherResponse: boolean;
	teacherResponse?: string | null;
	teacherRespondedAt?: string | null;
	createdAt?: string;
}

export interface CreateFeedbackDto {
	studentId: number;
	teacherId: number;
	lessonId: number;
	lessonDate: Date | string;
	overallRating: number;
	categories?: {
		clarity?: number;
		pace?: number;
		interaction?: number;
		materials?: number;
		atmosphere?: number;
	};
	whatWasGood?: string;
	whatCanImprove?: string;
	additionalComments?: string;
	isAnonymous?: boolean;
	allowTeacherResponse?: boolean;
}

export interface Grade {
	id: number;
	studentId: number;
	student?: {
		id: number;
		username: string;
		email: string;
	};
	timetableEntryId: number;
	timetableEntry?: {
		id: number;
		subject: Subject;
		teacher?: User | null;
		room?: Room | null;
		dayOfWeek?: number;
		startTime?: string;
		endTime?: string;
	};
	weekNumber: number;
	year: number;
	grade: number;
	gradeType: string;
	weight?: number;
	title?: string;
	description?: string;
	maxPoints?: number;
	achievedPoints?: number;
	date: string;
	teacherId: number;
	teacher?: {
		id: number;
		username: string;
		email: string;
	};
	createdAt?: string;
	updatedAt?: string;
}

export interface CreateGradeDto {
	studentId: number;
	timetableEntryId: number;
	weekNumber: number;
	year: number;
	grade: number;
	gradeType: string;
	weight?: number;
	title?: string;
	description?: string;
	maxPoints?: number;
	achievedPoints?: number;
	date: string;
	teacherId: number;
}

export interface GradeAverage {
	average: number;
	gradeCount: number;
	grades: {
		id: number;
		grade: number;
		gradeType: string;
		weight?: number;
		title?: string;
		date: string;
	}[];
}

export interface SubjectOverview {
	timetableEntryId: number;
	subject: Subject;
	teacher?: User | null;
	average: number;
	gradeCount: number;
	latestGrade: Grade;
}

// Lehrer-spezifische Notenübersicht
export interface TeacherGradesOverview {
	subject: Subject;
	timetableEntryIds: number[]; // Alle IDs für dieses Fach
	timetableEntries: Array<{
		id: number;
		teacher?: User | null;
		dayOfWeek: number;
		startTime: string;
		endTime: string;
	}>; // Alle Stundenplan-Einträge für dieses Fach
	studentCount: number;
	totalGrades: number;
	students: StudentGradesSummary[];
}

export interface StudentGradesSummary {
	student: {
		id: number;
		username: string;
		email: string;
	};
	average: number | null;
	gradeCount: number;
	grades: Grade[];
}

// Detaillierte Notenansicht für ein Fach
export interface SubjectGradeDetails {
	timetableEntry: {
		id: number;
		subject: Subject;
		teacher?: User | null;
		room?: Room | null;
		dayOfWeek: number;
		startTime: string;
		endTime: string;
	};
	students: StudentWithGrades[];
	totalStudents: number;
	totalGrades: number;
}

export interface SubjectGradeDetailsByName {
	subject: Subject;
	timetableEntries: Array<{
		id: number;
		teacher?: User | null;
		room?: Room | null;
		dayOfWeek: number;
		startTime: string;
		endTime: string;
	}>;
	students: StudentWithGrades[];
	totalStudents: number;
	totalGrades: number;
}

export interface StudentWithGrades {
	student: {
		id: number;
		username: string;
		email: string;
	};
	average: number | null;
	totalWeight: number;
	gradeCount: number;
	grades: GradeDetail[];
}

export interface GradeDetail {
	id: number;
	grade: number;
	gradeType: string;
	weight: number;
	title?: string;
	description?: string;
	maxPoints?: number;
	achievedPoints?: number;
	date: string;
	weekNumber: number;
	year: number;
}

export const api = new ApiClient(API_BASE_URL);
