package models

import (
	"time"

	"github.com/google/uuid"
)

// ========================================
// Stundenplan / Timetable
// ========================================

// TimetableSlot represents a time slot in the timetable
type TimetableSlot struct {
	ID         uuid.UUID `json:"id" db:"id"`
	SchoolID   uuid.UUID `json:"school_id" db:"school_id"`
	SlotNumber int       `json:"slot_number" db:"slot_number"` // 1, 2, 3... (Stunde)
	StartTime  string    `json:"start_time" db:"start_time"`   // "08:00"
	EndTime    string    `json:"end_time" db:"end_time"`       // "08:45"
	IsBreak    bool      `json:"is_break" db:"is_break"`       // Pause
	Name       *string   `json:"name,omitempty" db:"name"`     // e.g., "1. Stunde", "Große Pause"
}

// TimetableEntry represents a single lesson in the timetable
type TimetableEntry struct {
	ID           uuid.UUID  `json:"id" db:"id"`
	SchoolYearID uuid.UUID  `json:"school_year_id" db:"school_year_id"`
	ClassID      uuid.UUID  `json:"class_id" db:"class_id"`
	SubjectID    uuid.UUID  `json:"subject_id" db:"subject_id"`
	TeacherID    uuid.UUID  `json:"teacher_id" db:"teacher_id"`
	SlotID       uuid.UUID  `json:"slot_id" db:"slot_id"`
	DayOfWeek    int        `json:"day_of_week" db:"day_of_week"` // 1=Monday, 5=Friday
	Room         *string    `json:"room,omitempty" db:"room"`
	ValidFrom    time.Time  `json:"valid_from" db:"valid_from"`
	ValidUntil   *time.Time `json:"valid_until,omitempty" db:"valid_until"`
	CreatedAt    time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt    time.Time  `json:"updated_at" db:"updated_at"`
}

// TimetableSubstitution represents a substitution/replacement lesson
type TimetableSubstitution struct {
	ID                  uuid.UUID  `json:"id" db:"id"`
	OriginalEntryID     uuid.UUID  `json:"original_entry_id" db:"original_entry_id"`
	Date                time.Time  `json:"date" db:"date"`
	SubstituteTeacherID *uuid.UUID `json:"substitute_teacher_id,omitempty" db:"substitute_teacher_id"`
	SubstituteSubjectID *uuid.UUID `json:"substitute_subject_id,omitempty" db:"substitute_subject_id"`
	Room                *string    `json:"room,omitempty" db:"room"`
	Type                string     `json:"type" db:"type"` // 'substitution', 'cancelled', 'room_change', 'supervision'
	Note                *string    `json:"note,omitempty" db:"note"`
	CreatedAt           time.Time  `json:"created_at" db:"created_at"`
	CreatedBy           uuid.UUID  `json:"created_by" db:"created_by"`
}

// ========================================
// Abwesenheit / Attendance
// ========================================

// AttendanceRecord represents a student's attendance for a specific lesson
type AttendanceRecord struct {
	ID               uuid.UUID  `json:"id" db:"id"`
	StudentID        uuid.UUID  `json:"student_id" db:"student_id"`
	TimetableEntryID *uuid.UUID `json:"timetable_entry_id,omitempty" db:"timetable_entry_id"`
	Date             time.Time  `json:"date" db:"date"`
	SlotID           uuid.UUID  `json:"slot_id" db:"slot_id"`
	Status           string     `json:"status" db:"status"` // AttendanceStatus constants
	RecordedBy       uuid.UUID  `json:"recorded_by" db:"recorded_by"`
	Note             *string    `json:"note,omitempty" db:"note"`
	CreatedAt        time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt        time.Time  `json:"updated_at" db:"updated_at"`
}

// AbsenceReport represents a full absence report (one or more days)
type AbsenceReport struct {
	ID                     uuid.UUID  `json:"id" db:"id"`
	StudentID              uuid.UUID  `json:"student_id" db:"student_id"`
	StartDate              time.Time  `json:"start_date" db:"start_date"`
	EndDate                time.Time  `json:"end_date" db:"end_date"`
	Reason                 *string    `json:"reason,omitempty" db:"reason"`
	ReasonCategory         string     `json:"reason_category" db:"reason_category"`
	Status                 string     `json:"status" db:"status"`
	ReportedBy             uuid.UUID  `json:"reported_by" db:"reported_by"`
	ReportedAt             time.Time  `json:"reported_at" db:"reported_at"`
	ConfirmedBy            *uuid.UUID `json:"confirmed_by,omitempty" db:"confirmed_by"`
	ConfirmedAt            *time.Time `json:"confirmed_at,omitempty" db:"confirmed_at"`
	MedicalCertificate     bool       `json:"medical_certificate" db:"medical_certificate"`
	CertificateUploaded    bool       `json:"certificate_uploaded" db:"certificate_uploaded"`
	MatrixNotificationSent bool       `json:"matrix_notification_sent" db:"matrix_notification_sent"`
	EmailNotificationSent  bool       `json:"email_notification_sent" db:"email_notification_sent"`
	CreatedAt              time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt              time.Time  `json:"updated_at" db:"updated_at"`
}

// AbsenceNotification tracks notifications sent to parents about absences
type AbsenceNotification struct {
	ID                 uuid.UUID  `json:"id" db:"id"`
	AttendanceRecordID uuid.UUID  `json:"attendance_record_id" db:"attendance_record_id"`
	ParentID           uuid.UUID  `json:"parent_id" db:"parent_id"`
	Channel            string     `json:"channel" db:"channel"`
	MessageContent     string     `json:"message_content" db:"message_content"`
	SentAt             *time.Time `json:"sent_at,omitempty" db:"sent_at"`
	ReadAt             *time.Time `json:"read_at,omitempty" db:"read_at"`
	ResponseReceived   bool       `json:"response_received" db:"response_received"`
	ResponseContent    *string    `json:"response_content,omitempty" db:"response_content"`
	ResponseAt         *time.Time `json:"response_at,omitempty" db:"response_at"`
	CreatedAt          time.Time  `json:"created_at" db:"created_at"`
}

// ========================================
// Notenspiegel / Grades
// ========================================

// GradeScale represents the grading scale used
type GradeScale struct {
	ID           uuid.UUID `json:"id" db:"id"`
	SchoolID     uuid.UUID `json:"school_id" db:"school_id"`
	Name         string    `json:"name" db:"name"`
	MinValue     float64   `json:"min_value" db:"min_value"`
	MaxValue     float64   `json:"max_value" db:"max_value"`
	PassingValue float64   `json:"passing_value" db:"passing_value"`
	IsAscending  bool      `json:"is_ascending" db:"is_ascending"`
	IsDefault    bool      `json:"is_default" db:"is_default"`
	CreatedAt    time.Time `json:"created_at" db:"created_at"`
}

// Grade represents a single grade for a student
type Grade struct {
	ID           uuid.UUID  `json:"id" db:"id"`
	StudentID    uuid.UUID  `json:"student_id" db:"student_id"`
	SubjectID    uuid.UUID  `json:"subject_id" db:"subject_id"`
	TeacherID    uuid.UUID  `json:"teacher_id" db:"teacher_id"`
	SchoolYearID uuid.UUID  `json:"school_year_id" db:"school_year_id"`
	GradeScaleID uuid.UUID  `json:"grade_scale_id" db:"grade_scale_id"`
	Type         string     `json:"type" db:"type"`
	Value        float64    `json:"value" db:"value"`
	Weight       float64    `json:"weight" db:"weight"`
	Date         time.Time  `json:"date" db:"date"`
	Title        *string    `json:"title,omitempty" db:"title"`
	Description  *string    `json:"description,omitempty" db:"description"`
	IsVisible    bool       `json:"is_visible" db:"is_visible"`
	Semester     int        `json:"semester" db:"semester"`
	CreatedAt    time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt    time.Time  `json:"updated_at" db:"updated_at"`
}

// GradeComment represents a teacher comment on a student's grade
type GradeComment struct {
	ID        uuid.UUID `json:"id" db:"id"`
	GradeID   uuid.UUID `json:"grade_id" db:"grade_id"`
	TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"`
	Comment   string    `json:"comment" db:"comment"`
	IsPrivate bool      `json:"is_private" db:"is_private"`
	CreatedAt time.Time `json:"created_at" db:"created_at"`
}

// ========================================
// Klassenbuch, Meetings, Communication
// ========================================

// ClassDiaryEntry represents an entry in the digital class diary
type ClassDiaryEntry struct {
	ID                 uuid.UUID  `json:"id" db:"id"`
	ClassID            uuid.UUID  `json:"class_id" db:"class_id"`
	Date               time.Time  `json:"date" db:"date"`
	SlotID             uuid.UUID  `json:"slot_id" db:"slot_id"`
	SubjectID          uuid.UUID  `json:"subject_id" db:"subject_id"`
	TeacherID          uuid.UUID  `json:"teacher_id" db:"teacher_id"`
	Topic              *string    `json:"topic,omitempty" db:"topic"`
	Homework           *string    `json:"homework,omitempty" db:"homework"`
	HomeworkDueDate    *time.Time `json:"homework_due_date,omitempty" db:"homework_due_date"`
	Materials          *string    `json:"materials,omitempty" db:"materials"`
	Notes              *string    `json:"notes,omitempty" db:"notes"`
	IsCancelled        bool       `json:"is_cancelled" db:"is_cancelled"`
	CancellationReason *string    `json:"cancellation_reason,omitempty" db:"cancellation_reason"`
	CreatedAt          time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt          time.Time  `json:"updated_at" db:"updated_at"`
}

// ParentMeetingSlot represents available time slots for parent meetings
type ParentMeetingSlot struct {
	ID          uuid.UUID `json:"id" db:"id"`
	TeacherID   uuid.UUID `json:"teacher_id" db:"teacher_id"`
	Date        time.Time `json:"date" db:"date"`
	StartTime   string    `json:"start_time" db:"start_time"`
	EndTime     string    `json:"end_time" db:"end_time"`
	Location    *string   `json:"location,omitempty" db:"location"`
	IsOnline    bool      `json:"is_online" db:"is_online"`
	MeetingLink *string   `json:"meeting_link,omitempty" db:"meeting_link"`
	IsBooked    bool      `json:"is_booked" db:"is_booked"`
	CreatedAt   time.Time `json:"created_at" db:"created_at"`
}

// ParentMeeting represents a booked parent-teacher meeting
type ParentMeeting struct {
	ID           uuid.UUID  `json:"id" db:"id"`
	SlotID       uuid.UUID  `json:"slot_id" db:"slot_id"`
	ParentID     uuid.UUID  `json:"parent_id" db:"parent_id"`
	StudentID    uuid.UUID  `json:"student_id" db:"student_id"`
	Topic        *string    `json:"topic,omitempty" db:"topic"`
	Notes        *string    `json:"notes,omitempty" db:"notes"`
	Status       string     `json:"status" db:"status"`
	CancelledAt  *time.Time `json:"cancelled_at,omitempty" db:"cancelled_at"`
	CancelledBy  *uuid.UUID `json:"cancelled_by,omitempty" db:"cancelled_by"`
	CancelReason *string    `json:"cancel_reason,omitempty" db:"cancel_reason"`
	CompletedAt  *time.Time `json:"completed_at,omitempty" db:"completed_at"`
	CreatedAt    time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt    time.Time  `json:"updated_at" db:"updated_at"`
}

// MatrixRoom tracks Matrix rooms created for school communication
type MatrixRoom struct {
	ID           uuid.UUID  `json:"id" db:"id"`
	SchoolID     uuid.UUID  `json:"school_id" db:"school_id"`
	MatrixRoomID string     `json:"matrix_room_id" db:"matrix_room_id"`
	Type         string     `json:"type" db:"type"`
	ClassID      *uuid.UUID `json:"class_id,omitempty" db:"class_id"`
	StudentID    *uuid.UUID `json:"student_id,omitempty" db:"student_id"`
	Name         string     `json:"name" db:"name"`
	IsEncrypted  bool       `json:"is_encrypted" db:"is_encrypted"`
	CreatedAt    time.Time  `json:"created_at" db:"created_at"`
}

// MatrixRoomMember tracks membership in Matrix rooms
type MatrixRoomMember struct {
	ID           uuid.UUID  `json:"id" db:"id"`
	MatrixRoomID uuid.UUID  `json:"matrix_room_id" db:"matrix_room_id"`
	MatrixUserID string     `json:"matrix_user_id" db:"matrix_user_id"`
	UserID       *uuid.UUID `json:"user_id,omitempty" db:"user_id"`
	PowerLevel   int        `json:"power_level" db:"power_level"`
	CanWrite     bool       `json:"can_write" db:"can_write"`
	JoinedAt     time.Time  `json:"joined_at" db:"joined_at"`
	LeftAt       *time.Time `json:"left_at,omitempty" db:"left_at"`
}

// ParentOnboardingToken for QR-code based parent onboarding
type ParentOnboardingToken struct {
	ID           uuid.UUID  `json:"id" db:"id"`
	SchoolID     uuid.UUID  `json:"school_id" db:"school_id"`
	ClassID      uuid.UUID  `json:"class_id" db:"class_id"`
	StudentID    uuid.UUID  `json:"student_id" db:"student_id"`
	Token        string     `json:"token" db:"token"`
	Role         string     `json:"role" db:"role"`
	ExpiresAt    time.Time  `json:"expires_at" db:"expires_at"`
	UsedAt       *time.Time `json:"used_at,omitempty" db:"used_at"`
	UsedByUserID *uuid.UUID `json:"used_by_user_id,omitempty" db:"used_by_user_id"`
	CreatedAt    time.Time  `json:"created_at" db:"created_at"`
	CreatedBy    uuid.UUID  `json:"created_by" db:"created_by"`
}

// ========================================
// Schulverwaltung DTOs
// ========================================

// CreateSchoolRequest for creating a new school
type CreateSchoolRequest struct {
	Name       string  `json:"name" binding:"required"`
	ShortName  *string `json:"short_name"`
	Type       string  `json:"type" binding:"required"`
	Address    *string `json:"address"`
	City       *string `json:"city"`
	PostalCode *string `json:"postal_code"`
	State      *string `json:"state"`
	Phone      *string `json:"phone"`
	Email      *string `json:"email"`
	Website    *string `json:"website"`
}

// CreateClassRequest for creating a new class
type CreateClassRequest struct {
	SchoolYearID string  `json:"school_year_id" binding:"required"`
	Name         string  `json:"name" binding:"required"`
	Grade        int     `json:"grade" binding:"required"`
	Section      *string `json:"section"`
	Room         *string `json:"room"`
}

// CreateStudentRequest for creating a new student
type CreateStudentRequest struct {
	ClassID       string  `json:"class_id" binding:"required"`
	StudentNumber *string `json:"student_number"`
	FirstName     string  `json:"first_name" binding:"required"`
	LastName      string  `json:"last_name" binding:"required"`
	DateOfBirth   *string `json:"date_of_birth"` // ISO 8601
	Gender        *string `json:"gender"`
}

// RecordAttendanceRequest for recording attendance
type RecordAttendanceRequest struct {
	StudentID string  `json:"student_id" binding:"required"`
	Date      string  `json:"date" binding:"required"` // ISO 8601
	SlotID    string  `json:"slot_id" binding:"required"`
	Status    string  `json:"status" binding:"required"` // AttendanceStatus
	Note      *string `json:"note"`
}

// ReportAbsenceRequest for parents reporting absence
type ReportAbsenceRequest struct {
	StudentID      string  `json:"student_id" binding:"required"`
	StartDate      string  `json:"start_date" binding:"required"`
	EndDate        string  `json:"end_date" binding:"required"`
	Reason         *string `json:"reason"`
	ReasonCategory string  `json:"reason_category" binding:"required"`
}

// CreateGradeRequest for creating a grade
type CreateGradeRequest struct {
	StudentID    string  `json:"student_id" binding:"required"`
	SubjectID    string  `json:"subject_id" binding:"required"`
	SchoolYearID string  `json:"school_year_id" binding:"required"`
	Type         string  `json:"type" binding:"required"`
	Value        float64 `json:"value" binding:"required"`
	Weight       float64 `json:"weight"`
	Date         string  `json:"date" binding:"required"`
	Title        *string `json:"title"`
	Description  *string `json:"description"`
	Semester     int     `json:"semester" binding:"required"`
}

// StudentGradeOverview provides a summary of all grades for a student in a subject
type StudentGradeOverview struct {
	Student     Student `json:"student"`
	Subject     Subject `json:"subject"`
	Grades      []Grade `json:"grades"`
	Average     float64 `json:"average"`
	OralAverage float64 `json:"oral_average"`
	ExamAverage float64 `json:"exam_average"`
	Semester    int     `json:"semester"`
}

// ClassAttendanceOverview provides attendance summary for a class
type ClassAttendanceOverview struct {
	Class         Class              `json:"class"`
	Date          time.Time          `json:"date"`
	TotalStudents int                `json:"total_students"`
	PresentCount  int                `json:"present_count"`
	AbsentCount   int                `json:"absent_count"`
	LateCount     int                `json:"late_count"`
	Records       []AttendanceRecord `json:"records"`
}

// ParentDashboard provides a parent's view of their children's data
type ParentDashboard struct {
	Children         []StudentOverview `json:"children"`
	UnreadMessages   int               `json:"unread_messages"`
	UpcomingMeetings []ParentMeeting   `json:"upcoming_meetings"`
	RecentGrades     []Grade           `json:"recent_grades"`
	PendingActions   []string          `json:"pending_actions"`
}

// StudentOverview provides summary info about a student
type StudentOverview struct {
	Student           Student  `json:"student"`
	Class             Class    `json:"class"`
	ClassTeacher      *Teacher `json:"class_teacher,omitempty"`
	AttendanceRate    float64  `json:"attendance_rate"`
	UnexcusedAbsences int      `json:"unexcused_absences"`
	GradeAverage      float64  `json:"grade_average"`
}

// TimetableView provides a formatted timetable for display
type TimetableView struct {
	Class Class              `json:"class"`
	Week  string             `json:"week"` // ISO week: "2025-W01"
	Days  []TimetableDayView `json:"days"`
}

// TimetableDayView represents a single day in the timetable
type TimetableDayView struct {
	Date    time.Time             `json:"date"`
	DayName string                `json:"day_name"`
	Lessons []TimetableLessonView `json:"lessons"`
}

// TimetableLessonView represents a single lesson in the timetable view
type TimetableLessonView struct {
	Slot           TimetableSlot `json:"slot"`
	Subject        *Subject      `json:"subject,omitempty"`
	Teacher        *Teacher      `json:"teacher,omitempty"`
	Room           *string       `json:"room,omitempty"`
	IsSubstitution bool          `json:"is_substitution"`
	IsCancelled    bool          `json:"is_cancelled"`
	Note           *string       `json:"note,omitempty"`
}
