package ui

import (
	"context"
	"errors"
	"fmt"
	"go_dreamfactory/cmd/v2/lib/common"
	os_storage "go_dreamfactory/cmd/v2/lib/storage"
	"go_dreamfactory/cmd/v2/service"
	"go_dreamfactory/cmd/v2/service/observer"
	"go_dreamfactory/pb"
	"strings"

	mytheme "go_dreamfactory/cmd/v2/theme"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/layout"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cast"

	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type appMgo struct {
	appAdapter
	conf        *os_storage.Config
	storage     os_storage.Storage
	db          *mongo.Database
	client      *mongo.Client
	scriptEntry *widget.Entry
}

func (this *appMgo) LazyInit(ptService service.PttService, obs observer.Observer) error {
	this.tabItem = container.NewTabItemWithIcon(common.TOOLBAR_MGODB, theme.DownloadIcon(), nil)
	content := container.NewMax()
	content.Objects = []fyne.CanvasObject{}

	this.scriptEntry = widget.NewMultiLineEntry()

	connWinBtn := widget.NewButton("连接设置", this.showConWin)
	openConnBtn := widget.NewButton("打开连接", this.openConn)
	closeConnBtn := widget.NewButton("关闭连接", this.closeConn)
	createServerConfBtn := widget.NewButton("创建服务配置", this.createServerConf)
	btns := container.NewHBox(connWinBtn, openConnBtn, createServerConfBtn, layout.NewSpacer(), closeConnBtn)
	content.Objects = append(content.Objects, container.NewBorder(btns, nil, nil, nil, this.scriptEntry))
	this.tabItem.Content = content
	this.storage, _ = os_storage.NewOSStorage()
	var err error
	this.conf, err = this.storage.LoadConfig()
	if err != nil {
		logrus.Error(err)
		return err
	}
	return nil
}

func (this *appMgo) openConn() {
	if this.conf.MgoDB == nil {
		dialog.ShowError(errors.New("MgoDB没有配置"), toolWin.w)
		return
	}
	var option *options.ClientOptions
	if (this.conf.MgoDB.User == "" && this.conf.MgoDB.Password == "") &&
		this.conf.MgoDB.Host != "" && this.conf.MgoDB.Port != 0 && this.conf.MgoDB.Database != "" {
		option = options.Client().ApplyURI(fmt.Sprintf("mongodb://%s:%d", this.conf.MgoDB.Host, this.conf.MgoDB.Port))
	} else {
		option = options.Client().ApplyURI(fmt.Sprintf("mongodb://%s:%s@%s:%d", this.conf.MgoDB.User, this.conf.MgoDB.Password,
			this.conf.MgoDB.Host, this.conf.MgoDB.Port))
	}
	client, err := mongo.Connect(context.TODO(), option)
	if err != nil {
		logrus.Error(err)
		return
	}
	if err2 := client.Ping(context.TODO(), nil); err2 != nil {
		logrus.Error("Mongo连接失败", err2)
		return
	}
	this.db = client.Database(this.conf.MgoDB.Database)

	this.scriptEntry.Text = this.db.Name() + " 连接成功"
	this.scriptEntry.Refresh()
}

func (this *appMgo) closeConn() {
	if this.db != nil {
		if err := this.db.Client().Disconnect(context.TODO()); err != nil {
			this.scriptEntry.Text = "连接关闭失败"
		} else {
			this.scriptEntry.Text = "连接关闭成功"
		}
		this.scriptEntry.Refresh()
	}
}

func (this *appMgo) createServerConf() {
	serverId := widget.NewEntry()
	serverName := widget.NewEntry()
	owner := widget.NewEntry()
	cross := widget.NewEntry()
	crossId := widget.NewEntry()
	singleserver := widget.NewEntry()
	opentime := widget.NewEntry()
	redisIsCluster := widget.NewEntry()
	redisAddr := widget.NewEntry()
	redisPassword := widget.NewEntry()
	redisDb := widget.NewEntry()
	mongoUrl := widget.NewEntry()
	mongoDatabase := widget.NewEntry()

	form := widget.NewForm(
		widget.NewFormItem("serverid", serverId),
		widget.NewFormItem("serverName", serverName),
		widget.NewFormItem("owner", owner),
		widget.NewFormItem("cross", cross),
		widget.NewFormItem("crossId", crossId),
		widget.NewFormItem("singleserver", singleserver),
		widget.NewFormItem("opentime", opentime),
		widget.NewFormItem("redisIsCluster", redisIsCluster),
		widget.NewFormItem("redisAddr", redisAddr),
		widget.NewFormItem("redisPassword", redisPassword),
		widget.NewFormItem("redisDb", redisDb),
		widget.NewFormItem("mongoUrl", mongoUrl),
		widget.NewFormItem("mongoDatabase", mongoDatabase),
	)

	if this.conf.ServiceDBInfo != nil {
		serverId.Text = this.conf.ServiceDBInfo.Serverid
		serverName.Text = this.conf.ServiceDBInfo.ServerName
		owner.Text = this.conf.ServiceDBInfo.Owner
		cross.Text = this.conf.ServiceDBInfo.Cross
		crossId.Text = this.conf.ServiceDBInfo.CrossId
		singleserver.Text = this.conf.ServiceDBInfo.Singleserver
		opentime.Text = cast.ToString(this.conf.ServiceDBInfo.Opentime)
		redisIsCluster.Text = cast.ToString(this.conf.ServiceDBInfo.RedisIsCluster)
		redisAddr.Text = strings.Join(this.conf.ServiceDBInfo.RedisAddr, ",")
		redisPassword.Text = this.conf.ServiceDBInfo.RedisPassword
		redisDb.Text = cast.ToString(this.conf.ServiceDBInfo.RedisDb)
		mongoUrl.Text = this.conf.ServiceDBInfo.MongodbUrl
		mongoDatabase.Text = this.conf.ServiceDBInfo.MongodbDatabase
	}

	subBtn := widget.NewButton("保存", func() {
		this.conf.ServiceDBInfo = &pb.ServiceDBInfo{
			Serverid:        serverId.Text,
			ServerName:      serverName.Text,
			Owner:           owner.Text,
			Cross:           cross.Text,
			CrossId:         crossId.Text,
			Singleserver:    singleserver.Text,
			Opentime:        cast.ToInt64(opentime.Text),
			RedisIsCluster:  cast.ToBool(redisIsCluster.Text),
			RedisAddr:       strings.Split(redisAddr.Text, ","),
			RedisPassword:   redisPassword.Text,
			RedisDb:         cast.ToInt32(redisDb.Text),
			MongodbUrl:      mongoUrl.Text,
			MongodbDatabase: mongoDatabase.Text,
		}
		if err := this.storage.StoreConfig(this.conf); err != nil {
			logrus.Error(err)
		}
	})
	subBtn.Importance = widget.HighImportance

	execBtn := widget.NewButton("插入", func() {
		if this.db == nil {
			common.ShowTip("请先打开连接")
			return
		}
		c := this.db.Collection("serverdata")
		if _, err := c.InsertOne(context.TODO(), this.conf.ServiceDBInfo); err != nil {
			logrus.Error(err)
			return
		}

		this.scriptEntry.Text = "插入成功"
		this.scriptEntry.Refresh()
	})
	dconf := dialog.NewCustom("配置", "关闭", container.NewVBox(form, container.NewHBox(layout.NewSpacer(), subBtn, execBtn)), toolWin.w)
	dconf.Resize(fyne.NewSize(400, 600))
	dconf.Show()

}

func (this *appMgo) showConWin() {

	connName := widget.NewEntry()

	address := widget.NewEntry()

	port := widget.NewEntry()

	user := widget.NewEntry()
	password := widget.NewPasswordEntry()

	database := widget.NewEntry()

	form := widget.NewForm(
		widget.NewFormItem("Name", connName),
		widget.NewFormItem("Address", container.NewBorder(nil, nil, nil, port, address)),
		widget.NewFormItem("User", user),
		widget.NewFormItem("Password", password),
		widget.NewFormItem("Database", database),
	)

	if this.conf.MgoDB != nil {
		connName.Text = this.conf.MgoDB.Name
		address.Text = this.conf.MgoDB.Host
		port.Text = cast.ToString(this.conf.MgoDB.Port)
		user.Text = this.conf.MgoDB.User
		password.Text = this.conf.MgoDB.Password
		database.Text = this.conf.MgoDB.Database
	}
	form.OnSubmit = func() {
		this.conf.MgoDB = &os_storage.MgoDB{
			Name:     connName.Text,
			Host:     address.Text,
			Port:     cast.ToInt32(port.Text),
			User:     user.Text,
			Password: password.Text,
			Database: database.Text,
		}

		if connName.Text == "" || address.Text == "" || port.Text == "" {
			common.ShowTip("请填写完整")
			return
		}
		if err := this.storage.StoreConfig(this.conf); err != nil {
			logrus.Error(err)
			return
		}
		dialog.ShowInformation("提示", "保存成功", toolWin.w)
	}
	form.SubmitText = "保存"

	dconf := dialog.NewCustom("设置链接", "关闭", form, toolWin.w)
	dconf.Resize(fyne.NewSize(400, 200))
	dconf.Show()
}

func (a *appMgo) GetAppName() string {
	return common.TOOLBAR_MGODB
}
func (a *appMgo) Icon() fyne.Resource {
	return mytheme.ResourceMongodbJpg
}
