package models

import (
	"time"

	"github.com/google/uuid"
)

// SchoolYear represents a school year
type SchoolYear struct {
	ID        uuid.UUID `json:"id" db:"id"`
	Name      string    `json:"name" db:"name"`
	StartDate time.Time `json:"start_date" db:"start_date"`
	EndDate   time.Time `json:"end_date" db:"end_date"`
	IsCurrent bool      `json:"is_current" db:"is_current"`
	TeacherID uuid.UUID `json:"teacher_id" db:"teacher_id"`
	CreatedAt time.Time `json:"created_at" db:"created_at"`
}

// Class represents a school class
type Class struct {
	ID           uuid.UUID  `json:"id" db:"id"`
	TeacherID    uuid.UUID  `json:"teacher_id" db:"teacher_id"`
	SchoolYearID *uuid.UUID `json:"school_year_id,omitempty" db:"school_year_id"`
	Name         string     `json:"name" db:"name"`
	GradeLevel   int        `json:"grade_level" db:"grade_level"`
	SchoolType   string     `json:"school_type,omitempty" db:"school_type"`
	FederalState string     `json:"federal_state,omitempty" db:"federal_state"`
	CreatedAt    time.Time  `json:"created_at" db:"created_at"`
	StudentCount int        `json:"student_count,omitempty"` // Computed field
}

// Student represents a student
type Student struct {
	ID            uuid.UUID  `json:"id" db:"id"`
	ClassID       uuid.UUID  `json:"class_id" db:"class_id"`
	FirstName     string     `json:"first_name" db:"first_name"`
	LastName      string     `json:"last_name" db:"last_name"`
	BirthDate     *time.Time `json:"birth_date,omitempty" db:"date_of_birth"`
	StudentNumber *string    `json:"student_number,omitempty" db:"student_number"`
	Notes         *string    `json:"notes,omitempty" db:"notes"`
	CreatedAt     time.Time  `json:"created_at" db:"created_at"`
}

// Subject represents a school subject
type Subject struct {
	ID            uuid.UUID `json:"id" db:"id"`
	TeacherID     uuid.UUID `json:"teacher_id" db:"teacher_id"`
	Name          string    `json:"name" db:"name"`
	ShortName     string    `json:"short_name,omitempty" db:"short_name"`
	IsMainSubject bool      `json:"is_main_subject" db:"is_main_subject"`
	CreatedAt     time.Time `json:"created_at" db:"created_at"`
}

// ExamType represents types of exams
type ExamType string

const (
	ExamTypeKlassenarbeit ExamType = "klassenarbeit"
	ExamTypeTest          ExamType = "test"
	ExamTypeKlausur       ExamType = "klausur"
)

// ExamStatus represents exam status
type ExamStatus string

const (
	ExamStatusDraft    ExamStatus = "draft"
	ExamStatusActive   ExamStatus = "active"
	ExamStatusArchived ExamStatus = "archived"
)

// Exam represents an exam/test
type Exam struct {
	ID              uuid.UUID  `json:"id" db:"id"`
	TeacherID       uuid.UUID  `json:"teacher_id" db:"teacher_id"`
	ClassID         *uuid.UUID `json:"class_id,omitempty" db:"class_id"`
	SubjectID       *uuid.UUID `json:"subject_id,omitempty" db:"subject_id"`
	Title           string     `json:"title" db:"title"`
	ExamType        ExamType   `json:"exam_type" db:"exam_type"`
	Topic           string     `json:"topic,omitempty" db:"topic"`
	Content         string     `json:"content,omitempty" db:"content"`
	SourceFilePath  string     `json:"source_file_path,omitempty" db:"source_file_path"`
	DifficultyLevel int        `json:"difficulty_level" db:"difficulty_level"`
	DurationMinutes *int       `json:"duration_minutes,omitempty" db:"duration_minutes"`
	MaxPoints       *float64   `json:"max_points,omitempty" db:"max_points"`
	IsTemplate      bool       `json:"is_template" db:"is_template"`
	ParentExamID    *uuid.UUID `json:"parent_exam_id,omitempty" db:"parent_exam_id"`
	Status          ExamStatus `json:"status" db:"status"`
	ExamDate        *time.Time `json:"exam_date,omitempty" db:"exam_date"`
	CreatedAt       time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt       time.Time  `json:"updated_at" db:"updated_at"`

	// Computed/joined fields
	ClassName   string `json:"class_name,omitempty"`
	SubjectName string `json:"subject_name,omitempty"`
}

// ExamResult represents a student's exam result
type ExamResult struct {
	ID                uuid.UUID  `json:"id" db:"id"`
	ExamID            uuid.UUID  `json:"exam_id" db:"exam_id"`
	StudentID         uuid.UUID  `json:"student_id" db:"student_id"`
	PointsAchieved    *float64   `json:"points_achieved,omitempty" db:"points_achieved"`
	Grade             *float64   `json:"grade,omitempty" db:"grade"`
	Percentage        *float64   `json:"percentage,omitempty" db:"percentage"`
	Notes             string     `json:"notes,omitempty" db:"notes"`
	IsAbsent          bool       `json:"is_absent" db:"is_absent"`
	NeedsRewrite      bool       `json:"needs_rewrite" db:"needs_rewrite"`
	ApprovedByTeacher bool       `json:"approved_by_teacher" db:"approved_by_teacher"`
	ApprovedAt        *time.Time `json:"approved_at,omitempty" db:"approved_at"`
	CreatedAt         time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt         time.Time  `json:"updated_at" db:"updated_at"`

	// Joined fields
	StudentName string `json:"student_name,omitempty"`
}

// GradeOverview represents aggregated grades for a student
type GradeOverview 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"`
	SchoolYearID      uuid.UUID  `json:"school_year_id" db:"school_year_id"`
	Semester          int        `json:"semester" db:"semester"`
	WrittenGradeAvg   *float64   `json:"written_grade_avg,omitempty" db:"written_grade_avg"`
	WrittenGradeCount int        `json:"written_grade_count" db:"written_grade_count"`
	OralGrade         *float64   `json:"oral_grade,omitempty" db:"oral_grade"`
	OralNotes         string     `json:"oral_notes,omitempty" db:"oral_notes"`
	FinalGrade        *float64   `json:"final_grade,omitempty" db:"final_grade"`
	FinalGradeLocked  bool       `json:"final_grade_locked" db:"final_grade_locked"`
	WrittenWeight     int        `json:"written_weight" db:"written_weight"`
	OralWeight        int        `json:"oral_weight" db:"oral_weight"`
	CreatedAt         time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt         time.Time  `json:"updated_at" db:"updated_at"`

	// Joined fields
	StudentName string `json:"student_name,omitempty"`
	SubjectName string `json:"subject_name,omitempty"`
}

// AttendanceStatus represents attendance status
type AttendanceStatus string

const (
	AttendancePresent         AttendanceStatus = "present"
	AttendanceAbsentExcused   AttendanceStatus = "absent_excused"
	AttendanceAbsentUnexcused AttendanceStatus = "absent_unexcused"
	AttendanceLate            AttendanceStatus = "late"
)

// Attendance represents a student's attendance record
type Attendance struct {
	ID        uuid.UUID        `json:"id" db:"id"`
	StudentID uuid.UUID        `json:"student_id" db:"student_id"`
	Date      time.Time        `json:"date" db:"date"`
	Status    AttendanceStatus `json:"status" db:"status"`
	Periods   int              `json:"periods" db:"periods"`
	Reason    string           `json:"reason,omitempty" db:"reason"`
	CreatedAt time.Time        `json:"created_at" db:"created_at"`

	// Joined fields
	StudentName string `json:"student_name,omitempty"`
}

// GradebookEntryType represents types of gradebook entries
type GradebookEntryType string

const (
	EntryTypeNote     GradebookEntryType = "note"
	EntryTypeWarning  GradebookEntryType = "warning"
	EntryTypePraise   GradebookEntryType = "praise"
	EntryTypeIncident GradebookEntryType = "incident"
	EntryTypeHomework GradebookEntryType = "homework"
)

// GradebookEntry represents a gradebook entry
type GradebookEntry struct {
	ID                 uuid.UUID          `json:"id" db:"id"`
	ClassID            uuid.UUID          `json:"class_id" db:"class_id"`
	StudentID          *uuid.UUID         `json:"student_id,omitempty" db:"student_id"`
	Date               time.Time          `json:"date" db:"date"`
	EntryType          GradebookEntryType `json:"entry_type" db:"entry_type"`
	Content            string             `json:"content" db:"content"`
	IsVisibleToParents bool               `json:"is_visible_to_parents" db:"is_visible_to_parents"`
	CreatedAt          time.Time          `json:"created_at" db:"created_at"`

	// Joined fields
	StudentName string `json:"student_name,omitempty"`
}

// CertificateStatus represents certificate status
type CertificateStatus string

const (
	CertificateStatusDraft   CertificateStatus = "draft"
	CertificateStatusFinal   CertificateStatus = "final"
	CertificateStatusPrinted CertificateStatus = "printed"
)

// CertificateType represents types of certificates
type CertificateType string

const (
	CertificateTypeHalbjahr  CertificateType = "halbjahr"
	CertificateTypeJahres    CertificateType = "jahres"
	CertificateTypeAbschluss CertificateType = "abschluss"
)

// Certificate represents a student certificate
type Certificate struct {
	ID                    uuid.UUID         `json:"id" db:"id"`
	StudentID             uuid.UUID         `json:"student_id" db:"student_id"`
	SchoolYearID          uuid.UUID         `json:"school_year_id" db:"school_year_id"`
	Semester              int               `json:"semester" db:"semester"`
	CertificateType       CertificateType   `json:"certificate_type" db:"certificate_type"`
	TemplateName          string            `json:"template_name,omitempty" db:"template_name"`
	GradesJSON            map[string]any    `json:"grades_json,omitempty" db:"grades_json"`
	Remarks               string            `json:"remarks,omitempty" db:"remarks"`
	AbsenceDays           int               `json:"absence_days" db:"absence_days"`
	AbsenceDaysUnexcused  int               `json:"absence_days_unexcused" db:"absence_days_unexcused"`
	GeneratedPDFPath      string            `json:"generated_pdf_path,omitempty" db:"generated_pdf_path"`
	Status                CertificateStatus `json:"status" db:"status"`
	CreatedAt             time.Time         `json:"created_at" db:"created_at"`
	UpdatedAt             time.Time         `json:"updated_at" db:"updated_at"`

	// Joined fields
	StudentName string `json:"student_name,omitempty"`
	ClassName   string `json:"class_name,omitempty"`
}

// Request/Response DTOs

// CreateSchoolYearRequest represents a request to create a school year
type CreateSchoolYearRequest struct {
	Name      string `json:"name" binding:"required"`
	StartDate string `json:"start_date" binding:"required"`
	EndDate   string `json:"end_date" binding:"required"`
	IsCurrent bool   `json:"is_current"`
}

// CreateClassRequest represents a request to create a class
type CreateClassRequest struct {
	SchoolYearID string `json:"school_year_id"`
	Name         string `json:"name" binding:"required"`
	GradeLevel   int    `json:"grade_level" binding:"required,min=1,max=13"`
	SchoolType   string `json:"school_type"`
	FederalState string `json:"federal_state"`
}

// CreateStudentRequest represents a request to create a student
type CreateStudentRequest struct {
	FirstName     string `json:"first_name" binding:"required"`
	LastName      string `json:"last_name" binding:"required"`
	BirthDate     string `json:"birth_date"`
	StudentNumber string `json:"student_number"`
	Notes         string `json:"notes"`
}

// CreateSubjectRequest represents a request to create a subject
type CreateSubjectRequest struct {
	Name          string `json:"name" binding:"required"`
	ShortName     string `json:"short_name"`
	IsMainSubject bool   `json:"is_main_subject"`
}

// CreateExamRequest represents a request to create an exam
type CreateExamRequest struct {
	ClassID         string   `json:"class_id"`
	SubjectID       string   `json:"subject_id"`
	Title           string   `json:"title" binding:"required"`
	ExamType        ExamType `json:"exam_type" binding:"required"`
	Topic           string   `json:"topic"`
	Content         string   `json:"content"`
	DifficultyLevel int      `json:"difficulty_level"`
	DurationMinutes int      `json:"duration_minutes"`
	MaxPoints       float64  `json:"max_points"`
	ExamDate        string   `json:"exam_date"`
}

// UpdateExamResultRequest represents a request to update exam results
type UpdateExamResultRequest struct {
	StudentID      string   `json:"student_id" binding:"required"`
	PointsAchieved *float64 `json:"points_achieved"`
	Grade          *float64 `json:"grade"`
	Notes          string   `json:"notes"`
	IsAbsent       bool     `json:"is_absent"`
	NeedsRewrite   bool     `json:"needs_rewrite"`
}

// UpdateOralGradeRequest represents a request to update oral grades
type UpdateOralGradeRequest struct {
	OralGrade float64 `json:"oral_grade" binding:"required,min=1,max=6"`
	OralNotes string  `json:"oral_notes"`
}

// CreateAttendanceRequest represents a request to create attendance
type CreateAttendanceRequest struct {
	StudentID string           `json:"student_id" binding:"required"`
	Date      string           `json:"date" binding:"required"`
	Status    AttendanceStatus `json:"status" binding:"required"`
	Periods   int              `json:"periods"`
	Reason    string           `json:"reason"`
}

// CreateGradebookEntryRequest represents a request to create a gradebook entry
type CreateGradebookEntryRequest struct {
	ClassID            string             `json:"class_id" binding:"required"`
	StudentID          string             `json:"student_id"`
	Date               string             `json:"date" binding:"required"`
	EntryType          GradebookEntryType `json:"entry_type" binding:"required"`
	Content            string             `json:"content" binding:"required"`
	IsVisibleToParents bool               `json:"is_visible_to_parents"`
}

// GenerateCertificateRequest represents a request to generate a certificate
type GenerateCertificateRequest struct {
	StudentID       string          `json:"student_id" binding:"required"`
	SchoolYearID    string          `json:"school_year_id" binding:"required"`
	Semester        int             `json:"semester" binding:"required,min=1,max=2"`
	CertificateType CertificateType `json:"certificate_type" binding:"required"`
	TemplateName    string          `json:"template_name"`
	Remarks         string          `json:"remarks"`
}

// GenerateExamVariantRequest represents a request to generate an exam variant
type GenerateExamVariantRequest struct {
	VariationType string `json:"variation_type" binding:"required"` // "rewrite", "alternative", "similar"
}
