package repo

import (
	"fmt"
	v1 "github.com/deeptest-com/deeptest/cmd/server/v1/domain"
	"github.com/deeptest-com/deeptest/internal/pkg/config"
	"github.com/deeptest-com/deeptest/internal/pkg/consts"
	serverConsts "github.com/deeptest-com/deeptest/internal/server/consts"
	"github.com/deeptest-com/deeptest/internal/server/core/cache"
	"github.com/deeptest-com/deeptest/internal/server/core/dao"
	"github.com/deeptest-com/deeptest/internal/server/modules/model"
	_domain "github.com/deeptest-com/deeptest/pkg/domain"
	logUtils "github.com/deeptest-com/deeptest/pkg/lib/log"
	"gorm.io/gorm"
	"sort"
	"strconv"
	"strings"
	"time"
)

type ServeRepo struct {
	*BaseRepo       `inject:""`
	CategoryRepo    *CategoryRepo    `inject:""`
	EnvironmentRepo *EnvironmentRepo `inject:""`
}

func (r *ServeRepo) ListVersion(tenantId consts.TenantId, serveId uint) (res []model.ServeVersion, err error) {
	err = r.GetDB(tenantId).Where("serve_id = ? AND NOT deleted AND not disabled", serveId).Find(&res).Error
	return
}

func (r *ServeRepo) ListByProject(tenantId consts.TenantId, projectId uint) (pos []model.Serve, err error) {
	err = r.GetDB(tenantId).
		Where("project_id=?", projectId).
		Where("NOT deleted").
		Find(&pos).Error
	return
}

func (r *ServeRepo) ListByProjects(tenantId consts.TenantId, projectIds []uint) (pos []model.Serve, err error) {
	err = r.GetDB(tenantId).
		Where("project_id IN (?)", projectIds).
		Where("NOT deleted").
		Find(&pos).Error
	return
}

func (r *ServeRepo) Paginate(tenantId consts.TenantId, req v1.ServeReqPaginate) (ret _domain.PageData, err error) {

	var count int64
	db := r.GetDB(tenantId).Model(&model.Serve{}).Where("project_id = ? AND NOT deleted AND NOT disabled", req.ProjectId)

	if req.Name != "" {
		db = db.Where("name LIKE ?", fmt.Sprintf("%%%s%%", req.Name))
	}

	err = db.Count(&count).Error
	if err != nil {
		logUtils.Errorf("count report error %s", err.Error())
		return
	}

	results := make([]*model.Serve, 0)

	err = db.Scopes(dao.PaginateScope(req.Page, req.PageSize, req.Order, req.Field)).Find(&results).Error
	if err != nil {
		logUtils.Errorf("query report error %s", err.Error())
		return
	}

	//关联环境
	for key, result := range results {
		results[key].Servers, err = r.ListServer(tenantId, result.ID)
		if err != nil {
			return
		}

	}

	ret.Populate(results, count, req.Page, req.PageSize)

	return
}

func (r *ServeRepo) PaginateVersion(tenantId consts.TenantId, req v1.ServeVersionPaginate) (ret _domain.PageData, err error) {
	var count int64
	db := r.GetDB(tenantId).Model(&model.ServeVersion{}).Where("serve_id = ? AND NOT deleted AND NOT disabled", req.ServeId)

	if req.Version != "" {
		db = db.Where("value LIKE ?", fmt.Sprintf("%%%s%%", req.Version))
	}

	if req.CreateUser != "" {
		db = db.Where("creat_user = ?", fmt.Sprintf("%s", req.CreateUser))
	}

	err = db.Count(&count).Error
	if err != nil {
		logUtils.Errorf("count report error %s", err.Error())
		return
	}

	results := make([]*model.ServeVersion, 0)

	err = db.Scopes(dao.PaginateScope(req.Page, req.PageSize, req.Order, req.Field)).Find(&results).Error
	if err != nil {
		logUtils.Errorf("query report error %s", err.Error())
		return
	}
	ret.Populate(results, count, req.Page, req.PageSize)

	return
}

func (r *ServeRepo) PaginateSchema(tenantId consts.TenantId, req v1.ServeSchemaPaginate) (ret _domain.PageData, err error) {
	var count int64
	db := r.GetDB(tenantId).Model(&model.ComponentSchema{}).Where("project_id = ? AND NOT deleted AND NOT disabled", req.ProjectId)
	if req.Type != "" {
		db.Where("type=?", req.Type)
	}
	if req.Name != "" {
		db = db.Where("name LIKE ?", fmt.Sprintf("%%%s%%", req.Name))

	}

	err = db.Count(&count).Error
	if err != nil {
		logUtils.Errorf("count report error %s", err.Error())
		return
	}

	results := make([]*model.ComponentSchema, 0)

	err = db.Scopes(dao.PaginateScope(req.Page, req.PageSize, req.Order, req.Field)).Find(&results).Error
	if err != nil {
		logUtils.Errorf("query report error %s", err.Error())
		return
	}

	//事实计算schema组件引用信息
	for key, item := range results {
		results[key].Ref, err = r.GetSchemaRef(tenantId, item.ID)
	}
	ret.Populate(results, count, req.Page, req.PageSize)

	return
}

func (r *ServeRepo) PaginateSecurity(tenantId consts.TenantId, req v1.ServeSecurityPaginate) (ret _domain.PageData, err error) {
	var count int64
	db := r.GetDB(tenantId).Model(&model.ComponentSchemaSecurity{}).Where("serve_id = ? AND NOT deleted AND NOT disabled", req.ServeId)

	err = db.Count(&count).Error
	if err != nil {
		logUtils.Errorf("count report error %s", err.Error())
		return
	}

	results := make([]*model.ComponentSchemaSecurity, 0)

	err = db.Scopes(dao.PaginateScope(req.Page, req.PageSize, req.Order, req.Field)).Find(&results).Error
	if err != nil {
		logUtils.Errorf("query report error %s", err.Error())
		return
	}
	ret.Populate(results, count, req.Page, req.PageSize)

	return
}

func (r *ServeRepo) Get(tenantId consts.TenantId, id uint) (res model.Serve, err error) {
	//err = r.GetDB(tenantId).Where("NOT deleted AND not disabled").First(&res, id).Error
	err = r.GetDB(tenantId).Where("NOT deleted").First(&res, id).Error
	return
}

func (r *ServeRepo) GetByCode(tenantId consts.TenantId, projectId uint, shortName string) (ret model.Serve, err error) {
	db := r.GetDB(tenantId).Model(&ret).
		Where("short_name = ? AND NOT deleted", shortName)

	if projectId > 0 {
		db.Where("project_id = ?", projectId)
	}

	err = db.First(&ret).Error

	return
}

func (r *ServeRepo) GetSchema(tenantId consts.TenantId, id uint) (res model.ComponentSchema, err error) {
	err = r.GetDB(tenantId).Where("NOT deleted AND not disabled").First(&res, id).Error
	return
}

func (r *ServeRepo) GetSchemasByServeId(tenantId consts.TenantId, serveId uint) (res []model.ComponentSchema, err error) {
	err = r.GetDB(tenantId).Where("NOT deleted AND not disabled AND serve_id = ?", serveId).Find(&res).Error
	return
}

func (r *ServeRepo) GetSchemasByProjectId(tenantId consts.TenantId, projectId uint, options ...[]interface{}) (res []model.ComponentSchema, err error) {
	db := r.GetDB(tenantId).Select("id", fmt.Sprintf("(WITH RECURSIVE temp(id,parent_id,name) AS (SELECT id,parent_id,name from biz_category where entity_id = biz_project_serve_component_schema.id and type = '%s'  UNION ALL SELECT b.id,b.parent_id,b.name from biz_category b, temp c where c.parent_id = b.id and  b.parent_id > 0) select GROUP_CONCAT(name ORDER BY (@row_number:=@row_number+1) desc SEPARATOR  '.') name from temp,(select @row_number := 0) x  ) name", serverConsts.SchemaCategory), "type", "content", "serve_id", "examples", "tags", "description", "ref", "source_type", "project_id")
	db = db.Where("NOT deleted AND not disabled AND project_id = ?", projectId)
	if len(options) > 0 && len(options[0]) > 0 {
		db = db.Where("id in ?", options[0])
	}
	err = db.Find(&res).Error

	for key, item := range res {
		res[key].Ref = fmt.Sprintf("#/components/schemas/%s", item.Name)
	}

	return
}

func (r *ServeRepo) DeleteById(tenantId consts.TenantId, id uint) error {
	return r.GetDB(tenantId).Model(&model.Serve{}).Where("id = ?", id).Update("deleted", 1).Error
}

func (r *ServeRepo) DisableById(tenantId consts.TenantId, id uint) error {
	return r.GetDB(tenantId).Model(&model.Serve{}).Where("id = ?", id).Update("status", 4).Error
}

func (r *ServeRepo) DeleteVersionById(tenantId consts.TenantId, id uint) error {
	return r.GetDB(tenantId).Model(&model.ServeVersion{}).Where("id = ?", id).Update("deleted", 1).Error
}

func (r *ServeRepo) DisableVersionById(tenantId consts.TenantId, id uint) error {
	return r.GetDB(tenantId).Model(&model.ServeVersion{}).Where("id = ?", id).Update("disabled", 1).Error
}

func (r *ServeRepo) ListServer(tenantId consts.TenantId, serveId uint) (servers model.ServeServerArr, err error) {
	err = r.GetDB(tenantId).Where("serve_id = ? AND NOT deleted AND not disabled", serveId).
		Find(&servers).Error

	for index, server := range servers {
		var environment model.Environment
		environment, err = r.EnvironmentRepo.Get(tenantId, server.EnvironmentId)
		if err != nil {
			return
		}

		servers[index].EnvironmentName = environment.Name
		servers[index].Sort = environment.Sort
	}

	sort.Sort(servers)

	return
}

func (r *ServeRepo) ListSecurity(tenantId consts.TenantId, serveId uint) (res []model.ComponentSchemaSecurity, err error) {
	err = r.GetDB(tenantId).Where("serve_id = ? AND NOT deleted AND not disabled", serveId).Find(&res).Error
	return
}

func (r *ServeRepo) DeleteSchemaById(tenantId consts.TenantId, id uint) error {
	return r.GetDB(tenantId).Model(&model.ComponentSchema{}).Where("id = ?", id).Update("deleted", 1).Error
}

func (r *ServeRepo) DeleteSecurityId(tenantId consts.TenantId, id uint) error {
	return r.GetDB(tenantId).Model(&model.ComponentSchemaSecurity{}).Where("id = ?", id).Update("deleted", 1).Error
}

func (r *ServeRepo) SaveServeEndpointVersions(tenantId consts.TenantId, versions []model.ServeEndpointVersion) error {
	return r.GetDB(tenantId).Create(&versions).Error
}

func (r *ServeRepo) DeleteSaveServeEndpointVersions(tenantId consts.TenantId, serveId int64, version string) error {
	return r.GetDB(tenantId).Delete(&model.ServeEndpointVersion{}, "serve_id=? and serve_version=?", serveId, version).Error
}

func (r *ServeRepo) BindEndpoint(tenantId consts.TenantId, serveId int64, serveVersion string, serveEndpointVersion []model.ServeEndpointVersion) (err error) {
	r.GetDB(tenantId).Transaction(func(tx *gorm.DB) error {
		err = r.DeleteSaveServeEndpointVersions(tenantId, serveId, serveVersion)
		if err != nil {
			return err
		}
		err = r.SaveServeEndpointVersions(tenantId, serveEndpointVersion)
		if err != nil {
			return err
		}
		return nil
	})
	return
}

func (r *ServeRepo) SaveServer(tenantId consts.TenantId, environmentId uint, environmentName string, servers []model.ServeServer) (err error) {

	err = r.GetDB(tenantId).Delete(&model.ServeServer{}, "environment_id=?", environmentId).Error
	if err != nil {
		return err
	}

	if len(servers) == 0 {
		return
	}

	for key, _ := range servers {
		//servers[key].ID = 0
		servers[key].EnvironmentId = environmentId
		servers[key].Description = environmentName
		err = r.Save(tenantId, servers[key].ID, &servers[key])
		if err != nil {
			return err
		}
	}
	/*
		err = r.GetDB(tenantId).CreateExpression(servers).Error
		if err != nil {
			return err
		}
	*/
	return
}

func (r *ServeRepo) SaveServerForServe(tenantId consts.TenantId, serveId uint, servers []model.ServeServer) (err error) {
	if len(servers) == 0 {
		return
	}
	err = r.GetDB(tenantId).Delete(&model.ServeServer{}, "serve_id=?", serveId).Error
	if err != nil {
		return err
	}

	err = r.GetDB(tenantId).Create(servers).Error
	return
}

func (r *ServeRepo) ServeExist(tenantId consts.TenantId, id, projectId uint, name string) (res bool) {
	var count int64
	err := r.GetDB(tenantId).Model(&model.Serve{}).Where("id != ? and name = ? and project_id = ? AND NOT deleted", id, name, projectId).Count(&count).Error
	if err != nil {
		return false
	}
	return count > 0

}

func (r *ServeRepo) VersionExist(tenantId consts.TenantId, id, serveId uint, value string) (res bool) {
	var count int64
	err := r.GetDB(tenantId).Model(&model.ServeVersion{}).Where("id != ? and value = ? and serve_id=? AND NOT deleted", id, value, serveId).Count(&count).Error
	if err != nil {
		return false
	}
	return count > 0

}

func (r *ServeRepo) SecurityExist(tenantId consts.TenantId, id, serveId uint, name string) (res bool) {
	var count int64
	err := r.GetDB(tenantId).Model(&model.ComponentSchemaSecurity{}).Where("id != ? and name = ? and serve_id=? AND NOT deleted", id, name, serveId).Count(&count).Error
	if err != nil {
		return false
	}
	return count > 0

}

func (r *ServeRepo) SchemaExist(tenantId consts.TenantId, id, serveId uint, name string) (res bool) {
	var count int64
	err := r.GetDB(tenantId).Model(&model.ComponentSchema{}).Where("id != ? and name = ? and serve_id=? AND NOT deleted", id, name, serveId).Count(&count).Error
	if err != nil {
		return false
	}
	return count > 0

}

func (r *ServeRepo) SaveVersion(tenantId consts.TenantId, id uint, version *model.ServeVersion) (err error) {
	if id == 0 {
		err = r.CopyEndpointsVersionRef(tenantId, version)
		if err != nil {
			return err
		}
	}
	err = r.Save(tenantId, id, &version)
	if err != nil {
		return err
	}
	return
}

func (r *ServeRepo) GetLatestVersion(tenantId consts.TenantId, serveId uint) (res model.ServeVersion, err error) {
	var version model.ServeVersion
	err = r.GetDB(tenantId).Take(&version, "serve_id=?", serveId).Order("value desc").Error
	if err != nil {
		return
	}
	return
}

func (r *ServeRepo) GetBindEndpoints(tenantId consts.TenantId, serveId uint, version string) (endpoints []model.ServeEndpointVersion, err error) {
	err = r.GetDB(tenantId).Find(&endpoints, "serve_id=? and serve_version=?", serveId, version).Error
	return
}

func (r *ServeRepo) CopyEndpoints(tenantId consts.TenantId, endpoints []model.ServeEndpointVersion, version string) (err error) {
	for key, _ := range endpoints {
		endpoints[key].ID = 0
		endpoints[key].ServeVersion = version
	}
	return r.GetDB(tenantId).Create(endpoints).Error
}

func (r *ServeRepo) CopyEndpointsVersionRef(tenantId consts.TenantId, version *model.ServeVersion) (err error) {
	var latestVersion model.ServeVersion
	latestVersion, _ = r.GetLatestVersion(tenantId, uint(version.ServeId))
	if latestVersion.Value != "" {
		var endpoints []model.ServeEndpointVersion
		endpoints, err = r.GetBindEndpoints(tenantId, uint(version.ServeId), latestVersion.Value)
		if err != nil {
			err = r.CopyEndpoints(tenantId, endpoints, version.Value)
			if err != nil {
				return
			}
		}
	}
	return err
}
func (r *ServeRepo) GetBindEndpointIds(tenantId consts.TenantId, serveId uint, version string) (ids []int64, err error) {
	var endpointVersions []model.ServeEndpointVersion
	endpointVersions, err = r.GetBindEndpoints(tenantId, serveId, version)
	for _, endpointVersion := range endpointVersions {
		ids = append(ids, endpointVersion.EndpointId)
	}
	return
}

func (r *ServeRepo) ChangeServe(tenantId consts.TenantId, serveId, userId uint) (serve model.Serve, err error) {
	err = r.GetDB(tenantId).Model(&model.SysUserProfile{}).Where("user_id = ?", userId).
		Updates(map[string]interface{}{"curr_serve_id": serveId}).Error

	serve, err = r.Get(tenantId, serveId)

	return
}

func (r *ServeRepo) GetCurrServeByUser(tenantId consts.TenantId, userId uint) (currServe model.Serve, err error) {
	var user model.SysUser
	err = r.GetDB(tenantId).Preload("Profile").
		Where("id = ?", userId).
		First(&user).
		Error

	// may be null
	r.GetDB(tenantId).Model(&model.Serve{}).
		Where("id = ?", user.Profile.CurrServeId).
		First(&currServe)

	return
}

func (r *ServeRepo) SetCurrServeByUser(tenantId consts.TenantId, serveId, userId uint) (err error) {
	err = r.GetDB(tenantId).Model(&model.SysUserProfile{}).
		Where("user_id = ?", userId).
		Update("curr_serve_id", serveId).Error

	return
}

func (r *ServeRepo) GetCurrServerByUser(tenantId consts.TenantId, projectId, serveId, userId uint) (currServer model.ServeServer, err error) {
	projectUserServer, err := r.EnvironmentRepo.GetProjectUserServer(tenantId, projectId, userId)
	if err != nil {
		return
	}

	// may be null
	err = r.GetDB(tenantId).Model(&model.ServeServer{}).
		Where("environment_id = ? and serve_id = ?", projectUserServer.ServerId, serveId).
		First(&currServer).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return
	}
	if currServer.ID == 0 || err == gorm.ErrRecordNotFound {
		return currServer, nil
	}

	environment, err := r.EnvironmentRepo.Get(tenantId, projectUserServer.ServerId)
	if err != nil {
		return
	}
	currServer.EnvironmentName = environment.Name
	currServer.Sort = environment.Sort

	return
}

func (r *ServeRepo) SetCurrServerByUser(tenantId consts.TenantId, serverId, userId uint) (err error) {
	err = r.GetDB(tenantId).Model(&model.SysUserProfile{}).
		Where("user_id = ?", userId).
		Update("curr_server_id", serverId).Error

	return
}

func (r *ServeRepo) SaveServe(tenantId consts.TenantId, serve *model.Serve) (err error) {
	return r.GetDB(tenantId).Transaction(func(tx *gorm.DB) error {
		if serve.ID == 0 { //生成目录树跟节点
			/*
				err = r.AddDefaultCategory(serve.ProjectId)
				if err != nil {
					return err
				}
			*/

			//创建默认环境
			err = r.Save(tenantId, serve.ID, &serve)
			if err != nil {
				return err
			}

			err = r.AddDefaultServer(tenantId, serve.ProjectId, serve.ID)
			if err != nil {
				return err
			}
			//目录树默认不挂在根目录下面
			//			err = r.AddDefaultTestCategory(serve.ProjectId, serve.ID)

		} else {
			err = r.Save(tenantId, serve.ID, &serve)
		}

		if err != nil {
			return err
		}
		return nil
	})
}

func (r *ServeRepo) GetSchemaByRef(tenantId consts.TenantId, projectId uint, ref string) (res model.ComponentSchema, err error) {
	err = r.GetDB(tenantId).Where("project_id = ? AND NOT deleted AND not disabled and ref = ?", projectId, ref).Find(&res).Error
	return
}

func (r *ServeRepo) GetServerCountByEnvironmentId(tenantId consts.TenantId, environmentId uint) (count int64, err error) {
	err = r.GetDB(tenantId).Model(&model.ServeServer{}).Where("environment_id = ? AND NOT deleted AND not disabled ", environmentId).Count(&count).Error
	return
}

func (r *ServeRepo) GetCountByProject(tenantId consts.TenantId, projectId uint) (count int64, err error) {
	err = r.GetDB(tenantId).Model(&model.Serve{}).Where("project_id = ? AND NOT deleted AND not disabled ", projectId).Count(&count).Error
	return
}

func (r *ServeRepo) CreateServeSample(tenantId consts.TenantId, projectId uint) (serveId uint, err error) {
	return
}

func (r *ServeRepo) AddDefaultCategory(tenantId consts.TenantId, projectId uint) (err error) {
	category := model.Category{Name: "所属分类", ProjectId: projectId, Type: serverConsts.EndpointCategory}
	err = r.CategoryRepo.Save(tenantId, &category)
	return
}

func (r *ServeRepo) AddDefaultServer(tenantId consts.TenantId, projectId, serveId uint) (err error) {
	//var defaultEnv model.Environment
	defaultEnvs, err := r.EnvironmentRepo.GetDefaultByProject(tenantId, projectId)
	if err != nil {
		return
	}

	var defaultServer []model.ServeServer
	for _, v := range defaultEnvs {
		server := model.ServeServer{
			ServeId:       serveId,
			EnvironmentId: v.ID,
			Description:   v.Name,
			Url:           serverConsts.DefaultSever,
		}
		if v.Name == "Mock环境" {
			host, _ := cache.GetCacheString(fmt.Sprintf("%s_host", tenantId))
			if config.CONFIG.Saas.Switch {
				server.Url = host + "/lya/mocks/" + strconv.Itoa(int(serveId))
			} else {
				server.Url = host + "/mocks/" + strconv.Itoa(int(serveId))
			}

		}
		defaultServer = append(defaultServer, server)
	}
	err = r.SaveServerForServe(tenantId, serveId, defaultServer)

	if err != nil {
		return
	}

	return
}

func (r *ServeRepo) AddDefaultTestCategory(tenantId consts.TenantId, projectId uint) (err error) {
	root := model.DiagnoseInterface{
		Title:     "根节点",
		ProjectId: projectId,
		IsDir:     true,
		Type:      "dir",
	}
	err = r.GetDB(tenantId).Create(&root).Error
	return
}

func (r *ServeRepo) GetServesByIds(tenantId consts.TenantId, ids []uint) (serves []model.Serve, err error) {
	err = r.GetDB(tenantId).Where("id in ? AND not deleted AND not disabled ", ids).Find(&serves).Error
	return
}

func (r *ServeRepo) GetSchemas(tenantId consts.TenantId, serveIs []uint) (res []model.ComponentSchema, err error) {
	err = r.GetDB(tenantId).Where("NOT deleted AND not disabled and serve_id in ?", serveIs).Find(&res).Error
	return
}

func (r *ServeRepo) GetSecurities(tenantId consts.TenantId, serveIs []uint) (res []model.ComponentSchemaSecurity, err error) {
	err = r.GetDB(tenantId).Where("NOT deleted AND not disabled and serve_id in ?", serveIs).Find(&res).Error
	return
}

func (r *ServeRepo) GetServers(tenantId consts.TenantId, serveIs []uint) (res []model.ServeServer, err error) {
	err = r.GetDB(tenantId).Where("NOT deleted AND not disabled and serve_id in ?", serveIs).Find(&res).Error
	var environmentIds []uint
	for _, server := range res {
		environmentIds = append(environmentIds, server.EnvironmentId)
	}

	environments, _ := r.EnvironmentRepo.GetByIds(tenantId, environmentIds)
	for key, server := range res {
		res[key].EnvironmentName = environments[server.EnvironmentId].Name
	}
	return
}

func (r *ServeRepo) CreateSchemas(tenantId consts.TenantId, schemas []*model.ComponentSchema) (err error) {
	return r.GetDB(tenantId).Create(schemas).Error
}

func (r *ServeRepo) SaveSwaggerSync(tenantId consts.TenantId, sync *model.SwaggerSync) (err error) {
	return r.Save(tenantId, sync.ID, sync)
}

func (r *ServeRepo) GetSwaggerSync(tenantId consts.TenantId, projectId uint) (sync model.SwaggerSync, err error) {
	err = r.GetDB(tenantId).First(&sync, "project_id=?", projectId).Error
	return
}

func (r *ServeRepo) GetSwaggerSyncById(tenantId consts.TenantId, id uint) (sync model.SwaggerSync, err error) {
	err = r.GetDB(tenantId).First(&sync, "id=?", id).Error
	return
}

func (r *ServeRepo) GetSwaggerSyncList(tenantId consts.TenantId) (res []model.SwaggerSync, err error) {
	err = r.GetDB(tenantId).Find(&res).Error
	return
}

func (r *ServeRepo) GetDefault(tenantId consts.TenantId, projectId uint) (res model.Serve, err error) {
	err = r.GetDB(tenantId).Where("NOT deleted and project_id=?", projectId).First(&res).Error
	return
}

func (r *ServeRepo) GetComponentByItem(tenantId consts.TenantId, sourceType consts.SourceType, projectId uint, ref string) (res model.ComponentSchema, err error) {
	err = r.GetDB(tenantId).First(&res, "source_type=? AND project_id=? AND ref=? AND NOT deleted", sourceType, projectId, ref).Error
	return
}

func (r *ServeRepo) SaveSchemas(tenantId consts.TenantId, schemas []*model.ComponentSchema) (err error) {
	err = r.GetDB(tenantId).Save(schemas).Error
	if err == nil {
		var categories []*model.Category
		if len(schemas) == 0 {
			return err
		}

		var rootCategory model.Category
		projectId := schemas[0].ProjectId
		rootCategory, err = r.CategoryRepo.GetRoot(tenantId, serverConsts.SchemaCategory, schemas[0].ProjectId)
		if err != nil {
			return err
		}

		ordr := r.CategoryRepo.GetMaxOrder(tenantId, rootCategory.ID, serverConsts.SchemaCategory, projectId)
		for _, schema := range schemas {
			category, _ := r.CategoryRepo.GetByEntityId(tenantId, schema.ID, serverConsts.SchemaCategory)
			category.Name = schema.Name
			category.EntityId = schema.ID
			category.ParentId = int(rootCategory.ID)
			category.Type = serverConsts.SchemaCategory
			category.ProjectId = schema.ProjectId
			category.Ordr = ordr
			categories = append(categories, &category)
			ordr += 1
		}

		err = r.GetDB(tenantId).Save(categories).Error

	}

	return err
}

func (r *ServeRepo) UpdateSwaggerSyncExecTimeById(tenantId consts.TenantId, id uint) (err error) {
	return r.GetDB(tenantId).Model(&model.SwaggerSync{}).Where("id=?", id).Update("exec_time", time.Now()).Error
}

func (r *ServeRepo) ListAll(tenantId consts.TenantId) (res []model.Serve, err error) {
	err = r.GetDB(tenantId).Model(&model.Serve{}).
		Where("not disabled and not deleted").
		Find(&res).Error
	return
}

func (r *ServeRepo) BatchUpdateSchemaProjectByServeId(tenantId consts.TenantId, serveIds []uint, projectId uint) (err error) {
	err = r.GetDB(tenantId).Model(&model.ComponentSchema{}).Where("serve_id IN (?)", serveIds).Update("project_id", projectId).Error
	return
}

func (r *ServeRepo) GetSchemaRef(tenantId consts.TenantId, schemaId uint) (ref string, err error) {
	category, err := r.CategoryRepo.GetByEntityId(tenantId, schemaId, serverConsts.SchemaCategory)
	if err != nil {
		return
	}
	path, err := r.CategoryRepo.GetJoinedPath(tenantId, category.ID)
	if err != nil {
		return
	}

	ref = "#/components/schemas/" + strings.Join(path, ".")
	return

}

func (r *ServeRepo) GetDefaultServer(tenantId consts.TenantId, serveId uint) (server model.ServeServer, err error) {
	err = r.GetDB(tenantId).Model(&model.ServeServer{}).Where("serve_id=? AND NOT deleted ", serveId).First(&server).Order("created_at desc").Error
	return
}

func (r *ServeRepo) MockUrl(tenantId consts.TenantId) (err error) {
	host, _ := cache.GetCacheString(fmt.Sprintf("%s_host", tenantId))
	err = r.GetDB(tenantId).Model(&model.ServeServer{}).Where("id = 2 and serve_id = 1 and description = 'Mock环境' and url not like 'http%' AND NOT deleted ").UpdateColumn("url", gorm.Expr("CONCAT(?,url)", host)).Error
	return
}
