package repository

import (
	"context"

	"eslogad-be/internal/entities"

	"github.com/google/uuid"
	"gorm.io/gorm"
)

type LabelRepository struct{ db *gorm.DB }

func NewLabelRepository(db *gorm.DB) *LabelRepository { return &LabelRepository{db: db} }
func (r *LabelRepository) Create(ctx context.Context, e *entities.Label) error {
	return r.db.WithContext(ctx).Create(e).Error
}
func (r *LabelRepository) Update(ctx context.Context, e *entities.Label) error {
	return r.db.WithContext(ctx).Model(&entities.Label{}).Where("id = ?", e.ID).Updates(e).Error
}
func (r *LabelRepository) Delete(ctx context.Context, id uuid.UUID) error {
	return r.db.WithContext(ctx).Delete(&entities.Label{}, "id = ?", id).Error
}
func (r *LabelRepository) List(ctx context.Context) ([]entities.Label, error) {
	var list []entities.Label
	err := r.db.WithContext(ctx).Order("name ASC").Find(&list).Error
	return list, err
}
func (r *LabelRepository) Get(ctx context.Context, id uuid.UUID) (*entities.Label, error) {
	var e entities.Label
	if err := r.db.WithContext(ctx).First(&e, "id = ?", id).Error; err != nil {
		return nil, err
	}
	return &e, nil
}

type PriorityRepository struct{ db *gorm.DB }

func NewPriorityRepository(db *gorm.DB) *PriorityRepository { return &PriorityRepository{db: db} }
func (r *PriorityRepository) Create(ctx context.Context, e *entities.Priority) error {
	return r.db.WithContext(ctx).Create(e).Error
}
func (r *PriorityRepository) Update(ctx context.Context, e *entities.Priority) error {
	return r.db.WithContext(ctx).Model(&entities.Priority{}).Where("id = ?", e.ID).Updates(e).Error
}
func (r *PriorityRepository) Delete(ctx context.Context, id uuid.UUID) error {
	return r.db.WithContext(ctx).Delete(&entities.Priority{}, "id = ?", id).Error
}
func (r *PriorityRepository) List(ctx context.Context) ([]entities.Priority, error) {
	var list []entities.Priority
	err := r.db.WithContext(ctx).Order("level ASC").Find(&list).Error
	return list, err
}
func (r *PriorityRepository) Get(ctx context.Context, id uuid.UUID) (*entities.Priority, error) {
	var e entities.Priority
	if err := r.db.WithContext(ctx).First(&e, "id = ?", id).Error; err != nil {
		return nil, err
	}
	return &e, nil
}

type InstitutionRepository struct{ db *gorm.DB }

func NewInstitutionRepository(db *gorm.DB) *InstitutionRepository {
	return &InstitutionRepository{db: db}
}
func (r *InstitutionRepository) Create(ctx context.Context, e *entities.Institution) error {
	return r.db.WithContext(ctx).Create(e).Error
}
func (r *InstitutionRepository) Update(ctx context.Context, e *entities.Institution) error {
	return r.db.WithContext(ctx).Model(&entities.Institution{}).Where("id = ?", e.ID).Updates(e).Error
}
func (r *InstitutionRepository) Delete(ctx context.Context, id uuid.UUID) error {
	return r.db.WithContext(ctx).Delete(&entities.Institution{}, "id = ?", id).Error
}
func (r *InstitutionRepository) List(ctx context.Context) ([]entities.Institution, error) {
	var list []entities.Institution
	err := r.db.WithContext(ctx).Order("name ASC").Find(&list).Error
	return list, err
}
func (r *InstitutionRepository) Get(ctx context.Context, id uuid.UUID) (*entities.Institution, error) {
	var e entities.Institution
	if err := r.db.WithContext(ctx).First(&e, "id = ?", id).Error; err != nil {
		return nil, err
	}
	return &e, nil
}

type DispositionActionRepository struct{ db *gorm.DB }

func NewDispositionActionRepository(db *gorm.DB) *DispositionActionRepository {
	return &DispositionActionRepository{db: db}
}
func (r *DispositionActionRepository) Create(ctx context.Context, e *entities.DispositionAction) error {
	return r.db.WithContext(ctx).Create(e).Error
}
func (r *DispositionActionRepository) Update(ctx context.Context, e *entities.DispositionAction) error {
	return r.db.WithContext(ctx).Model(&entities.DispositionAction{}).Where("id = ?", e.ID).Updates(e).Error
}
func (r *DispositionActionRepository) Delete(ctx context.Context, id uuid.UUID) error {
	return r.db.WithContext(ctx).Delete(&entities.DispositionAction{}, "id = ?", id).Error
}
func (r *DispositionActionRepository) List(ctx context.Context) ([]entities.DispositionAction, error) {
	var list []entities.DispositionAction
	err := r.db.WithContext(ctx).Order("sort_order NULLS LAST, label ASC").Find(&list).Error
	return list, err
}
func (r *DispositionActionRepository) Get(ctx context.Context, id uuid.UUID) (*entities.DispositionAction, error) {
	var e entities.DispositionAction
	if err := r.db.WithContext(ctx).First(&e, "id = ?", id).Error; err != nil {
		return nil, err
	}
	return &e, nil
}

func (r *DispositionActionRepository) GetByIDs(ctx context.Context, ids []uuid.UUID) ([]entities.DispositionAction, error) {
	var actions []entities.DispositionAction
	if len(ids) == 0 {
		return actions, nil
	}
	if err := r.db.WithContext(ctx).Where("id IN ?", ids).Find(&actions).Error; err != nil {
		return nil, err
	}
	return actions, nil
}

type DepartmentRepository struct{ db *gorm.DB }

func NewDepartmentRepository(db *gorm.DB) *DepartmentRepository { return &DepartmentRepository{db: db} }

func (r *DepartmentRepository) GetByCode(ctx context.Context, code string) (*entities.Department, error) {
	db := DBFromContext(ctx, r.db)
	var dep entities.Department
	if err := db.WithContext(ctx).Where("code = ?", code).First(&dep).Error; err != nil {
		return nil, err
	}
	return &dep, nil
}

func (r *DepartmentRepository) Get(ctx context.Context, id uuid.UUID) (*entities.Department, error) {
	db := DBFromContext(ctx, r.db)
	var dep entities.Department
	if err := db.WithContext(ctx).First(&dep, "id = ?", id).Error; err != nil {
		return nil, err
	}
	return &dep, nil
}
