package mysql

import (
	"context"

	"gorm.io/gorm"

	"github.com/pingcap-inc/pchub/internal/pkg/code"
	v1 "github.com/pingcap-inc/pchub/model/v1"
	"github.com/pingcap-inc/pchub/pkg/errors"
)

type approval struct {
	db *gorm.DB
}

func newApproval(ds *datastore) *approval {
	return &approval{db: ds.db}
}

func (u *approval) Create(ctx context.Context, approval *v1.Approval) (*v1.Approval, error) {
	return approval, u.db.Create(approval).Error
}

func (u *approval) Update(ctx context.Context, approval *v1.Approval) error {
	return u.db.Save(approval).Error
}

func (u *approval) Get(ctx context.Context, approval *v1.Approval) (*v1.Approval, error) {
	approvalRes := v1.Approval{}
	model := u.db.Where("1 = 1")
	if approval.ApprovalType != 0 {
		model = model.Where("approvalType = ?", approval.ApprovalType)
	}
	if approval.InstanceCode != "" {
		model = model.Where("instanceCode = ?", approval.InstanceCode)
	}
	if approval.Luid != "" {
		model = model.Where("luid = ?", approval.Luid)
	}
	err := model.First(&approvalRes).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.WithCode(code.ErrApprovalNotFound, "gorm.ErrRecordNotFound: %v", err.Error())
		}

		return nil, errors.WithCode(code.ErrDatabase, "gorm.ErrRecordNotFound: %v", err.Error())
	}

	return &approvalRes, nil
}

func (u *approval) GetsByPage(ctx context.Context, params map[string]string) (*v1.Page, error) {
	page := v1.NewPage(params["size"], params["current"], v1.BuildDesc("createdAt"))

	var approvalRes []v1.Approval
	model := u.db.Order("createdAt desc")
	if value, ok := params["luid"]; ok && value != "" {
		model.Where("luid = ?", value)
	}
	if value, ok := params["approvalType"]; ok && value != "" {
		model.Where("approvalType = ?", value)
	}

	countModel := model
	var total int64
	if err := countModel.Model(v1.Approval{}).Count(&total).Error; err != nil {
		return nil, errors.WithCode(code.ErrDatabase, "gorm count err: %v", err.Error())
	}
	page.SetTotal(total)
	offset := (page.GetCurrent() - 1) * page.GetSize()
	err := model.Offset(int(offset)).Limit(int(page.GetSize())).Find(&approvalRes).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.WithCode(code.ErrApprovalNotFound, "gorm.ErrRecordNotFound: %v", err.Error())
		}

		return nil, errors.WithCode(code.ErrDatabase, "gorm.ErrRecordNotFound: %v", err.Error())
	}
	page.SetRecords(approvalRes)

	return page, nil
}
