package repository

import (
	"errors"
	"netidhub-saas-be/app/database"
	"netidhub-saas-be/app/database/entity"

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

type clientApprovalSettingsRepository struct {
	DB  *database.Database
	Log zerolog.Logger
}

func NewClientApprovalSettingsRepository(db *database.Database, log zerolog.Logger) ClientApprovalSettingsRepository {
	return &clientApprovalSettingsRepository{
		DB:  db,
		Log: log,
	}
}

func (r *clientApprovalSettingsRepository) Create(clientId *uuid.UUID, settings *entity.ClientApprovalSettings) (*entity.ClientApprovalSettings, error) {
	settings.ClientId = *clientId
	if err := r.DB.DB.Create(settings).Error; err != nil {
		return nil, err
	}
	return settings, nil
}

func (r *clientApprovalSettingsRepository) FindOne(clientId *uuid.UUID) (*entity.ClientApprovalSettings, error) {
	var settings entity.ClientApprovalSettings
	err := r.DB.DB.Where("client_id = ?", clientId).First(&settings).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &settings, nil
}

func (r *clientApprovalSettingsRepository) Update(clientId *uuid.UUID, settings *entity.ClientApprovalSettings) (*entity.ClientApprovalSettings, error) {
	settings.ClientId = *clientId
	if err := r.DB.DB.Where("client_id = ?", clientId).Save(settings).Error; err != nil {
		return nil, err
	}
	return settings, nil
}

func (r *clientApprovalSettingsRepository) Delete(clientId *uuid.UUID) error {
	return r.DB.DB.Where("client_id = ?", clientId).Delete(&entity.ClientApprovalSettings{}).Error
}

func (r *clientApprovalSettingsRepository) FindByClientId(clientId uuid.UUID) (*entity.ClientApprovalSettings, error) {
	var settings entity.ClientApprovalSettings
	err := r.DB.DB.Where("client_id = ?", clientId).First(&settings).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &settings, nil
}

func (r *clientApprovalSettingsRepository) FindActiveSettings(clientId *uuid.UUID) (*entity.ClientApprovalSettings, error) {
	var settings entity.ClientApprovalSettings
	err := r.DB.DB.Where("client_id = ? AND is_active = ?", clientId, true).First(&settings).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &settings, nil
}

func (r *clientApprovalSettingsRepository) FindByWorkflowId(workflowId uint) ([]*entity.ClientApprovalSettings, error) {
	var settings []*entity.ClientApprovalSettings
	err := r.DB.DB.Where("default_workflow_id = ?", workflowId).Find(&settings).Error
	return settings, err
}

func (r *clientApprovalSettingsRepository) AddExemptUser(clientId *uuid.UUID, userId uint) error {
	return r.DB.DB.Model(&entity.ClientApprovalSettings{}).
		Where("client_id = ?", clientId).
		Update("approval_exempt_users", gorm.Expr("array_append(approval_exempt_users, ?)", userId)).Error
}

func (r *clientApprovalSettingsRepository) RemoveExemptUser(clientId *uuid.UUID, userId uint) error {
	return r.DB.DB.Model(&entity.ClientApprovalSettings{}).
		Where("client_id = ?", clientId).
		Update("approval_exempt_users", gorm.Expr("array_remove(approval_exempt_users, ?)", userId)).Error
}

func (r *clientApprovalSettingsRepository) AddExemptRole(clientId *uuid.UUID, roleId uint) error {
	return r.DB.DB.Model(&entity.ClientApprovalSettings{}).
		Where("client_id = ?", clientId).
		Update("approval_exempt_roles", gorm.Expr("array_append(approval_exempt_roles, ?)", roleId)).Error
}

func (r *clientApprovalSettingsRepository) RemoveExemptRole(clientId *uuid.UUID, roleId uint) error {
	return r.DB.DB.Model(&entity.ClientApprovalSettings{}).
		Where("client_id = ?", clientId).
		Update("approval_exempt_roles", gorm.Expr("array_remove(approval_exempt_roles, ?)", roleId)).Error
}

func (r *clientApprovalSettingsRepository) AddExemptCategory(clientId *uuid.UUID, categoryId uint) error {
	return r.DB.DB.Model(&entity.ClientApprovalSettings{}).
		Where("client_id = ?", clientId).
		Update("approval_exempt_categories", gorm.Expr("array_append(approval_exempt_categories, ?)", categoryId)).Error
}

func (r *clientApprovalSettingsRepository) RemoveExemptCategory(clientId *uuid.UUID, categoryId uint) error {
	return r.DB.DB.Model(&entity.ClientApprovalSettings{}).
		Where("client_id = ?", clientId).
		Update("approval_exempt_categories", gorm.Expr("array_remove(approval_exempt_categories, ?)", categoryId)).Error
}

func (r *clientApprovalSettingsRepository) BulkUpdateExemptUsers(clientId *uuid.UUID, userIds []uint) error {
	return r.DB.DB.Model(&entity.ClientApprovalSettings{}).
		Where("client_id = ?", clientId).
		Update("approval_exempt_users", userIds).Error
}

func (r *clientApprovalSettingsRepository) BulkUpdateExemptRoles(clientId *uuid.UUID, roleIds []uint) error {
	return r.DB.DB.Model(&entity.ClientApprovalSettings{}).
		Where("client_id = ?", clientId).
		Update("approval_exempt_roles", roleIds).Error
}

func (r *clientApprovalSettingsRepository) BulkUpdateExemptCategories(clientId *uuid.UUID, categoryIds []uint) error {
	return r.DB.DB.Model(&entity.ClientApprovalSettings{}).
		Where("client_id = ?", clientId).
		Update("approval_exempt_categories", categoryIds).Error
}
