package handlers

import (
	"errors"
	"net/http"
	"time"

	"nitipabsen/backend/config"
	authmiddleware "nitipabsen/backend/middleware"
	"nitipabsen/backend/models"

	"gorm.io/gorm"
)

type AttendanceHandler struct{}
type attendanceRequest struct {
	Date   string `json:"date"`
	Status string `json:"status"`
}

func (AttendanceHandler) List(w http.ResponseWriter, r *http.Request) {
	userID, _ := authmiddleware.UserID(r.Context())
	var rows []models.Attendance
	config.DB.Where("user_id = ?", userID).Order("date asc").Find(&rows)
	writeJSON(w, 200, rows)
}
func (AttendanceHandler) Upsert(w http.ResponseWriter, r *http.Request) {
	userID, _ := authmiddleware.UserID(r.Context())
	var input attendanceRequest
	if !decode(r, &input) || input.Status == "" {
		writeError(w, 400, "date and status are required")
		return
	}
	date, err := time.Parse("2006-01-02", input.Date)
	if err != nil || !validStatus(input.Status) {
		writeError(w, 400, "invalid date or status")
		return
	}
	row := models.Attendance{UserID: userID, Date: date, Status: input.Status}
	var existing models.Attendance
	result := config.DB.Where("user_id = ? AND date = ?", userID, input.Date).First(&existing)
	if result.Error == nil {
		existing.Status = input.Status
		if err := config.DB.Model(&existing).Update("status", input.Status).Error; err != nil {
			writeError(w, 500, "could not save attendance")
			return
		}
		row = existing
	} else if errors.Is(result.Error, gorm.ErrRecordNotFound) {
		if err := config.DB.Create(&row).Error; err != nil {
			writeError(w, 500, "could not save attendance")
			return
		}
	} else {
		writeError(w, 500, "could not save attendance")
		return
	}
	writeJSON(w, 200, row)
}

func (AttendanceHandler) Delete(w http.ResponseWriter, r *http.Request) {
	userID, _ := authmiddleware.UserID(r.Context())
	date, err := time.Parse("2006-01-02", r.URL.Query().Get("date"))
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid date")
		return
	}
	if result := config.DB.Where("user_id = ? AND date = ?", userID, date).Delete(&models.Attendance{}); result.Error != nil {
		writeError(w, http.StatusInternalServerError, "could not delete attendance")
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

func validStatus(status string) bool {
	return status == "present" || status == "absent" || status == "leave"
}
