package models

import (
	"context"
	"errors"

	"github.com/timetracker/backend/internal/db"
	"github.com/timetracker/backend/internal/types"
	"gorm.io/gorm"
)

// Activity represents an activity in the system
type Activity struct {
	EntityBase
	Name        string  `gorm:"column:name"`
	BillingRate float64 `gorm:"column:billing_rate"`
}

// TableName specifies the table name for GORM
func (Activity) TableName() string {
	return "activities"
}

// ActivityUpdate contains the updatable fields of an Activity
type ActivityUpdate struct {
	ID          types.ULID `gorm:"-"` // Use "-" to indicate that this field should be ignored
	Name        *string    `gorm:"column:name"`
	BillingRate *float64   `gorm:"column:billing_rate"`
}

// ActivityCreate contains the fields for creating a new Activity
type ActivityCreate struct {
	Name        string  `gorm:"column:name"`
	BillingRate float64 `gorm:"column:billing_rate"`
}

// GetActivityByID finds an Activity by its ID
func GetActivityByID(ctx context.Context, id types.ULID) (*Activity, error) {
	var activity Activity
	result := db.GetEngine(ctx).Where("id = ?", id).First(&activity)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, result.Error
	}
	return &activity, nil
}

// GetAllActivities returns all Activities
func GetAllActivities(ctx context.Context) ([]Activity, error) {
	var activities []Activity
	result := db.GetEngine(ctx).Find(&activities)
	if result.Error != nil {
		return nil, result.Error
	}
	return activities, nil
}

// CreateActivity creates a new Activity
func CreateActivity(ctx context.Context, create ActivityCreate) (*Activity, error) {
	activity := Activity{
		Name:        create.Name,
		BillingRate: create.BillingRate,
	}

	result := db.GetEngine(ctx).Create(&activity)
	if result.Error != nil {
		return nil, result.Error
	}
	return &activity, nil
}

// UpdateActivity updates an existing Activity
func UpdateActivity(ctx context.Context, update ActivityUpdate) (*Activity, error) {
	activity, err := GetActivityByID(ctx, update.ID)
	if err != nil {
		return nil, err
	}
	if activity == nil {
		return nil, errors.New("activity not found")
	}

	// Use generic update function
	if err := UpdateModel(ctx, activity, update); err != nil {
		return nil, err
	}

	// Load updated data from the database
	return GetActivityByID(ctx, update.ID)
}

// DeleteActivity deletes an Activity by its ID
func DeleteActivity(ctx context.Context, id types.ULID) error {
	result := db.GetEngine(ctx).Delete(&Activity{}, id)
	return result.Error
}
