// Package pdks — Personel Devam Kontrol Sistemi.
//
// Devam kayitlari (giris/cikis, mola, mesai, izin) KENDI KURALLARI olan bir is
// alanidir: bir gunun calisma suresi giris/cikis ciftlerinden ve molalardan
// HESAPLANIR; gec kalma, mesai ve devamsizlik bunlardan turetilir. `biz` paketi
// genel kayit yonetimidir (musteri, fatura) ve bu hesaplari yapmaz — burada yapilir.
//
// Katman sorumluluklari:
//   - Service: devam is kurallari (giris/cikis eslesmesi, sure hesabi, mesai).
//   - Repository: kalicilik (Mongo uretimde, bellek ici testte).
//   - tools.go: modele acilan PDKS araclari.
package pdks

import (
	"errors"
	"time"
)

// Depo hatalari (API katmani bunlari HTTP durumuna cevirir).
var (
	ErrNotFound  = errors.New("pdks: kayit bulunamadi")
	ErrDuplicate = errors.New("pdks: kayit zaten var")
	ErrConflict  = errors.New("pdks: cakisan kayit var (aynı anda iki giris)")
	ErrForbidden = errors.New("pdks: bu islem icin yetkiniz yok")
	ErrInvalid   = errors.New("pdks: gecersiz veri")
)

// Department, organizasyon agacinin dugumudur (bolum).
//
// ParentID bossa kok bolumdur. Agac tek seviye olmak zorunda DEGILDIR:
// "Muhasebe -> Finans" gibi ic ice bolumler yaygindir. Dongusel referans (a->b->a)
// kurulmasi Service tarafindan engellenir.
type Department struct {
	ID          string    `bson:"_id" json:"id"`
	Name        string    `bson:"name" json:"name"`
	ParentID    string    `bson:"parentId,omitempty" json:"parentId,omitempty"`
	Code        string    `bson:"code,omitempty" json:"code,omitempty"`
	ManagerID   string    `bson:"managerId,omitempty" json:"managerId,omitempty"`
	WeeklyHours float64   `bson:"weeklyHours,omitempty" json:"weeklyHours,omitempty"`
	Active      bool      `bson:"active" json:"active"`
	CreatedAt   time.Time `bson:"createdAt" json:"createdAt"`
	UpdatedAt   time.Time `bson:"updatedAt" json:"updatedAt"`
}

func (d Department) Clone() Department { return d }

// Employee, PDKS'te takip edilen personeldir.
//
// UserID, sistem hesabina baglantisidir (bos olabilir: sistemde hesabi olmayan
// personel de takip edilebilir). Baglanti varsa otomatik giris/cikis bu alandan
// yapilir (AutoTrack).
type Employee struct {
	ID           string    `bson:"_id" json:"id"`
	UserID       string    `bson:"userId,omitempty" json:"userId,omitempty"`
	Name         string    `bson:"name" json:"name"`
	DepartmentID string    `bson:"departmentId,omitempty" json:"departmentId,omitempty"`
	Title        string    `bson:"title,omitempty" json:"title,omitempty"`
	Email        string    `bson:"email,omitempty" json:"email,omitempty"`
	Phone        string    `bson:"phone,omitempty" json:"phone,omitempty"`
	HireDate     string    `bson:"hireDate,omitempty" json:"hireDate,omitempty"`
	WeeklyHours  float64   `bson:"weeklyHours,omitempty" json:"weeklyHours,omitempty"`
	AnnualLeave  float64   `bson:"annualLeave,omitempty" json:"annualLeave,omitempty"`
	AutoTrack    bool      `bson:"autoTrack" json:"autoTrack"`
	Active       bool      `bson:"active" json:"active"`
	CreatedAt    time.Time `bson:"createdAt" json:"createdAt"`
	UpdatedAt    time.Time `bson:"updatedAt" json:"updatedAt"`
}

func (e Employee) Clone() Employee { return e }

// Shift, bir vardiyadir (calisma saat araligi).
//
// Molalar bu araligin ICINDE olmalidir; Service bunu dogrular. Gece vardiyasi
// icin End < Start olabilir (22:00 -> 06:00); capraz gece olarak yorumlanir.
type Shift struct {
	ID          string    `bson:"_id" json:"id"`
	Name        string    `bson:"name" json:"name"`
	Start       string    `bson:"start" json:"start"`
	End         string    `bson:"end" json:"end"`
	BreakMin    int       `bson:"breakMin,omitempty" json:"breakMin,omitempty"`
	WeeklyHours float64   `bson:"weeklyHours,omitempty" json:"weeklyHours,omitempty"`
	Days        []int     `bson:"days,omitempty" json:"days,omitempty"`
	Active      bool      `bson:"active" json:"active"`
	CreatedAt   time.Time `bson:"createdAt" json:"createdAt"`
	UpdatedAt   time.Time `bson:"updatedAt" json:"updatedAt"`
}

func (s Shift) Clone() Shift { return s }

// AttendanceType, bir devam olayinin turudur.
type AttendanceType string

const (
	AttendanceIn         AttendanceType = "in"
	AttendanceOut        AttendanceType = "out"
	AttendanceBreakStart AttendanceType = "break_start"
	AttendanceBreakEnd   AttendanceType = "break_end"
)

// Attendance, TEK bir devam olayidir (giris, cikis veya mola siniri).
//
// Neden OLAY modeli? Gercek hayatta gun icinde cok giris/cikis olabilir (ogle
// arasi, ikram, doktor). Olaylari SIRAYA yazip sureyi hesaplamak, tek "gunluk
// kayit" alani tutmaktan gercekcidir ve denetime izin verir (kayit sirasi, eksik
// cikis, unutulmus mola).
type Attendance struct {
	ID        string         `bson:"_id" json:"id"`
	EmpID     string         `bson:"empId" json:"empId"`
	Type      AttendanceType `bson:"type" json:"type"`
	At        time.Time      `bson:"at" json:"at"`
	DayOf     string         `bson:"dayOf" json:"dayOf"`
	Source    string         `bson:"source,omitempty" json:"source,omitempty"`
	Note      string         `bson:"note,omitempty" json:"note,omitempty"`
	CreatedAt time.Time      `bson:"createdAt" json:"createdAt"`
}

func (a Attendance) Clone() Attendance { return a }

// Kaynak sabitleri.
const (
	SourceManual = "manual"
	SourceAuto   = "auto"
	SourceImport = "import"
)

// Leave, bir izin kaydidir (yillik/rapor/mazeret/saglik ...).
type Leave struct {
	ID        string    `bson:"_id" json:"id"`
	EmpID     string    `bson:"empId" json:"empId"`
	Kind      string    `bson:"kind" json:"kind"`
	From      string    `bson:"from" json:"from"`
	To        string    `bson:"to" json:"to"`
	Days      float64   `bson:"days" json:"days"`
	Approved  bool      `bson:"approved" json:"approved"`
	Reason    string    `bson:"reason,omitempty" json:"reason,omitempty"`
	CreatedAt time.Time `bson:"createdAt" json:"createdAt"`
	UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
}

func (l Leave) Clone() Leave { return l }

// Izin turleri.
const (
	LeaveAnnual = "annual"
	LeaveReport = "report"
	LeaveSick   = "sick"
	LeaveUnpaid = "unpaid"
	LeaveOther  = "other"
)

// DailySummary, BIR GUNUN hesaplanmis sonucudur (raporun temel birimi).
//
// Bu bir KAYIT DEGIL hesaptir: olaylardan turetilir. Saklamak gerekmez; her
// raporda yeniden hesaplanir (boylece gecmise eklenen bir olay gecmis raporu da
// dogru gosterir — PDKS'ta yanlis hesap en pahali hatadir).
type DailySummary struct {
	EmpID       string `json:"empId"`
	DayOf       string `json:"dayOf"`
	FirstIn     string `json:"firstIn,omitempty"`
	LastOut     string `json:"lastOut,omitempty"`
	WorkMin     int    `json:"workMin"`
	BreakMin    int    `json:"breakMin"`
	Status      string `json:"status"`
	LateMin     int    `json:"lateMin"`
	EarlyMin    int    `json:"earlyMin"`
	OvertimeMin int    `json:"overtimeMin"`
	ShiftID     string `json:"shiftId,omitempty"`
	Note        string `json:"note,omitempty"`
}

// Gun sonu durum sabitleri.
const (
	StatusPresent    = "present"
	StatusAbsent     = "absent"
	StatusLeave      = "leave"
	StatusOpen       = "open"
	StatusIncomplete = "incomplete"
)

// DayOf, t'un ait oldugu is gunu anahtarini dondurur.
func DayOf(t time.Time) string { return t.Format("2006-01-02") }

// ParseDayOf, "YYYY-MM-DD" anahtarini cozumler.
func ParseDayOf(s string) (time.Time, error) {
	return time.ParseInLocation("2006-01-02", s, time.Local)
}
