package models

import (
	"github.com/veypi/vigo"
	"github.com/veypi/vigo/logv"
	"gorm.io/gorm"
)

const AUSTATUS_OK = "ok"
const AUSTATUS_NO = "no"
const AUSTATUS_APPLYING = "applying"
const AUSTATUS_REJECT = "reject"

type App struct {
	vigo.Model
	Name       string  `json:"name"  src:"json" desc:"应用名称"`
	Icon       string  `json:"icon"  src:"json" desc:"图标"`
	Des        string  `json:"des"  src:"json" desc:"描述"`
	Typ        string  `json:"typ" gorm:"default:public"  src:"json" desc:"类型"`
	Status     string  `json:"status" gorm:"default:ok"  src:"json" desc:"状态"`
	InitRoleID *string `json:"init_role_id" gorm:"index;type:varchar(36);default: null"  src:"json" desc:"初始角色ID"`
	InitRole   *Role   `json:"init_role" gorm:"foreignKey:InitRoleID;references:ID"`
	InitUrl    string  `json:"init_url"  src:"json" desc:"初始URL"`
	UserCount  uint    `json:"user_count" default:"0"`
	Key        string  `json:"-"`
}

type AppUser struct {
	vigo.Model
	AppID string `json:"app_id"  src:"path" desc:"应用ID"`
	App   *App   `json:"app" gorm:"foreignKey:AppID;references:ID"`

	UserID string `json:"user_id"  src:"json" desc:"用户ID"`
	User   *User  `json:"user" gorm:"foreignKey:UserID;references:ID"`

	Status string `json:"status"  src:"json" desc:"状态"`
}

func (m *AppUser) onOk(tx *gorm.DB) (err error) {
	app := &App{}
	logv.AssertError(tx.Where("id = ?", m.AppID).First(app).Error)
	if app.InitRoleID != nil {
		urList := make([]*UserRole, 0, 2)
		logv.AssertError(tx.Debug().Where("app_id = ? AND user_id = ?", m.AppID, m.UserID).Find(&urList).Error)
		if len(urList) == 0 {
			return tx.Create(&UserRole{
				AppID:  m.AppID,
				UserID: m.UserID,
				RoleID: *app.InitRoleID,
				Status: "ok",
			}).Error
		}
	}
	return nil
}

func (m *AppUser) AfterCreate(tx *gorm.DB) error {
	if m.Status == AUSTATUS_OK {
		logv.AssertError(m.onOk(tx))
	}
	return tx.Model(&App{}).Where("id = ?", m.AppID).Update("user_count", gorm.Expr("user_count + ?", 1)).Error
}

func (m *AppUser) AfterUpdate(tx *gorm.DB) error {
	if m.Status == AUSTATUS_OK {
		return m.onOk(tx)
	}
	return nil
}

type Resource struct {
	vigo.Model
	AppID string `json:"app_id" src:"path@app_id" desc:"应用ID"`
	App   *App   `json:"-" gorm:"foreignKey:AppID;references:ID"`
	Name  string `json:"name" src:"json" desc:"名称"`
	Des   string `json:"des" src:"json" desc:"描述"`
}

type Role struct {
	vigo.Model
	AppID     string    `json:"app_id" src:"path@app_id" desc:"应用ID"`
	App       *App      `json:"-" gorm:"foreignKey:AppID;references:ID"`
	Name      string    `json:"name" src:"json" desc:"名称"`
	Des       string    `json:"des" src:"json" desc:"描述"`
	UserCount uint      `json:"user_count" default:"0"`
	Access    []*Access `json:"-"`
}

type Access struct {
	vigo.Model
	AppID string `json:"app_id" gorm:"index;type:varchar(36)" src:"path@app_id" desc:"应用ID"`
	App   *App   `json:"-" gorm:"foreignKey:AppID;references:ID"`

	UserID *string `json:"user_id" gorm:"index;type:varchar(36);default: null" src:"json" desc:"用户ID"`
	User   *User   `json:"-" gorm:"foreignKey:UserID;references:ID"`

	RoleID *string `json:"role_id" gorm:"index;type:varchar(36);default: null" src:"json" desc:"角色ID"`
	Role   *Role   `json:"-" gorm:"foreignKey:RoleID;references:ID"`

	ResourceID *string   `json:"resource_id" gorm:"index;type:varchar(36);default: null" src:"json" desc:"资源ID"`
	Resource   *Resource `json:"-" gorm:"foreignKey:ResourceID;references:ID"`

	Name  string `json:"name" src:"json" desc:"名称"`
	TID   string `json:"tid" src:"json" desc:"资源ID"`
	Level uint   `json:"level" src:"json" desc:"级别"`
}
