package mysql

import (
	"database/sql"
	"errors"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/gookit/goutil/strutil"
	"github.com/mitchellh/mapstructure"
	"matrix-common/pkg/logger"
	"matrix-middle-service/internel/controller/record/location/dto"
	database2 "matrix-middle-service/pkg/config/database"
	"matrix-middle-service/pkg/database"
	"matrix-middle-service/pkg/database/driver/mysql/conf"
	"matrix-middle-service/pkg/database/model"
	fib "matrix-middle-service/pkg/utils/fiber"
	"strings"
	"time"
	"xorm.io/xorm"
)

var dbEngine *xorm.EngineGroup
var dbInst *db

func init() {
	// 初始化数据源
	fib.Exec(func() {
		logger.Log().Debug("添加 mysql 数据源支持")
	})

	database.Register("mysql", func(c database2.DataSourcesType[any]) database.DataBase {
		mc := &conf.Config{}
		_ = mapstructure.Decode(c.Config, &mc)

		if dbEngine != nil {
			_ = dbEngine.Close()
		}

		logger.Log().Debug("[mysql] 数据源初始化")
		var err error
		dbEngine, err = xorm.NewEngineGroup("mysql", mc.DataSources)
		if err != nil {
			logger.Log().Fatal(err)
		}
		dbEngine.TZLocation, _ = time.LoadLocation("Asia/Shanghai") // 本程序时区设置为上海
		dbEngine.DatabaseTZ, _ = time.LoadLocation("Asia/Shanghai") // 数据库时区设置为上海

		dbInst = &db{
			db:     dbEngine,
			config: mc,
		}

		return dbInst
	})
}

type db struct {
	db     *xorm.EngineGroup
	config *conf.Config
}

func (d *db) GetLocationRecord(record *dto.GetDto) ([]*model.LocationRecord, error) {
	list := make([]*model.LocationRecord, 0)

	db := d.db.Where("1=1")

	if record.StartTime != nil {
		db.And("location_time >= ?", record.StartTime.String())
	}
	if record.EndTime != nil {
		db.And("location_time <= ?", record.EndTime.String())
	}
	err := db.Find(&list)

	if err != nil {
		return nil, err
	}
	return list, nil
}

func (d *db) RecordLocation(record *model.LocationRecord) error {
	_, err := d.db.Insert(record)
	return err
}

func (d *db) DeleteBotTypeById(id string) error {
	if strutil.IsBlank(id) {
		return errors.New(fmt.Sprintf("id 不能为空"))
	}

	exist, err := d.db.Exist(&model.BotType{Id: id})
	if err != nil {
		return err
	}
	if !exist {
		return errors.New(fmt.Sprintf("类型id %s 不存在", id))
	}

	_, err = d.db.Limit(1).Delete(&model.BotType{Id: id})
	return err
}

func (d *db) AddBotType(bt *model.BotType) error {
	if strutil.IsBlank(bt.Id) {
		return errors.New(fmt.Sprintf("id 不能为空"))
	}

	if strutil.IsBlank(bt.Name) {
		return errors.New(fmt.Sprintf("类型名称 不能为空"))
	}

	exist, err := d.db.Exist(&model.BotType{Name: bt.Name})
	if err != nil {
		return err
	}
	if exist {
		return errors.New(fmt.Sprintf("类型 %s 已存在", bt.Name))
	}

	_, err = d.db.UseBool("active").Insert(bt)
	return err
}

func (d *db) GetAllBotTypes() ([]*model.BotType, error) {
	list := make([]*model.BotType, 0)
	err := d.db.Find(&list)
	return list, err
}

func (d *db) Close() error {
	logger.Log().Debug("[mysql] 关闭数据库连接")
	return d.db.Close()
}

func (d *db) Open() (err error) {
	logger.Log().Debug("[mysql] 连接数据库")
	// 自动创建数据库
	for _, dsn := range d.config.DataSources {
		dbName := ParseSqlConnDBName(dsn)
		conn, err := sql.Open("mysql", strings.Split(dsn, "/")[0]+"/information_schema?charset=utf8mb4")
		_, err = conn.Query(fmt.Sprintf("Create Database If Not Exists %s Character Set utf8mb4;", dbName))
		if err != nil {
			logger.Log().Fatal(err)
		}
	}

	err = d.db.Ping()
	if err != nil {
		logger.Log().Fatalf("[mysql] 数据库连接失败, %s", err)
	}
	logger.Log().Debug("[mysql] 数据库 连接成功")

	err = d.db.Sync2(
		&model.QQBot{},
		&model.WebHook{},
		&model.BotType{},
		&model.BotAccess{},
		&model.LocationRecord{})

	if err != nil {
		logger.Log().Fatal(err)
	}
	logger.Log().Debug("[mysql] 数据表 同步成功")
	return
}
