/*
 * Copyright 2021 PingCAP, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package model

import (
	"context"
	"time"

	"gorm.io/gorm"
)

const (
	savepointTableName = "savepoint"
)

type Savepoint struct {
	ID        uint      `gorm:"column:id;type:int(11) unsigned NOT NULL AUTO_INCREMENT;PRIMARY_KEY"`
	CreatedAt time.Time `gorm:"column:created_at;<-:false;type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP"`
	UpdatedAt time.Time `gorm:"column:updated_at;<-:false;type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"`
	JobRef    uint      `gorm:"column:job_ref;type:int(11);NOT NULL"`
	Job       Job       `gorm:"foreignKey:JobRef;reference:ID;constraint:OnDelete:CASCADE"`
	Path      string    `gorm:"column:path;type:text;DEFAULT:NULL"`
}

func (s *Savepoint) TableName() string {
	return savepointTableName
}

type SavepointDao interface {
	Insert(ctx context.Context, savepoint *Savepoint) error
	List(ctx context.Context, jobID uint) ([]Savepoint, error)
	// Find(ctx context.Context, userID string, jobID string) (*Job, bool, error)
}

type savepointDao struct {
	db *gorm.DB
}

func NewSavepointDao(options ...DaoOption) (SavepointDao, error) {
	dao := new(savepointDao)
	for _, option := range options {
		if err := option(dao); err != nil {
			return nil, err
		}
	}
	return dao, nil
}

func (dao *savepointDao) SetDB(db *gorm.DB) {
	dao.db = db
}

func (dao *savepointDao) Insert(ctx context.Context, savepoint *Savepoint) error {
	return dao.db.WithContext(ctx).Table(savepoint.TableName()).Create(savepoint).Error
}

func (dao *savepointDao) List(ctx context.Context, jobID uint) ([]Savepoint, error) {
	savepoints := new([]Savepoint)

	if err := dao.db.Where("job_ref = ?", jobID).Order("created_at desc").Find(savepoints).Error; err != nil {
		return *savepoints, err
	}

	return *savepoints, nil
}
