package models

import (
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"html"
	"strings"
	"time"
)

const (
	BusinessConfUseXf          = "UseXf"
	BusinessConfXfAppid        = "XfAppid"
	BusinessConfXfApiKey       = "XfApiKey"
	BusinessConfXfApiSecret    = "XfApiSecret"
	BusinessConfXfVcn          = "XfVcn"
	BusinessConfEnPptCoverImgs = "EnPptCoverImgs"
)

// BusinessConf 商户配置表
type BusinessConf struct {
	Id         int    `orm:"column(id);pk"`
	ConfKey    string `description:"配置Key"`
	ConfVal    string `description:"配置值"`
	ValType    int    `description:"1-字符串；2-数值；3-字符串数组；4-富文本；"`
	Necessary  int    `description:"是否必填：0-否；1-是"`
	Remark     string `description:"备注"`
	CreateTime time.Time
}

func (m *BusinessConf) TableName() string {
	return "business_conf"
}

func (m *BusinessConf) PrimaryId() string {
	return "id"
}

func (m *BusinessConf) Create() (err error) {
	o := orm.NewOrm()
	id, err := o.Insert(m)
	if err != nil {
		return
	}
	m.Id = int(id)
	return
}

func (m *BusinessConf) CreateMulti(items []*BusinessConf) (err error) {
	if len(items) == 0 {
		return
	}
	o := orm.NewOrm()
	_, err = o.InsertMulti(len(items), items)
	return
}

func (m *BusinessConf) Update(cols []string) (err error) {
	o := orm.NewOrm()
	_, err = o.Update(m, cols...)
	return
}

func (m *BusinessConf) Del() (err error) {
	o := orm.NewOrm()
	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
	_, err = o.Raw(sql, m.Id).Exec()
	return
}

func (m *BusinessConf) GetItemById(id int) (item *BusinessConf, err error) {
	o := orm.NewOrm()
	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
	err = o.Raw(sql, id).QueryRow(&item)
	return
}

func (m *BusinessConf) GetItemByCondition(condition string, pars []interface{}) (item *BusinessConf, err error) {
	o := orm.NewOrm()
	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s LIMIT 1`, m.TableName(), condition)
	err = o.Raw(sql, pars).QueryRow(&item)
	return
}

func (m *BusinessConf) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
	o := orm.NewOrm()
	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
	err = o.Raw(sql, pars).QueryRow(&count)
	return
}

func (m *BusinessConf) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*BusinessConf, err error) {
	o := orm.NewOrm()
	fields := strings.Join(fieldArr, ",")
	if len(fieldArr) == 0 {
		fields = `*`
	}
	order := `ORDER BY create_time DESC`
	if orderRule != "" {
		order = ` ORDER BY ` + orderRule
	}
	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
	_, err = o.Raw(sql, pars).QueryRows(&items)
	return
}

func (m *BusinessConf) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*BusinessConf, err error) {
	o := orm.NewOrm()
	fields := strings.Join(fieldArr, ",")
	if len(fieldArr) == 0 {
		fields = `*`
	}
	order := `ORDER BY create_time DESC`
	if orderRule != "" {
		order = ` ORDER BY ` + orderRule
	}
	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
	return
}

// GetBusinessConf 获取商家配置
func GetBusinessConf() (list map[string]string, err error) {
	list = make(map[string]string)

	var items []*BusinessConf
	o := orm.NewOrm()
	sql := `SELECT * FROM business_conf`
	_, err = o.Raw(sql).QueryRows(&items)
	if err != nil {
		return
	}

	for _, v := range items {
		if v.ValType == 4 {
			list[v.ConfKey] = html.UnescapeString(v.ConfVal)
			continue
		}
		list[v.ConfKey] = v.ConfVal
	}
	return
}

// BusinessConfUpdate 更新配置
type BusinessConfUpdate struct {
	ConfKey string
	ConfVal string
}

// UpdateBusinessConfMulti 批量修改配置
func UpdateBusinessConfMulti(items []BusinessConfUpdate) (err error) {
	o := orm.NewOrm()
	p, err := o.Raw("UPDATE business_conf SET conf_val = ? WHERE conf_key = ?").Prepare()
	if err != nil {
		return
	}
	defer func() {
		_ = p.Close()
	}()
	for _, v := range items {
		_, err = p.Exec(v.ConfVal, v.ConfKey)
		if err != nil {
			return
		}
	}
	return
}
