package services

import (
	"context"
	"time"

	"github.com/breakpilot/school-service/internal/models"
	"github.com/google/uuid"
	"github.com/jackc/pgx/v5/pgxpool"
)

// ClassService handles class-related operations
type ClassService struct {
	db *pgxpool.Pool
}

// NewClassService creates a new ClassService
func NewClassService(db *pgxpool.Pool) *ClassService {
	return &ClassService{db: db}
}

// School Year Operations

// CreateSchoolYear creates a new school year
func (s *ClassService) CreateSchoolYear(ctx context.Context, teacherID string, req *models.CreateSchoolYearRequest) (*models.SchoolYear, error) {
	startDate, _ := time.Parse("2006-01-02", req.StartDate)
	endDate, _ := time.Parse("2006-01-02", req.EndDate)

	// If this is current, unset other current years for this teacher
	if req.IsCurrent {
		s.db.Exec(ctx, `UPDATE school_years SET is_current = false WHERE teacher_id = $1`, teacherID)
	}

	var year models.SchoolYear
	err := s.db.QueryRow(ctx, `
		INSERT INTO school_years (teacher_id, name, start_date, end_date, is_current)
		VALUES ($1, $2, $3, $4, $5)
		RETURNING id, name, start_date, end_date, is_current, teacher_id, created_at
	`, teacherID, req.Name, startDate, endDate, req.IsCurrent).Scan(
		&year.ID, &year.Name, &year.StartDate, &year.EndDate, &year.IsCurrent, &year.TeacherID, &year.CreatedAt,
	)
	return &year, err
}

// GetSchoolYears returns all school years for a teacher
func (s *ClassService) GetSchoolYears(ctx context.Context, teacherID string) ([]models.SchoolYear, error) {
	rows, err := s.db.Query(ctx, `
		SELECT id, name, start_date, end_date, is_current, teacher_id, created_at
		FROM school_years
		WHERE teacher_id = $1
		ORDER BY start_date DESC
	`, teacherID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var years []models.SchoolYear
	for rows.Next() {
		var y models.SchoolYear
		if err := rows.Scan(&y.ID, &y.Name, &y.StartDate, &y.EndDate, &y.IsCurrent, &y.TeacherID, &y.CreatedAt); err != nil {
			return nil, err
		}
		years = append(years, y)
	}
	return years, nil
}

// Class Operations

// CreateClass creates a new class
func (s *ClassService) CreateClass(ctx context.Context, teacherID string, req *models.CreateClassRequest) (*models.Class, error) {
	var schoolYearID *uuid.UUID
	if req.SchoolYearID != "" {
		id, _ := uuid.Parse(req.SchoolYearID)
		schoolYearID = &id
	}

	var class models.Class
	err := s.db.QueryRow(ctx, `
		INSERT INTO classes (teacher_id, school_year_id, name, grade_level, school_type, federal_state)
		VALUES ($1, $2, $3, $4, $5, $6)
		RETURNING id, teacher_id, school_year_id, name, grade_level, school_type, federal_state, created_at
	`, teacherID, schoolYearID, req.Name, req.GradeLevel, req.SchoolType, req.FederalState).Scan(
		&class.ID, &class.TeacherID, &class.SchoolYearID, &class.Name, &class.GradeLevel, &class.SchoolType, &class.FederalState, &class.CreatedAt,
	)
	return &class, err
}

// GetClasses returns all classes for a teacher
func (s *ClassService) GetClasses(ctx context.Context, teacherID string) ([]models.Class, error) {
	rows, err := s.db.Query(ctx, `
		SELECT c.id, c.teacher_id, c.school_year_id, c.name, c.grade_level, c.school_type, c.federal_state, c.created_at,
		       COALESCE((SELECT COUNT(*) FROM students WHERE class_id = c.id), 0) as student_count
		FROM classes c
		WHERE c.teacher_id = $1
		ORDER BY c.grade_level, c.name
	`, teacherID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var classes []models.Class
	for rows.Next() {
		var c models.Class
		if err := rows.Scan(&c.ID, &c.TeacherID, &c.SchoolYearID, &c.Name, &c.GradeLevel, &c.SchoolType, &c.FederalState, &c.CreatedAt, &c.StudentCount); err != nil {
			return nil, err
		}
		classes = append(classes, c)
	}
	return classes, nil
}

// GetClass returns a single class
func (s *ClassService) GetClass(ctx context.Context, classID, teacherID string) (*models.Class, error) {
	var class models.Class
	err := s.db.QueryRow(ctx, `
		SELECT c.id, c.teacher_id, c.school_year_id, c.name, c.grade_level, c.school_type, c.federal_state, c.created_at,
		       COALESCE((SELECT COUNT(*) FROM students WHERE class_id = c.id), 0) as student_count
		FROM classes c
		WHERE c.id = $1 AND c.teacher_id = $2
	`, classID, teacherID).Scan(
		&class.ID, &class.TeacherID, &class.SchoolYearID, &class.Name, &class.GradeLevel, &class.SchoolType, &class.FederalState, &class.CreatedAt, &class.StudentCount,
	)
	return &class, err
}

// DeleteClass deletes a class
func (s *ClassService) DeleteClass(ctx context.Context, classID, teacherID string) error {
	_, err := s.db.Exec(ctx, `DELETE FROM classes WHERE id = $1 AND teacher_id = $2`, classID, teacherID)
	return err
}

// Student Operations

// CreateStudent creates a new student
func (s *ClassService) CreateStudent(ctx context.Context, classID string, req *models.CreateStudentRequest) (*models.Student, error) {
	var birthDate *time.Time
	if req.BirthDate != "" {
		t, _ := time.Parse("2006-01-02", req.BirthDate)
		birthDate = &t
	}

	// Get school_id from class
	var schoolID string
	err := s.db.QueryRow(ctx, `SELECT school_id FROM classes WHERE id = $1`, classID).Scan(&schoolID)
	if err != nil {
		return nil, err
	}

	var student models.Student
	err = s.db.QueryRow(ctx, `
		INSERT INTO students (school_id, class_id, first_name, last_name, date_of_birth, student_number)
		VALUES ($1, $2, $3, $4, $5, $6)
		RETURNING id, class_id, first_name, last_name, date_of_birth, student_number, created_at
	`, schoolID, classID, req.FirstName, req.LastName, birthDate, req.StudentNumber).Scan(
		&student.ID, &student.ClassID, &student.FirstName, &student.LastName, &student.BirthDate, &student.StudentNumber, &student.CreatedAt,
	)
	return &student, err
}

// GetStudents returns all students in a class
func (s *ClassService) GetStudents(ctx context.Context, classID string) ([]models.Student, error) {
	rows, err := s.db.Query(ctx, `
		SELECT id, class_id, first_name, last_name, date_of_birth, student_number, created_at
		FROM students
		WHERE class_id = $1
		ORDER BY last_name, first_name
	`, classID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var students []models.Student
	for rows.Next() {
		var st models.Student
		if err := rows.Scan(&st.ID, &st.ClassID, &st.FirstName, &st.LastName, &st.BirthDate, &st.StudentNumber, &st.CreatedAt); err != nil {
			return nil, err
		}
		students = append(students, st)
	}
	return students, nil
}

// DeleteStudent deletes a student
func (s *ClassService) DeleteStudent(ctx context.Context, studentID string) error {
	_, err := s.db.Exec(ctx, `DELETE FROM students WHERE id = $1`, studentID)
	return err
}

// Subject Operations

// CreateSubject creates a new subject
func (s *ClassService) CreateSubject(ctx context.Context, teacherID string, req *models.CreateSubjectRequest) (*models.Subject, error) {
	var subject models.Subject
	err := s.db.QueryRow(ctx, `
		INSERT INTO subjects (teacher_id, name, short_name, is_main_subject)
		VALUES ($1, $2, $3, $4)
		RETURNING id, teacher_id, name, short_name, is_main_subject, created_at
	`, teacherID, req.Name, req.ShortName, req.IsMainSubject).Scan(
		&subject.ID, &subject.TeacherID, &subject.Name, &subject.ShortName, &subject.IsMainSubject, &subject.CreatedAt,
	)
	return &subject, err
}

// GetSubjects returns all subjects for a teacher
func (s *ClassService) GetSubjects(ctx context.Context, teacherID string) ([]models.Subject, error) {
	rows, err := s.db.Query(ctx, `
		SELECT id, teacher_id, name, short_name, is_main_subject, created_at
		FROM subjects
		WHERE teacher_id = $1
		ORDER BY name
	`, teacherID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var subjects []models.Subject
	for rows.Next() {
		var subj models.Subject
		if err := rows.Scan(&subj.ID, &subj.TeacherID, &subj.Name, &subj.ShortName, &subj.IsMainSubject, &subj.CreatedAt); err != nil {
			return nil, err
		}
		subjects = append(subjects, subj)
	}
	return subjects, nil
}

// DeleteSubject deletes a subject
func (s *ClassService) DeleteSubject(ctx context.Context, subjectID, teacherID string) error {
	_, err := s.db.Exec(ctx, `DELETE FROM subjects WHERE id = $1 AND teacher_id = $2`, subjectID, teacherID)
	return err
}
