package repository

import (
	"dataapps/commons/database"
	entity "dataapps/internal/entity/sqleditor"
	"fmt"
	"strconv"

	"github.com/pkg/errors"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

// @Time    : 2022/11/14 11:30 AM
// @Author  : lvhongmeng

const (
	LIMIT = 500
)

func UpdateDataAppSettings(param entity.DataAppSettings) error {
	err := database.DBConn.DB.Table("dataapp_settings").Clauses(clause.OnConflict{
		Columns:   []clause.Column{{Name: "dataapp_id"}},
		DoUpdates: clause.AssignmentColumns([]string{"basic_settings", "updated_by"}),
	}).Create(&param).Error
	if err != nil {
		return err
	}
	return nil

}

func ShowDataAppSettings(projectId uint64) (*entity.DataAppSettings, error) {
	res := entity.DataAppSettings{}
	err := database.DBConn.DB.Table("dataapp_settings").Where("project_id=?", projectId).Find(&res).Limit(1).Error
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("ShowDataAppSettings: %+v failed", projectId))
	}
	return &res, nil
}

func UpdateSettings(param entity.SQLEditorSettings) error {
	res := entity.SQLEditorSettings{}
	err := database.DBConn.DB.Table("sql_editor_settings").Where("cluster_id=? and created_by=?", param.ClusterID, param.CreatedBy).First(&res).Error
	if err != nil {
		return err
	}
	if len(res.BasicSettings) == 0 {
		if err = database.DBConn.DB.Table("sql_editor_settings").Save(&param).Error; err != nil {
			return errors.Wrap(err, fmt.Sprintf("create settings: %+v failed", param))
		}
	} else {
		if err = database.DBConn.DB.Table("sql_editor_settings").Where("cluster_id=? and created_by=?", param.ClusterID, param.CreatedBy).Update("basic_settings", param.BasicSettings).Error; err != nil {
			return errors.Wrap(err, fmt.Sprintf("update settings: %+v failed", param))
		}
	}
	return nil
}

func ShowUserSettings(param entity.SQLEditorSettings) (*entity.SQLEditorSettings, error) {
	res := entity.SQLEditorSettings{}
	err := database.DBConn.DB.Table("sql_editor_settings").Where("cluster_id=? and created_by=?", param.ClusterID, param.CreatedBy).First(&res).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			param.BasicSettings = "{\"limit\": " + strconv.Itoa(LIMIT) + ",\"show_system_db_schema\":false}"
			if err = database.DBConn.DB.Table("sql_editor_settings").Save(&param).Error; err != nil {
				return nil, err
			}
			return &param, nil
		} else {
			return nil, err
		}
	}
	return &res, nil
}

func ShowUserInfo(createdBy string) (*entity.UserInfo, error) {
	res := entity.UserInfo{CreatedBy: createdBy}
	err := database.DBConn.DB.Table("sql_editor_user").Where("created_by=?", createdBy).Find(&res).Error
	if err != nil {
		return nil, err
	}
	return &res, nil
}

func UpdateUserInfo(param map[string]interface{}) error {
	err := database.DBConn.DB.Table("sql_editor_user").Clauses(clause.OnConflict{
		Columns:   []clause.Column{{Name: "created_by"}},
		DoUpdates: clause.Assignments(updateExpr(param)),
	}).Create(&param).Error
	if err != nil {
		return err
	}

	return nil
}

func updateExpr(m map[string]interface{}) map[string]interface{} {
	updates := make(map[string]interface{}, 0)
	for k, v := range m {
		if k == "privacy_box_count" {
			updates[k] = gorm.Expr("privacy_box_count + ?", v)
		} else {
			updates[k] = v
		}
	}
	return updates
}

func CreateMessage(param entity.SqlEditorMessage) error {
	err := database.DBConn.DB.Table("sql_editor_message").Save(&param).Error
	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("create message: %+v failed", param))
	}
	return nil
}

func CreateOplog(param entity.SqlEditorOplog) error {
	err := database.DBConn.DB.Table("sql_editor_oplog").Save(&param).Error
	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("create sql editor oplog: %+v failed", param))
	}
	return nil
}

func ShowOplog(chat2querySid string, eventType string) (*entity.SqlEditorOplog, error) {
	var res entity.SqlEditorOplog
	err := database.DBConn.DB.Table("sql_editor_oplog").Where("chat2query_sid=? AND event_type=?", chat2querySid, eventType).First(&res).Error
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("ShowOplog failed, chat2query_sid:%s, event_type:%s", chat2querySid, eventType))
	}
	return &res, nil
}

func CreateSQLFile(param entity.SqlEditorFile) (*uint64, error) {
	err := database.DBConn.DB.Table("sql_editor_files").Save(&param).Error
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("create sql file: %+v failed", param))
	}
	return &param.ID, nil
}

func ShowSQLFile(sqlfileId uint64, createdBy string) (*entity.SqlEditorFile, error) {
	res := entity.SqlEditorFile{}
	err := database.DBConn.DB.Table("sql_editor_files").Where("id=? and created_by=?", sqlfileId, createdBy).First(&res).Error
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("show sql file: %v failed", sqlfileId))
	}
	return &res, nil
}

func UpdateSQLFile(param entity.SqlEditorFile) error {
	if err := database.DBConn.DB.Table("sql_editor_files").Where("id=? and created_by=? and is_deleted=0", param.ID, param.UpdatedBy).Updates(map[string]interface{}{"name": param.Name, "content": param.Content}).Error; err != nil {
		return errors.Wrap(err, fmt.Sprintf("update sql file failed! id:%v", param.ID))
	}
	return nil
}

func DeleteSQLFile(sqlfileId uint64, createdBy string) error {
	if err := database.DBConn.DB.Table("sql_editor_files").Where("id=? and created_by=?", sqlfileId, createdBy).Update("is_deleted", 1).Error; err != nil {
		return errors.Wrap(err, fmt.Sprintf("delete sql file failed! id:%v", sqlfileId))
	}
	return nil
}

func ListSQLFile(clusterId uint64, createdBy string) ([]*entity.SqlEditorFile, error) {
	var sqlfileEntity []*entity.SqlEditorFile
	if err := database.DBConn.DB.Where("cluster_id=? and created_by=? and is_deleted=0", clusterId, createdBy).Order("created_at desc").Find(&sqlfileEntity).Error; err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("list sql file failed! clusterid: %v", clusterId))
	}
	return sqlfileEntity, nil
}

//func UpdateMessage(param entity.SqlEditorMessage) error {
//	err := database.DBConn.DB.Table("sql_editor_message").Where("sql_id=?", param.SqlId).Updates(&param).Error
//	if err != nil {
//		return errors.Wrap(err, fmt.Sprintf("update message: %+v failed", param))
//	}
//	return nil
//}

//func UpdateUserInfo(param map[string]interface{}) error {
//	for k, v := range param {
//		if k == "created_by" {
//			continue
//		} else if k == "privacy_box_count" {
//			err := database.DBConn.DB.Table("sql_editor_user").Clauses(clause.OnConflict{
//				Columns:   []clause.Column{{Name: "created_by"}},
//				DoUpdates: clause.Assignments(map[string]interface{}{"privacy_box_count": gorm.Expr("privacy_box_count + ?", v)}),
//			}).Create(&param).Error
//			if err != nil {
//				return err
//			}
//		} else {
//			err := database.DBConn.DB.Table("sql_editor_user").Clauses(clause.OnConflict{
//				Columns:   []clause.Column{{Name: "created_by"}},
//				DoUpdates: clause.AssignmentColumns([]string{k}),
//			}).Create(&param).Error
//			if err != nil {
//				return err
//			}
//		}
//	}
//	return nil
//}
