package repository

import (
	"time"

	"gorm.io/gorm"

	"nex/backend/internal/config"
	"nex/backend/internal/domain"
	appErrors "nex/backend/pkg/errors"
)

type modelRepository struct {
	db *gorm.DB
}

func NewModelRepository(db *gorm.DB) ModelRepository {
	return &modelRepository{db: db}
}

func (r *modelRepository) Create(model *domain.Model) error {
	m := toConfigModel(model)
	m.CreatedAt = time.Now()
	return r.db.Create(&m).Error
}

func (r *modelRepository) GetByID(id string) (*domain.Model, error) {
	var m config.Model
	err := r.db.First(&m, "id = ?", id).Error
	if err != nil {
		return nil, err
	}
	d := toDomainModel(&m)
	return &d, nil
}

func (r *modelRepository) List(providerID string) ([]domain.Model, error) {
	var models []config.Model
	var err error
	if providerID != "" {
		err = r.db.Where("provider_id = ?", providerID).Find(&models).Error
	} else {
		err = r.db.Find(&models).Error
	}
	if err != nil {
		return nil, err
	}
	result := make([]domain.Model, len(models))
	for i := range models {
		result[i] = toDomainModel(&models[i])
	}
	return result, nil
}

func (r *modelRepository) FindByProviderAndModelName(providerID, modelName string) (*domain.Model, error) {
	var m config.Model
	err := r.db.Where("provider_id = ? AND model_name = ?", providerID, modelName).First(&m).Error
	if err != nil {
		return nil, err
	}
	d := toDomainModel(&m)
	return &d, nil
}

func (r *modelRepository) ListEnabled() ([]domain.Model, error) {
	var models []config.Model
	err := r.db.Joins("JOIN providers ON providers.id = models.provider_id").
		Where("models.enabled = ? AND providers.enabled = ?", true, true).
		Find(&models).Error
	if err != nil {
		return nil, err
	}
	result := make([]domain.Model, len(models))
	for i := range models {
		result[i] = toDomainModel(&models[i])
	}
	return result, nil
}

func (r *modelRepository) Update(id string, updates map[string]interface{}) error {
	result := r.db.Model(&config.Model{}).Where("id = ?", id).Updates(updates)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return appErrors.ErrModelNotFound
	}
	return nil
}

func (r *modelRepository) Delete(id string) error {
	result := r.db.Delete(&config.Model{}, "id = ?", id)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return appErrors.ErrModelNotFound
	}
	return nil
}

func toDomainModel(m *config.Model) domain.Model {
	return domain.Model{
		ID:         m.ID,
		ProviderID: m.ProviderID,
		ModelName:  m.ModelName,
		Enabled:    m.Enabled,
		CreatedAt:  m.CreatedAt,
	}
}

func toConfigModel(m *domain.Model) config.Model {
	return config.Model{
		ID:         m.ID,
		ProviderID: m.ProviderID,
		ModelName:  m.ModelName,
		Enabled:    m.Enabled,
	}
}
