package wecom

import (
	"context"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
)

// SceneRepository 持久化企业微信审批业务场景当前配置。
type SceneRepository struct {
	db *gorm.DB
}

// NewSceneRepository 创建企业微信审批场景 Repository。
func NewSceneRepository(db *gorm.DB) *SceneRepository {
	return &SceneRepository{db: db}
}

// FindForUpdate 在事务内锁定指定业务场景。
func (r *SceneRepository) FindForUpdate(ctx context.Context, tx *gorm.DB, businessType string) (*model.WeComApprovalScene, error) {
	var scene model.WeComApprovalScene
	err := tx.WithContext(ctx).Clauses(clause.Locking{Strength: "UPDATE"}).Where("business_type = ?", businessType).First(&scene).Error
	if err == gorm.ErrRecordNotFound {
		return nil, nil
	}
	if err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询企业微信审批场景失败")
	}
	return &scene, nil
}

// Create 创建企业微信审批场景配置。
func (r *SceneRepository) Create(ctx context.Context, tx *gorm.DB, scene *model.WeComApprovalScene) error {
	if err := tx.WithContext(ctx).Create(scene).Error; err != nil {
		return errors.Wrap(errors.CodeDatabaseError, err, "创建企业微信审批场景失败")
	}
	return nil
}

// Update 更新企业微信审批场景当前配置。
func (r *SceneRepository) Update(ctx context.Context, tx *gorm.DB, scene *model.WeComApprovalScene) error {
	if err := tx.WithContext(ctx).Model(&model.WeComApprovalScene{}).Where("id = ?", scene.ID).Updates(map[string]any{
		"application_id": scene.ApplicationID, "template_id": scene.TemplateID, "template_name": scene.TemplateName,
		"control_mapping": scene.ControlMapping, "template_snapshot": scene.TemplateSnapshot,
		"template_fingerprint": scene.TemplateFingerprint,
		"status":               scene.Status, "last_verified_at": scene.LastVerifiedAt,
		"updated_by": scene.UpdatedBy, "updated_at": scene.UpdatedAt,
	}).Error; err != nil {
		return errors.Wrap(errors.CodeDatabaseError, err, "更新企业微信审批场景失败")
	}
	return nil
}

// List 分页查询企业微信审批场景配置。
func (r *SceneRepository) List(ctx context.Context, page, pageSize int) ([]model.WeComApprovalScene, int64, error) {
	query := r.db.WithContext(ctx).Model(&model.WeComApprovalScene{})
	var total int64
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, errors.Wrap(errors.CodeDatabaseError, err, "统计企业微信审批场景失败")
	}
	var scenes []model.WeComApprovalScene
	if err := query.Order("business_type ASC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&scenes).Error; err != nil {
		return nil, 0, errors.Wrap(errors.CodeDatabaseError, err, "查询企业微信审批场景失败")
	}
	return scenes, total, nil
}

// GetEnabled 查询指定业务类型当前启用的企微审批场景。
func (r *SceneRepository) GetEnabled(ctx context.Context, businessType string) (*model.WeComApprovalScene, error) {
	var scene model.WeComApprovalScene
	if err := r.db.WithContext(ctx).Where("business_type = ? AND status = ?", businessType, constants.StatusEnabled).First(&scene).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeServiceUnavailable, "企业微信审批场景未配置或已禁用")
		}
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询企业微信审批场景失败")
	}
	return &scene, nil
}
